Merge branch 'master' into 745-captcha-login-message
This commit is contained in:
@@ -5,44 +5,45 @@ import ch.jalu.injector.InjectorBuilder;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import fr.xephi.authme.api.API;
|
||||
import fr.xephi.authme.api.NewAPI;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.command.CommandHandler;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.initialization.DataFolder;
|
||||
import fr.xephi.authme.initialization.Initializer;
|
||||
import fr.xephi.authme.initialization.MetricsManager;
|
||||
import fr.xephi.authme.initialization.DataSourceProvider;
|
||||
import fr.xephi.authme.initialization.OnShutdownPlayerSaver;
|
||||
import fr.xephi.authme.initialization.OnStartupTasks;
|
||||
import fr.xephi.authme.initialization.SettingsProvider;
|
||||
import fr.xephi.authme.initialization.TaskCloser;
|
||||
import fr.xephi.authme.listener.BlockListener;
|
||||
import fr.xephi.authme.listener.EntityListener;
|
||||
import fr.xephi.authme.listener.PlayerListener;
|
||||
import fr.xephi.authme.listener.PlayerListener111;
|
||||
import fr.xephi.authme.listener.PlayerListener16;
|
||||
import fr.xephi.authme.listener.PlayerListener18;
|
||||
import fr.xephi.authme.listener.PlayerListener19;
|
||||
import fr.xephi.authme.listener.ServerListener;
|
||||
import fr.xephi.authme.message.Messages;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import fr.xephi.authme.permission.PermissionsSystemType;
|
||||
import fr.xephi.authme.security.crypts.SHA256;
|
||||
import fr.xephi.authme.service.BackupService;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.GeoIpService;
|
||||
import fr.xephi.authme.service.MigrationService;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
import fr.xephi.authme.task.CleanupTask;
|
||||
import fr.xephi.authme.task.purge.PurgeService;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.MigrationService;
|
||||
import fr.xephi.authme.util.PlayerUtils;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.PluginLoader;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.plugin.java.JavaPluginLoader;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
|
||||
import java.io.File;
|
||||
@@ -60,7 +61,7 @@ public class AuthMe extends JavaPlugin {
|
||||
private static final String LOG_FILENAME = "authme.log";
|
||||
private static final int CLEANUP_INTERVAL = 5 * TICKS_PER_MINUTE;
|
||||
|
||||
// Default version and build number values;
|
||||
// Default version and build number values
|
||||
private static String pluginVersion = "N/D";
|
||||
private static String pluginBuildNumber = "Unknown";
|
||||
|
||||
@@ -68,7 +69,6 @@ public class AuthMe extends JavaPlugin {
|
||||
private CommandHandler commandHandler;
|
||||
private PermissionsManager permsMan;
|
||||
private Settings settings;
|
||||
private Messages messages;
|
||||
private DataSource database;
|
||||
private BukkitService bukkitService;
|
||||
private Injector injector;
|
||||
@@ -86,9 +86,8 @@ public class AuthMe extends JavaPlugin {
|
||||
*/
|
||||
@VisibleForTesting
|
||||
@SuppressWarnings("deprecation") // the super constructor is deprecated to mark it for unit testing only
|
||||
protected AuthMe(final PluginLoader loader, final Server server, final PluginDescriptionFile description,
|
||||
final File dataFolder, final File file) {
|
||||
super(loader, server, description, dataFolder, file);
|
||||
protected AuthMe(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file) {
|
||||
super(loader, description, dataFolder, file);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,7 +132,7 @@ public class AuthMe extends JavaPlugin {
|
||||
@Override
|
||||
public void onEnable() {
|
||||
// Load the plugin version data from the plugin description file
|
||||
loadPluginInfo();
|
||||
loadPluginInfo(getDescription().getVersion());
|
||||
|
||||
// Initialize the plugin
|
||||
try {
|
||||
@@ -156,7 +155,7 @@ public class AuthMe extends JavaPlugin {
|
||||
new BackupService(this, settings).doBackup(BackupService.BackupCause.START);
|
||||
|
||||
// Set up Metrics
|
||||
MetricsManager.sendMetrics(this, settings);
|
||||
OnStartupTasks.sendMetrics(this, settings);
|
||||
|
||||
// Sponsor messages
|
||||
ConsoleLogger.info("Development builds are available on our jenkins, thanks to f14stelt.");
|
||||
@@ -176,9 +175,10 @@ public class AuthMe extends JavaPlugin {
|
||||
|
||||
/**
|
||||
* Load the version and build number of the plugin from the description file.
|
||||
*
|
||||
* @param versionRaw the version as given by the plugin description file
|
||||
*/
|
||||
private void loadPluginInfo() {
|
||||
String versionRaw = this.getDescription().getVersion();
|
||||
private static void loadPluginInfo(String versionRaw) {
|
||||
int index = versionRaw.lastIndexOf("-");
|
||||
if (index != -1) {
|
||||
pluginVersion = versionRaw.substring(0, index);
|
||||
@@ -191,10 +191,8 @@ public class AuthMe extends JavaPlugin {
|
||||
|
||||
/**
|
||||
* Initialize the plugin and all the services.
|
||||
*
|
||||
* @throws Exception if the initialization fails
|
||||
*/
|
||||
private void initialize() throws Exception {
|
||||
private void initialize() {
|
||||
// Set the Logger instance and log file path
|
||||
ConsoleLogger.setLogger(getLogger());
|
||||
ConsoleLogger.setLogFile(new File(getDataFolder(), LOG_FILENAME));
|
||||
@@ -202,40 +200,30 @@ public class AuthMe extends JavaPlugin {
|
||||
// Create plugin folder
|
||||
getDataFolder().mkdir();
|
||||
|
||||
// Load settings and set up the console and console filter
|
||||
settings = Initializer.createSettings(this);
|
||||
bukkitService = new BukkitService(this, settings);
|
||||
Initializer initializer = new Initializer(this, bukkitService);
|
||||
|
||||
ConsoleLogger.setLoggingOptions(settings);
|
||||
initializer.setupConsoleFilter(settings, getLogger());
|
||||
|
||||
// Connect to the database and set up tables
|
||||
database = initializer.setupDatabase(settings);
|
||||
|
||||
// Convert deprecated PLAINTEXT hash entries
|
||||
MigrationService.changePlainTextToSha256(settings, database, new SHA256());
|
||||
|
||||
// Injector initialization
|
||||
// Create injector, provide elements from the Bukkit environment and register providers
|
||||
injector = new InjectorBuilder().addDefaultHandlers("fr.xephi.authme").create();
|
||||
|
||||
// Register elements of the Bukkit / JavaPlugin environment
|
||||
injector.register(AuthMe.class, this);
|
||||
injector.register(Server.class, getServer());
|
||||
injector.register(PluginManager.class, getServer().getPluginManager());
|
||||
injector.register(BukkitScheduler.class, getServer().getScheduler());
|
||||
injector.provide(DataFolder.class, getDataFolder());
|
||||
injector.registerProvider(Settings.class, SettingsProvider.class);
|
||||
injector.registerProvider(DataSource.class, DataSourceProvider.class);
|
||||
|
||||
// Register elements we instantiate manually
|
||||
injector.register(Settings.class, settings);
|
||||
injector.register(DataSource.class, database);
|
||||
injector.register(BukkitService.class, bukkitService);
|
||||
// Get settings and set up logger
|
||||
settings = injector.getSingleton(Settings.class);
|
||||
ConsoleLogger.setLoggingOptions(settings);
|
||||
OnStartupTasks.setupConsoleFilter(settings, getLogger());
|
||||
|
||||
// Set all service fields on the AuthMe class
|
||||
instantiateServices(injector);
|
||||
|
||||
// Convert deprecated PLAINTEXT hash entries
|
||||
MigrationService.changePlainTextToSha256(settings, database, new SHA256());
|
||||
|
||||
// TODO: does this still make sense? -sgdc3
|
||||
// If the server is empty (fresh start) just set all the players as unlogged
|
||||
if (bukkitService.getOnlinePlayers().size() == 0) {
|
||||
if (bukkitService.getOnlinePlayers().isEmpty()) {
|
||||
database.purgeLogged();
|
||||
}
|
||||
|
||||
@@ -243,7 +231,8 @@ public class AuthMe extends JavaPlugin {
|
||||
registerEventListeners(injector);
|
||||
|
||||
// Start Email recall task if needed
|
||||
initializer.scheduleRecallEmailTask(settings, database, messages);
|
||||
OnStartupTasks onStartupTasks = injector.newInstance(OnStartupTasks.class);
|
||||
onStartupTasks.scheduleRecallEmailTask();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -256,7 +245,7 @@ public class AuthMe extends JavaPlugin {
|
||||
playerCache = PlayerCache.getInstance();
|
||||
injector.register(PlayerCache.class, playerCache);
|
||||
|
||||
messages = injector.getSingleton(Messages.class);
|
||||
database = injector.getSingleton(DataSource.class);
|
||||
permsMan = injector.getSingleton(PermissionsManager.class);
|
||||
bukkitService = injector.getSingleton(BukkitService.class);
|
||||
commandHandler = injector.getSingleton(CommandHandler.class);
|
||||
@@ -312,6 +301,11 @@ public class AuthMe extends JavaPlugin {
|
||||
if (isClassLoaded("org.bukkit.event.player.PlayerSwapHandItemsEvent")) {
|
||||
pluginManager.registerEvents(injector.getSingleton(PlayerListener19.class), this);
|
||||
}
|
||||
|
||||
// Register listener for 1.11 events if available
|
||||
if (isClassLoaded("org.bukkit.event.entity.EntityAirChangeEvent")) {
|
||||
pluginManager.registerEvents(injector.getSingleton(PlayerListener111.class), this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -343,10 +337,7 @@ public class AuthMe extends JavaPlugin {
|
||||
}
|
||||
|
||||
// Wait for tasks and close data source
|
||||
new Thread(
|
||||
new TaskCloser(this, database),
|
||||
"AuthMe-DataSource#close"
|
||||
).start();
|
||||
new TaskCloser(this, database).run();
|
||||
|
||||
// Disabled correctly
|
||||
ConsoleLogger.info("AuthMe " + this.getDescription().getVersion() + " disabled!");
|
||||
|
||||
@@ -19,12 +19,13 @@ import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Deprecated API of AuthMe. Please use {@link NewAPI} instead.
|
||||
*
|
||||
* @deprecated Use {@link NewAPI}
|
||||
*/
|
||||
@Deprecated
|
||||
public class API {
|
||||
|
||||
public static final String newline = System.getProperty("line.separator");
|
||||
public static AuthMe instance;
|
||||
private static AuthMe instance;
|
||||
private static DataSource dataSource;
|
||||
private static PasswordSecurity passwordSecurity;
|
||||
private static Management management;
|
||||
@@ -83,28 +84,17 @@ public class API {
|
||||
}
|
||||
|
||||
public static Location getLastLocation(Player player) {
|
||||
try {
|
||||
PlayerAuth auth = PlayerCache.getInstance().getAuth(player.getName().toLowerCase());
|
||||
PlayerAuth auth = PlayerCache.getInstance().getAuth(player.getName().toLowerCase());
|
||||
|
||||
if (auth != null) {
|
||||
Location loc = new Location(Bukkit.getWorld(auth.getWorld()), auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ());
|
||||
return loc;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
} catch (NullPointerException ex) {
|
||||
return null;
|
||||
if (auth != null) {
|
||||
return new Location(Bukkit.getWorld(auth.getWorld()), auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void setPlayerInventory(Player player, ItemStack[] content,
|
||||
ItemStack[] armor) {
|
||||
try {
|
||||
player.getInventory().setContents(content);
|
||||
player.getInventory().setArmorContents(armor);
|
||||
} catch (NullPointerException ignored) {
|
||||
}
|
||||
public static void setPlayerInventory(Player player, ItemStack[] content, ItemStack[] armor) {
|
||||
player.getInventory().setContents(content);
|
||||
player.getInventory().setArmorContents(armor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,8 +25,8 @@ import java.util.List;
|
||||
*/
|
||||
public class NewAPI {
|
||||
|
||||
public static NewAPI singleton;
|
||||
public final AuthMe plugin;
|
||||
private static NewAPI singleton;
|
||||
private final AuthMe plugin;
|
||||
private final PluginHookService pluginHookService;
|
||||
private final DataSource dataSource;
|
||||
private final PasswordSecurity passwordSecurity;
|
||||
|
||||
@@ -87,10 +87,10 @@ public class CommandMapper {
|
||||
return classes;
|
||||
}
|
||||
|
||||
private FoundCommandResult getCommandWithSmallestDifference(CommandDescription base, List<String> parts) {
|
||||
private static FoundCommandResult getCommandWithSmallestDifference(CommandDescription base, List<String> parts) {
|
||||
// Return the base command with incorrect arg count error if we only have one part
|
||||
if (parts.size() <= 1) {
|
||||
return new FoundCommandResult(base, parts, new ArrayList<String>(), 0.0, INCORRECT_ARGUMENTS);
|
||||
return new FoundCommandResult(base, parts, new ArrayList<>(), 0.0, INCORRECT_ARGUMENTS);
|
||||
}
|
||||
|
||||
final String childLabel = parts.get(1);
|
||||
@@ -115,7 +115,7 @@ public class CommandMapper {
|
||||
final int partsSize = parts.size();
|
||||
List<String> labels = parts.subList(0, Math.min(closestCommand.getLabelCount(), partsSize));
|
||||
List<String> arguments = (labels.size() == partsSize)
|
||||
? new ArrayList<String>()
|
||||
? new ArrayList<>()
|
||||
: parts.subList(labels.size(), partsSize);
|
||||
|
||||
return new FoundCommandResult(closestCommand, labels, arguments, minDifference, status);
|
||||
@@ -141,7 +141,7 @@ public class CommandMapper {
|
||||
*
|
||||
* @return A command if there was a complete match (including proper argument count), null otherwise
|
||||
*/
|
||||
private CommandDescription getSuitableChild(CommandDescription baseCommand, List<String> parts) {
|
||||
private static CommandDescription getSuitableChild(CommandDescription baseCommand, List<String> parts) {
|
||||
if (CollectionUtils.isEmpty(parts)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
package fr.xephi.authme.command;
|
||||
|
||||
import com.github.authme.configme.properties.Property;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.message.Messages;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Service for implementations of {@link ExecutableCommand} to execute some common tasks.
|
||||
* This service basically wraps calls, forwarding them to other classes.
|
||||
*/
|
||||
public class CommandService {
|
||||
|
||||
@Inject
|
||||
private Messages messages;
|
||||
@Inject
|
||||
private Settings settings;
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
/**
|
||||
* Send a message to a player.
|
||||
*
|
||||
* @param sender The command sender to send the message to
|
||||
* @param messageKey The message key to send
|
||||
*/
|
||||
public void send(CommandSender sender, MessageKey messageKey) {
|
||||
messages.send(sender, messageKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to a player.
|
||||
*
|
||||
* @param sender The command sender to send the message to
|
||||
* @param messageKey The message key to send
|
||||
* @param replacements The replacement arguments for the message key's tags
|
||||
*/
|
||||
public void send(CommandSender sender, MessageKey messageKey, String... replacements) {
|
||||
messages.send(sender, messageKey, replacements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a message by its message key.
|
||||
*
|
||||
* @param key The message to retrieve
|
||||
* @return The message
|
||||
*/
|
||||
public String[] retrieveMessage(MessageKey key) {
|
||||
return messages.retrieve(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a message as a single String by its message key.
|
||||
*
|
||||
* @param key The message to retrieve
|
||||
* @return The message
|
||||
*/
|
||||
public String retrieveSingle(MessageKey key) {
|
||||
return messages.retrieveSingle(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the given property's value.
|
||||
*
|
||||
* @param property The property to retrieve
|
||||
* @param <T> The type of the property
|
||||
* @return The property's value
|
||||
*/
|
||||
public <T> T getProperty(Property<T> property) {
|
||||
return settings.getProperty(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the settings manager.
|
||||
*
|
||||
* @return The settings manager
|
||||
*/
|
||||
public Settings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
public boolean validateEmail(String email) {
|
||||
return validationService.validateEmail(email);
|
||||
}
|
||||
|
||||
public boolean isEmailFreeForRegistration(String email, CommandSender sender) {
|
||||
return validationService.isEmailFreeForRegistration(email, sender);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -23,7 +23,7 @@ public class AccountsCommand implements ExecutableCommand {
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private CommandService commandService;
|
||||
private CommonService commonService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(final CommandSender sender, List<String> arguments) {
|
||||
@@ -50,13 +50,13 @@ public class AccountsCommand implements ExecutableCommand {
|
||||
public void run() {
|
||||
PlayerAuth auth = dataSource.getAuth(playerName.toLowerCase());
|
||||
if (auth == null) {
|
||||
commandService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> accountList = dataSource.getAllAuthsByIp(auth.getIp());
|
||||
if (accountList.isEmpty()) {
|
||||
commandService.send(sender, MessageKey.USER_NOT_REGISTERED);
|
||||
commonService.send(sender, MessageKey.USER_NOT_REGISTERED);
|
||||
} else if (accountList.size() == 1) {
|
||||
sender.sendMessage("[AuthMe] " + playerName + " is a single account player");
|
||||
} else {
|
||||
|
||||
+35
-28
@@ -1,15 +1,15 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.security.PasswordSecurity;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.service.ValidationService.ValidationResult;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -38,7 +38,7 @@ public class ChangePasswordAdminCommand implements ExecutableCommand {
|
||||
private ValidationService validationService;
|
||||
|
||||
@Inject
|
||||
private CommandService commandService;
|
||||
private CommonService commonService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(final CommandSender sender, List<String> arguments) {
|
||||
@@ -49,38 +49,45 @@ public class ChangePasswordAdminCommand implements ExecutableCommand {
|
||||
// Validate the password
|
||||
ValidationResult validationResult = validationService.validatePassword(playerPass, playerName);
|
||||
if (validationResult.hasError()) {
|
||||
commandService.send(sender, validationResult.getMessageKey(), validationResult.getArgs());
|
||||
commonService.send(sender, validationResult.getMessageKey(), validationResult.getArgs());
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the password
|
||||
final String playerNameLowerCase = playerName.toLowerCase();
|
||||
bukkitService.runTaskOptionallyAsync(new Runnable() {
|
||||
bukkitService.runTaskOptionallyAsync(() -> changePassword(playerName.toLowerCase(), playerPass, sender));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
PlayerAuth auth = null;
|
||||
if (playerCache.isAuthenticated(playerNameLowerCase)) {
|
||||
auth = playerCache.getAuth(playerNameLowerCase);
|
||||
} else if (dataSource.isAuthAvailable(playerNameLowerCase)) {
|
||||
auth = dataSource.getAuth(playerNameLowerCase);
|
||||
}
|
||||
if (auth == null) {
|
||||
commandService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Changes the password of the given player to the given password.
|
||||
*
|
||||
* @param nameLowercase the name of the player
|
||||
* @param password the password to set
|
||||
* @param sender the sender initiating the password change
|
||||
*/
|
||||
private void changePassword(String nameLowercase, String password, CommandSender sender) {
|
||||
PlayerAuth auth = getAuth(nameLowercase);
|
||||
if (auth == null) {
|
||||
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
return;
|
||||
}
|
||||
|
||||
HashedPassword hashedPassword = passwordSecurity.computeHash(playerPass, playerNameLowerCase);
|
||||
auth.setPassword(hashedPassword);
|
||||
HashedPassword hashedPassword = passwordSecurity.computeHash(password, nameLowercase);
|
||||
auth.setPassword(hashedPassword);
|
||||
|
||||
if (dataSource.updatePassword(auth)) {
|
||||
commandService.send(sender, MessageKey.PASSWORD_CHANGED_SUCCESS);
|
||||
ConsoleLogger.info(sender.getName() + " changed password of " + playerNameLowerCase);
|
||||
} else {
|
||||
commandService.send(sender, MessageKey.ERROR);
|
||||
}
|
||||
}
|
||||
if (dataSource.updatePassword(auth)) {
|
||||
commonService.send(sender, MessageKey.PASSWORD_CHANGED_SUCCESS);
|
||||
ConsoleLogger.info(sender.getName() + " changed password of " + nameLowercase);
|
||||
} else {
|
||||
commonService.send(sender, MessageKey.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
private PlayerAuth getAuth(String nameLowercase) {
|
||||
if (playerCache.isAuthenticated(nameLowercase)) {
|
||||
return playerCache.getAuth(nameLowercase);
|
||||
} else if (dataSource.isAuthAvailable(nameLowercase)) {
|
||||
return dataSource.getAuth(nameLowercase);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import ch.jalu.injector.Injector;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.datasource.converter.Converter;
|
||||
import fr.xephi.authme.datasource.converter.CrazyLoginConverter;
|
||||
@@ -16,6 +15,7 @@ import fr.xephi.authme.datasource.converter.vAuthConverter;
|
||||
import fr.xephi.authme.datasource.converter.xAuthConverter;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -31,7 +31,7 @@ public class ConverterCommand implements ExecutableCommand {
|
||||
static final Map<String, Class<? extends Converter>> CONVERTERS = getConverters();
|
||||
|
||||
@Inject
|
||||
private CommandService commandService;
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
@@ -61,7 +61,7 @@ public class ConverterCommand implements ExecutableCommand {
|
||||
try {
|
||||
converter.execute(sender);
|
||||
} catch (Exception e) {
|
||||
commandService.send(sender, MessageKey.ERROR);
|
||||
commonService.send(sender, MessageKey.ERROR);
|
||||
ConsoleLogger.logException("Error during conversion:", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -19,7 +19,7 @@ public class GetEmailCommand implements ExecutableCommand {
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private CommandService commandService;
|
||||
private CommonService commonService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
@@ -27,7 +27,7 @@ public class GetEmailCommand implements ExecutableCommand {
|
||||
|
||||
PlayerAuth auth = dataSource.getAuth(playerName);
|
||||
if (auth == null) {
|
||||
commandService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
} else {
|
||||
sender.sendMessage("[AuthMe] " + playerName + "'s email: " + auth.getEmail());
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -20,16 +20,16 @@ public class LastLoginCommand implements ExecutableCommand {
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private CommandService commandService;
|
||||
private CommonService commonService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
// Get the player
|
||||
String playerName = (arguments.size() >= 1) ? arguments.get(0) : sender.getName();
|
||||
String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0);
|
||||
|
||||
PlayerAuth auth = dataSource.getAuth(playerName);
|
||||
if (auth == null) {
|
||||
commandService.send(sender, MessageKey.USER_NOT_REGISTERED);
|
||||
commonService.send(sender, MessageKey.USER_NOT_REGISTERED);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -19,7 +19,7 @@ public class PurgeLastPositionCommand implements ExecutableCommand {
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private CommandService commandService;
|
||||
private CommonService commonService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(final CommandSender sender, List<String> arguments) {
|
||||
@@ -35,7 +35,7 @@ public class PurgeLastPositionCommand implements ExecutableCommand {
|
||||
// Get the user auth and make sure the user exists
|
||||
PlayerAuth auth = dataSource.getAuth(playerName);
|
||||
if (auth == null) {
|
||||
commandService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@ package fr.xephi.authme.command.executable.authme;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.limbo.LimboCache;
|
||||
import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.security.PasswordSecurity;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.service.ValidationService.ValidationResult;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -27,7 +27,7 @@ public class RegisterAdminCommand implements ExecutableCommand {
|
||||
private PasswordSecurity passwordSecurity;
|
||||
|
||||
@Inject
|
||||
private CommandService commandService;
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
@@ -51,7 +51,7 @@ public class RegisterAdminCommand implements ExecutableCommand {
|
||||
// Command logic
|
||||
ValidationResult passwordValidation = validationService.validatePassword(playerPass, playerName);
|
||||
if (passwordValidation.hasError()) {
|
||||
commandService.send(sender, passwordValidation.getMessageKey(), passwordValidation.getArgs());
|
||||
commonService.send(sender, passwordValidation.getMessageKey(), passwordValidation.getArgs());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public class RegisterAdminCommand implements ExecutableCommand {
|
||||
@Override
|
||||
public void run() {
|
||||
if (dataSource.isAuthAvailable(playerNameLowerCase)) {
|
||||
commandService.send(sender, MessageKey.NAME_ALREADY_REGISTERED);
|
||||
commonService.send(sender, MessageKey.NAME_ALREADY_REGISTERED);
|
||||
return;
|
||||
}
|
||||
HashedPassword hashedPassword = passwordSecurity.computeHash(playerPass, playerNameLowerCase);
|
||||
@@ -71,12 +71,12 @@ public class RegisterAdminCommand implements ExecutableCommand {
|
||||
.build();
|
||||
|
||||
if (!dataSource.saveAuth(auth)) {
|
||||
commandService.send(sender, MessageKey.ERROR);
|
||||
commonService.send(sender, MessageKey.ERROR);
|
||||
return;
|
||||
}
|
||||
dataSource.setUnlogged(playerNameLowerCase);
|
||||
|
||||
commandService.send(sender, MessageKey.REGISTER_SUCCESS);
|
||||
commonService.send(sender, MessageKey.REGISTER_SUCCESS);
|
||||
ConsoleLogger.info(sender.getName() + " registered " + playerName);
|
||||
final Player player = bukkitService.getPlayerExact(playerName);
|
||||
if (player != null) {
|
||||
@@ -84,7 +84,7 @@ public class RegisterAdminCommand implements ExecutableCommand {
|
||||
@Override
|
||||
public void run() {
|
||||
limboCache.restoreData(player);
|
||||
player.kickPlayer(commandService.retrieveSingle(MessageKey.KICK_FOR_ADMIN_REGISTER));
|
||||
player.kickPlayer(commonService.retrieveSingleMessage(MessageKey.KICK_FOR_ADMIN_REGISTER));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ package fr.xephi.authme.command.executable.authme;
|
||||
import ch.jalu.injector.Injector;
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.initialization.Reloadable;
|
||||
import fr.xephi.authme.initialization.SettingsDependent;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -35,7 +35,7 @@ public class ReloadCommand implements ExecutableCommand {
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private CommandService commandService;
|
||||
private CommonService commonService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
@@ -48,7 +48,7 @@ public class ReloadCommand implements ExecutableCommand {
|
||||
sender.sendMessage("Note: cannot change database type during /authme reload");
|
||||
}
|
||||
performReloadOnServices();
|
||||
commandService.send(sender, MessageKey.CONFIG_RELOAD_SUCCESS);
|
||||
commonService.send(sender, MessageKey.CONFIG_RELOAD_SUCCESS);
|
||||
} catch (Exception e) {
|
||||
sender.sendMessage("Error occurred during reload of AuthMe: aborting");
|
||||
ConsoleLogger.logException("Aborting! Encountered exception during reload of AuthMe:", e);
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -21,7 +22,7 @@ public class SetEmailCommand implements ExecutableCommand {
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private CommandService commandService;
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
@@ -29,6 +30,9 @@ public class SetEmailCommand implements ExecutableCommand {
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(final CommandSender sender, List<String> arguments) {
|
||||
// Get the player name and email address
|
||||
@@ -36,8 +40,8 @@ public class SetEmailCommand implements ExecutableCommand {
|
||||
final String playerEmail = arguments.get(1);
|
||||
|
||||
// Validate the email address
|
||||
if (!commandService.validateEmail(playerEmail)) {
|
||||
commandService.send(sender, MessageKey.INVALID_EMAIL);
|
||||
if (!validationService.validateEmail(playerEmail)) {
|
||||
commonService.send(sender, MessageKey.INVALID_EMAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -47,17 +51,17 @@ public class SetEmailCommand implements ExecutableCommand {
|
||||
// Validate the user
|
||||
PlayerAuth auth = dataSource.getAuth(playerName);
|
||||
if (auth == null) {
|
||||
commandService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
return;
|
||||
} else if (!commandService.isEmailFreeForRegistration(playerEmail, sender)) {
|
||||
commandService.send(sender, MessageKey.EMAIL_ALREADY_USED_ERROR);
|
||||
} else if (!validationService.isEmailFreeForRegistration(playerEmail, sender)) {
|
||||
commonService.send(sender, MessageKey.EMAIL_ALREADY_USED_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the email address
|
||||
auth.setEmail(playerEmail);
|
||||
if (!dataSource.updateEmail(auth)) {
|
||||
commandService.send(sender, MessageKey.ERROR);
|
||||
commonService.send(sender, MessageKey.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -67,7 +71,7 @@ public class SetEmailCommand implements ExecutableCommand {
|
||||
}
|
||||
|
||||
// Show a status message
|
||||
commandService.send(sender, MessageKey.EMAIL_CHANGED_SUCCESS);
|
||||
commonService.send(sender, MessageKey.EMAIL_CHANGED_SUCCESS);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -21,7 +21,7 @@ public class UnregisterAdminCommand implements ExecutableCommand {
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private CommandService commandService;
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
@@ -38,7 +38,7 @@ public class UnregisterAdminCommand implements ExecutableCommand {
|
||||
|
||||
// Make sure the user exists
|
||||
if (!dataSource.isAuthAvailable(playerName)) {
|
||||
commandService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package fr.xephi.authme.command.executable.captcha;
|
||||
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.data.CaptchaManager;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.data.limbo.LimboCache;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -20,7 +22,7 @@ public class CaptchaCommand extends PlayerCommand {
|
||||
private CaptchaManager captchaManager;
|
||||
|
||||
@Inject
|
||||
private CommandService commandService;
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private LimboCache limboCache;
|
||||
@@ -30,9 +32,9 @@ public class CaptchaCommand extends PlayerCommand {
|
||||
final String playerName = player.getName().toLowerCase();
|
||||
|
||||
if (playerCache.isAuthenticated(playerName)) {
|
||||
commandService.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
||||
commonService.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
||||
} else if (!captchaManager.isCaptchaRequired(playerName)) {
|
||||
commandService.send(player, MessageKey.USAGE_LOGIN);
|
||||
commonService.send(player, MessageKey.USAGE_LOGIN);
|
||||
} else {
|
||||
checkCaptcha(player, arguments.get(0));
|
||||
}
|
||||
@@ -46,7 +48,7 @@ public class CaptchaCommand extends PlayerCommand {
|
||||
limboCache.getPlayerData(player.getName()).getMessageTask().setMuted(false);
|
||||
} else {
|
||||
String newCode = captchaManager.generateCode(player.getName());
|
||||
commandService.send(player, MessageKey.CAPTCHA_WRONG_ERROR, newCode);
|
||||
commonService.send(player, MessageKey.CAPTCHA_WRONG_ERROR, newCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,10 +1,10 @@
|
||||
package fr.xephi.authme.command.executable.changepassword;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.service.ValidationService.ValidationResult;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -18,7 +18,7 @@ import java.util.List;
|
||||
public class ChangePasswordCommand extends PlayerCommand {
|
||||
|
||||
@Inject
|
||||
private CommandService commandService;
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
@@ -36,14 +36,14 @@ public class ChangePasswordCommand extends PlayerCommand {
|
||||
|
||||
String name = player.getName().toLowerCase();
|
||||
if (!playerCache.isAuthenticated(name)) {
|
||||
commandService.send(player, MessageKey.NOT_LOGGED_IN);
|
||||
commonService.send(player, MessageKey.NOT_LOGGED_IN);
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure the password is allowed
|
||||
ValidationResult passwordValidation = validationService.validatePassword(newPassword, name);
|
||||
if (passwordValidation.hasError()) {
|
||||
commandService.send(player, passwordValidation.getMessageKey(), passwordValidation.getArgs());
|
||||
commonService.send(player, passwordValidation.getMessageKey(), passwordValidation.getArgs());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package fr.xephi.authme.command.executable.email;
|
||||
|
||||
import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -18,7 +18,7 @@ public class AddEmailCommand extends PlayerCommand {
|
||||
private Management management;
|
||||
|
||||
@Inject
|
||||
private CommandService commandService;
|
||||
private CommonService commonService;
|
||||
|
||||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
@@ -29,7 +29,7 @@ public class AddEmailCommand extends PlayerCommand {
|
||||
// Closer inspection of the mail address handled by the async task
|
||||
management.performAddEmail(player, email);
|
||||
} else {
|
||||
commandService.send(player, MessageKey.CONFIRM_EMAIL_MESSAGE);
|
||||
commonService.send(player, MessageKey.CONFIRM_EMAIL_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
package fr.xephi.authme.command.executable.email;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.mail.SendMailSSL;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.security.PasswordSecurity;
|
||||
import fr.xephi.authme.util.RandomStringUtils;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.RecoveryCodeService;
|
||||
import fr.xephi.authme.util.RandomStringUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -28,7 +28,7 @@ public class RecoverEmailCommand extends PlayerCommand {
|
||||
private PasswordSecurity passwordSecurity;
|
||||
|
||||
@Inject
|
||||
private CommandService commandService;
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
@@ -49,23 +49,23 @@ public class RecoverEmailCommand extends PlayerCommand {
|
||||
|
||||
if (!sendMailSsl.hasAllInformation()) {
|
||||
ConsoleLogger.warning("Mail API is not set");
|
||||
commandService.send(player, MessageKey.INCOMPLETE_EMAIL_SETTINGS);
|
||||
commonService.send(player, MessageKey.INCOMPLETE_EMAIL_SETTINGS);
|
||||
return;
|
||||
}
|
||||
if (playerCache.isAuthenticated(playerName)) {
|
||||
commandService.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
||||
commonService.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerAuth auth = dataSource.getAuth(playerName); // TODO: Create method to get email only
|
||||
if (auth == null) {
|
||||
commandService.send(player, MessageKey.REGISTER_EMAIL_MESSAGE);
|
||||
commonService.send(player, MessageKey.REGISTER_EMAIL_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
final String email = auth.getEmail();
|
||||
if (email == null || !email.equalsIgnoreCase(playerMail) || "your@email.com".equalsIgnoreCase(email)) {
|
||||
commandService.send(player, MessageKey.INVALID_EMAIL);
|
||||
commonService.send(player, MessageKey.INVALID_EMAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -84,28 +84,35 @@ public class RecoverEmailCommand extends PlayerCommand {
|
||||
|
||||
private void createAndSendRecoveryCode(Player player, String email) {
|
||||
String recoveryCode = recoveryCodeService.generateCode(player.getName());
|
||||
sendMailSsl.sendRecoveryCode(player.getName(), email, recoveryCode);
|
||||
commandService.send(player, MessageKey.RECOVERY_CODE_SENT);
|
||||
boolean couldSendMail = sendMailSsl.sendRecoveryCode(player.getName(), email, recoveryCode);
|
||||
if (couldSendMail) {
|
||||
commonService.send(player, MessageKey.RECOVERY_CODE_SENT);
|
||||
} else {
|
||||
commonService.send(player, MessageKey.EMAIL_SEND_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
private void processRecoveryCode(Player player, String code, String email) {
|
||||
final String name = player.getName();
|
||||
if (!recoveryCodeService.isCodeValid(name, code)) {
|
||||
commandService.send(player, MessageKey.INCORRECT_RECOVERY_CODE);
|
||||
return;
|
||||
if (recoveryCodeService.isCodeValid(name, code)) {
|
||||
generateAndSendNewPassword(player, email);
|
||||
recoveryCodeService.removeCode(name);
|
||||
} else {
|
||||
commonService.send(player, MessageKey.INCORRECT_RECOVERY_CODE);
|
||||
}
|
||||
|
||||
generateAndSendNewPassword(player, email);
|
||||
recoveryCodeService.removeCode(name);
|
||||
}
|
||||
|
||||
private void generateAndSendNewPassword(Player player, String email) {
|
||||
String name = player.getName();
|
||||
String thePass = RandomStringUtils.generate(commandService.getProperty(RECOVERY_PASSWORD_LENGTH));
|
||||
String thePass = RandomStringUtils.generate(commonService.getProperty(RECOVERY_PASSWORD_LENGTH));
|
||||
HashedPassword hashNew = passwordSecurity.computeHash(thePass, name);
|
||||
|
||||
dataSource.updatePassword(name, hashNew);
|
||||
sendMailSsl.sendPasswordMail(name, email, thePass);
|
||||
commandService.send(player, MessageKey.RECOVERY_EMAIL_SENT_MESSAGE);
|
||||
boolean couldSendMail = sendMailSsl.sendPasswordMail(name, email, thePass);
|
||||
if (couldSendMail) {
|
||||
commonService.send(player, MessageKey.RECOVERY_EMAIL_SENT_MESSAGE);
|
||||
} else {
|
||||
commonService.send(player, MessageKey.EMAIL_SEND_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package fr.xephi.authme.command.executable.email;
|
||||
|
||||
import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -14,8 +14,9 @@ import java.util.List;
|
||||
* Show email command.
|
||||
*/
|
||||
public class ShowEmailCommand extends PlayerCommand {
|
||||
|
||||
@Inject
|
||||
private CommandService commandService;
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
@@ -23,10 +24,10 @@ public class ShowEmailCommand extends PlayerCommand {
|
||||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
PlayerAuth auth = playerCache.getAuth(player.getName());
|
||||
if (auth.getEmail() != null && !auth.getEmail().equalsIgnoreCase("your@email.com")) {
|
||||
commandService.send(player, MessageKey.EMAIL_SHOW, auth.getEmail());
|
||||
if (auth.getEmail() != null && !"your@email.com".equalsIgnoreCase(auth.getEmail())) {
|
||||
commonService.send(player, MessageKey.EMAIL_SHOW, auth.getEmail());
|
||||
} else {
|
||||
commandService.send(player, MessageKey.SHOW_NO_EMAIL);
|
||||
commonService.send(player, MessageKey.SHOW_NO_EMAIL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
package fr.xephi.authme.command.executable.register;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.mail.SendMailSSL;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import fr.xephi.authme.security.HashAlgorithm;
|
||||
import fr.xephi.authme.util.RandomStringUtils;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
import fr.xephi.authme.util.RandomStringUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -20,20 +21,26 @@ import static fr.xephi.authme.settings.properties.RegistrationSettings.ENABLE_CO
|
||||
import static fr.xephi.authme.settings.properties.RegistrationSettings.USE_EMAIL_REGISTRATION;
|
||||
import static fr.xephi.authme.settings.properties.RestrictionSettings.ENABLE_PASSWORD_CONFIRMATION;
|
||||
|
||||
/**
|
||||
* Command for /register.
|
||||
*/
|
||||
public class RegisterCommand extends PlayerCommand {
|
||||
|
||||
@Inject
|
||||
private Management management;
|
||||
|
||||
@Inject
|
||||
private CommandService commandService;
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private SendMailSSL sendMailSsl;
|
||||
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
if (commandService.getProperty(SecuritySettings.PASSWORD_HASH) == HashAlgorithm.TWO_FACTOR) {
|
||||
if (commonService.getProperty(SecuritySettings.PASSWORD_HASH) == HashAlgorithm.TWO_FACTOR) {
|
||||
//for two factor auth we don't need to check the usage
|
||||
management.performRegister(player, "", "", true);
|
||||
return;
|
||||
@@ -42,11 +49,11 @@ public class RegisterCommand extends PlayerCommand {
|
||||
// Ensure that there is 1 argument, or 2 if confirmation is required
|
||||
final boolean useConfirmation = isConfirmationRequired();
|
||||
if (arguments.isEmpty() || useConfirmation && arguments.size() < 2) {
|
||||
commandService.send(player, MessageKey.USAGE_REGISTER);
|
||||
commonService.send(player, MessageKey.USAGE_REGISTER);
|
||||
return;
|
||||
}
|
||||
|
||||
if (commandService.getProperty(USE_EMAIL_REGISTRATION)) {
|
||||
if (commonService.getProperty(USE_EMAIL_REGISTRATION)) {
|
||||
handleEmailRegistration(player, arguments);
|
||||
} else {
|
||||
handlePasswordRegistration(player, arguments);
|
||||
@@ -59,8 +66,8 @@ public class RegisterCommand extends PlayerCommand {
|
||||
}
|
||||
|
||||
private void handlePasswordRegistration(Player player, List<String> arguments) {
|
||||
if (commandService.getProperty(ENABLE_PASSWORD_CONFIRMATION) && !arguments.get(0).equals(arguments.get(1))) {
|
||||
commandService.send(player, MessageKey.PASSWORD_MATCH_ERROR);
|
||||
if (commonService.getProperty(ENABLE_PASSWORD_CONFIRMATION) && !arguments.get(0).equals(arguments.get(1))) {
|
||||
commonService.send(player, MessageKey.PASSWORD_MATCH_ERROR);
|
||||
} else {
|
||||
management.performRegister(player, arguments.get(0), "", true);
|
||||
}
|
||||
@@ -68,19 +75,19 @@ public class RegisterCommand extends PlayerCommand {
|
||||
|
||||
private void handleEmailRegistration(Player player, List<String> arguments) {
|
||||
if (!sendMailSsl.hasAllInformation()) {
|
||||
commandService.send(player, MessageKey.INCOMPLETE_EMAIL_SETTINGS);
|
||||
commonService.send(player, MessageKey.INCOMPLETE_EMAIL_SETTINGS);
|
||||
ConsoleLogger.warning("Cannot register player '" + player.getName() + "': no email or password is set "
|
||||
+ "to send emails from. Please adjust your config at " + EmailSettings.MAIL_ACCOUNT.getPath());
|
||||
return;
|
||||
}
|
||||
|
||||
final String email = arguments.get(0);
|
||||
if (!commandService.validateEmail(email)) {
|
||||
commandService.send(player, MessageKey.INVALID_EMAIL);
|
||||
} else if (commandService.getProperty(ENABLE_CONFIRM_EMAIL) && !email.equals(arguments.get(1))) {
|
||||
commandService.send(player, MessageKey.USAGE_REGISTER);
|
||||
if (!validationService.validateEmail(email)) {
|
||||
commonService.send(player, MessageKey.INVALID_EMAIL);
|
||||
} else if (commonService.getProperty(ENABLE_CONFIRM_EMAIL) && !email.equals(arguments.get(1))) {
|
||||
commonService.send(player, MessageKey.USAGE_REGISTER);
|
||||
} else {
|
||||
String thePass = RandomStringUtils.generate(commandService.getProperty(RECOVERY_PASSWORD_LENGTH));
|
||||
String thePass = RandomStringUtils.generate(commonService.getProperty(RECOVERY_PASSWORD_LENGTH));
|
||||
management.performRegister(player, thePass, email, true);
|
||||
}
|
||||
}
|
||||
@@ -91,8 +98,8 @@ public class RegisterCommand extends PlayerCommand {
|
||||
* @return True if the confirmation is needed, false otherwise
|
||||
*/
|
||||
private boolean isConfirmationRequired() {
|
||||
return commandService.getProperty(USE_EMAIL_REGISTRATION)
|
||||
? commandService.getProperty(ENABLE_CONFIRM_EMAIL)
|
||||
: commandService.getProperty(ENABLE_PASSWORD_CONFIRMATION);
|
||||
return commonService.getProperty(USE_EMAIL_REGISTRATION)
|
||||
? commonService.getProperty(ENABLE_CONFIRM_EMAIL)
|
||||
: commonService.getProperty(ENABLE_PASSWORD_CONFIRMATION);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package fr.xephi.authme.command.executable.unregister;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -19,7 +19,7 @@ public class UnregisterCommand extends PlayerCommand {
|
||||
private Management management;
|
||||
|
||||
@Inject
|
||||
private CommandService commandService;
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
@@ -31,7 +31,7 @@ public class UnregisterCommand extends PlayerCommand {
|
||||
|
||||
// Make sure the player is authenticated
|
||||
if (!playerCache.isAuthenticated(playerName)) {
|
||||
commandService.send(player, MessageKey.NOT_LOGGED_IN);
|
||||
commonService.send(player, MessageKey.NOT_LOGGED_IN);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ public class PlayerAuth {
|
||||
* @return String
|
||||
*/
|
||||
public String serialize() {
|
||||
StringBuffer str = new StringBuffer();
|
||||
StringBuilder str = new StringBuilder();
|
||||
char d = ';';
|
||||
str.append(this.nickname).append(d);
|
||||
str.append(this.realName).append(d);
|
||||
|
||||
@@ -84,10 +84,10 @@ public class LimboCache {
|
||||
float walkSpeed = data.getWalkSpeed();
|
||||
float flySpeed = data.getFlySpeed();
|
||||
// Reset the speed value if it was 0
|
||||
if(walkSpeed == 0f) {
|
||||
if(walkSpeed < 0.01f) {
|
||||
walkSpeed = 0.2f;
|
||||
}
|
||||
if(flySpeed == 0f) {
|
||||
if(flySpeed < 0.01f) {
|
||||
flySpeed = 0.2f;
|
||||
}
|
||||
player.setWalkSpeed(walkSpeed);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package fr.xephi.authme.datasource;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
@@ -11,15 +10,13 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.datasource.DataSourceType;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -48,17 +45,12 @@ public class CacheDataSource implements DataSource {
|
||||
.build(new CacheLoader<String, Optional<PlayerAuth>>() {
|
||||
@Override
|
||||
public Optional<PlayerAuth> load(String key) {
|
||||
return Optional.fromNullable(source.getAuth(key));
|
||||
return Optional.ofNullable(source.getAuth(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Optional<PlayerAuth>> reload(final String key, Optional<PlayerAuth> oldValue) {
|
||||
return executorService.submit(new Callable<Optional<PlayerAuth>>() {
|
||||
@Override
|
||||
public Optional<PlayerAuth> call() {
|
||||
return load(key);
|
||||
}
|
||||
});
|
||||
return executorService.submit(() -> load(key));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -90,7 +82,7 @@ public class CacheDataSource implements DataSource {
|
||||
@Override
|
||||
public PlayerAuth getAuth(String user) {
|
||||
user = user.toLowerCase();
|
||||
return cachedAuths.getUnchecked(user).orNull();
|
||||
return cachedAuths.getUnchecked(user).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,7 +9,6 @@ import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
@@ -295,19 +294,11 @@ public class FlatFile implements DataSource {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (FileNotFoundException ex) {
|
||||
ConsoleLogger.warning(ex.getMessage());
|
||||
return false;
|
||||
} catch (IOException ex) {
|
||||
ConsoleLogger.warning(ex.getMessage());
|
||||
return false;
|
||||
} finally {
|
||||
if (br != null) {
|
||||
try {
|
||||
br.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
silentClose(br);
|
||||
}
|
||||
if (newAuth != null) {
|
||||
removeAuth(auth.getNickname());
|
||||
@@ -330,19 +321,11 @@ public class FlatFile implements DataSource {
|
||||
}
|
||||
}
|
||||
return countIp;
|
||||
} catch (FileNotFoundException ex) {
|
||||
ConsoleLogger.warning(ex.getMessage());
|
||||
return new ArrayList<>();
|
||||
} catch (IOException ex) {
|
||||
ConsoleLogger.warning(ex.getMessage());
|
||||
return new ArrayList<>();
|
||||
} finally {
|
||||
if (br != null) {
|
||||
try {
|
||||
br.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
silentClose(br);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,12 +346,7 @@ public class FlatFile implements DataSource {
|
||||
} catch (IOException ex) {
|
||||
ConsoleLogger.warning(ex.getMessage());
|
||||
} finally {
|
||||
if (br != null) {
|
||||
try {
|
||||
br.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
silentClose(br);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5,9 +5,6 @@ import com.zaxxer.hikari.HikariDataSource;
|
||||
import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.Columns;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.datasource.DataSourceType;
|
||||
import fr.xephi.authme.security.HashAlgorithm;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.security.crypts.XFBCRYPT;
|
||||
@@ -15,8 +12,8 @@ import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
import fr.xephi.authme.util.RuntimeUtils;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
import fr.xephi.authme.util.Utils;
|
||||
|
||||
import java.sql.Blob;
|
||||
import java.sql.Connection;
|
||||
@@ -50,7 +47,7 @@ public class MySQL implements DataSource {
|
||||
private int phpBbGroup;
|
||||
private String wordpressPrefix;
|
||||
|
||||
public MySQL(Settings settings) throws ClassNotFoundException, SQLException, PoolInitializationException {
|
||||
public MySQL(Settings settings) throws ClassNotFoundException, SQLException {
|
||||
setParameters(settings);
|
||||
|
||||
// Set the connection arguments (and check if connection is ok)
|
||||
@@ -100,17 +97,17 @@ public class MySQL implements DataSource {
|
||||
this.phpBbGroup = settings.getProperty(HooksSettings.PHPBB_ACTIVATED_GROUP_ID);
|
||||
this.wordpressPrefix = settings.getProperty(HooksSettings.WORDPRESS_TABLE_PREFIX);
|
||||
this.poolSize = settings.getProperty(DatabaseSettings.MYSQL_POOL_SIZE);
|
||||
if(poolSize == -1) {
|
||||
poolSize = RuntimeUtils.getCoreCount();
|
||||
if (poolSize == -1) {
|
||||
poolSize = Utils.getCoreCount();
|
||||
}
|
||||
}
|
||||
|
||||
private void setConnectionArguments() throws RuntimeException {
|
||||
private void setConnectionArguments() {
|
||||
ds = new HikariDataSource();
|
||||
ds.setPoolName("AuthMeMYSQLPool");
|
||||
|
||||
// Pool size
|
||||
ds.setMaximumPoolSize(poolSize);
|
||||
ds.setMaximumPoolSize(poolSize);
|
||||
|
||||
// Database URL
|
||||
ds.setJdbcUrl("jdbc:mysql://" + this.host + ":" + this.port + "/" + this.database);
|
||||
@@ -137,7 +134,7 @@ public class MySQL implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() throws RuntimeException {
|
||||
public void reload() {
|
||||
if (ds != null) {
|
||||
ds.close();
|
||||
}
|
||||
|
||||
@@ -3,9 +3,6 @@ package fr.xephi.authme.datasource;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.Columns;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.datasource.DataSourceType;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
@@ -397,7 +394,7 @@ public class SQLite implements DataSource {
|
||||
}
|
||||
}
|
||||
|
||||
private void close(Statement st) {
|
||||
private static void close(Statement st) {
|
||||
if (st != null) {
|
||||
try {
|
||||
st.close();
|
||||
@@ -407,7 +404,7 @@ public class SQLite implements DataSource {
|
||||
}
|
||||
}
|
||||
|
||||
private void close(Connection con) {
|
||||
private static void close(Connection con) {
|
||||
if (con != null) {
|
||||
try {
|
||||
con.close();
|
||||
@@ -417,7 +414,7 @@ public class SQLite implements DataSource {
|
||||
}
|
||||
}
|
||||
|
||||
private void close(ResultSet rs) {
|
||||
private static void close(ResultSet rs) {
|
||||
if (rs != null) {
|
||||
try {
|
||||
rs.close();
|
||||
@@ -479,7 +476,7 @@ public class SQLite implements DataSource {
|
||||
pst.setString(1, user);
|
||||
rs = pst.executeQuery();
|
||||
if (rs.next())
|
||||
return (rs.getInt(col.IS_LOGGED) == 1);
|
||||
return rs.getInt(col.IS_LOGGED) == 1;
|
||||
} catch (SQLException ex) {
|
||||
logSqlException(ex);
|
||||
} finally {
|
||||
|
||||
@@ -43,20 +43,7 @@ public class CrazyLoginConverter implements Converter {
|
||||
try (BufferedReader users = new BufferedReader(new FileReader(source))) {
|
||||
while ((line = users.readLine()) != null) {
|
||||
if (line.contains("|")) {
|
||||
String[] args = line.split("\\|");
|
||||
if (args.length < 2 || "name".equalsIgnoreCase(args[0])) {
|
||||
continue;
|
||||
}
|
||||
String playerName = args[0];
|
||||
String password = args[1];
|
||||
if (password != null) {
|
||||
PlayerAuth auth = PlayerAuth.builder()
|
||||
.name(playerName.toLowerCase())
|
||||
.realName(playerName)
|
||||
.password(password, null)
|
||||
.build();
|
||||
database.saveAuth(auth);
|
||||
}
|
||||
migrateAccount(line);
|
||||
}
|
||||
}
|
||||
ConsoleLogger.info("CrazyLogin database has been imported correctly");
|
||||
@@ -66,4 +53,26 @@ public class CrazyLoginConverter implements Converter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves an account from CrazyLogin to the AuthMe database.
|
||||
*
|
||||
* @param line line read from the CrazyLogin file (one account)
|
||||
*/
|
||||
private void migrateAccount(String line) {
|
||||
String[] args = line.split("\\|");
|
||||
if (args.length < 2 || "name".equalsIgnoreCase(args[0])) {
|
||||
return;
|
||||
}
|
||||
String playerName = args[0];
|
||||
String password = args[1];
|
||||
if (password != null) {
|
||||
PlayerAuth auth = PlayerAuth.builder()
|
||||
.name(playerName.toLowerCase())
|
||||
.realName(playerName)
|
||||
.password(password, null)
|
||||
.build();
|
||||
database.saveAuth(auth);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
package fr.xephi.authme.initialization;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.datasource.CacheDataSource;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.datasource.DataSourceType;
|
||||
import fr.xephi.authme.datasource.FlatFile;
|
||||
import fr.xephi.authme.datasource.MySQL;
|
||||
import fr.xephi.authme.datasource.SQLite;
|
||||
import fr.xephi.authme.datasource.converter.ForceFlatToSqlite;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Creates the AuthMe data source.
|
||||
*/
|
||||
public class DataSourceProvider implements Provider<DataSource> {
|
||||
|
||||
private static final String FLATFILE_FILENAME = "auths.db";
|
||||
private static final int SQLITE_MAX_SIZE = 4000;
|
||||
|
||||
@Inject
|
||||
@DataFolder
|
||||
private File dataFolder;
|
||||
@Inject
|
||||
private Settings settings;
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
DataSourceProvider() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSource get() {
|
||||
try {
|
||||
return createDataSource();
|
||||
} catch (Exception e) {
|
||||
ConsoleLogger.logException("Could not create data source:", e);
|
||||
throw new IllegalStateException("Error during initialization of data source", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the data source.
|
||||
*
|
||||
* @return the constructed datasource
|
||||
* @throws ClassNotFoundException if no driver could be found for the datasource
|
||||
* @throws SQLException when initialization of a SQL datasource failed
|
||||
* @throws IOException if flat file cannot be read
|
||||
*/
|
||||
private DataSource createDataSource() throws ClassNotFoundException, SQLException, IOException {
|
||||
DataSourceType dataSourceType = settings.getProperty(DatabaseSettings.BACKEND);
|
||||
DataSource dataSource;
|
||||
switch (dataSourceType) {
|
||||
case FILE:
|
||||
File source = new File(dataFolder, FLATFILE_FILENAME);
|
||||
dataSource = new FlatFile(source);
|
||||
break;
|
||||
case MYSQL:
|
||||
dataSource = new MySQL(settings);
|
||||
break;
|
||||
case SQLITE:
|
||||
dataSource = new SQLite(settings);
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown data source type '" + dataSourceType + "'");
|
||||
}
|
||||
|
||||
dataSource = convertFlatfileToSqlite(dataSource);
|
||||
|
||||
if (settings.getProperty(DatabaseSettings.USE_CACHING)) {
|
||||
dataSource = new CacheDataSource(dataSource);
|
||||
}
|
||||
if (DataSourceType.SQLITE.equals(dataSourceType)) {
|
||||
checkDataSourceSize(dataSource, bukkitService);
|
||||
}
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
private void checkDataSourceSize(final DataSource dataSource, BukkitService bukkitService) {
|
||||
bukkitService.runTaskAsynchronously(() -> {
|
||||
int accounts = dataSource.getAccountsRegistered();
|
||||
if (accounts >= SQLITE_MAX_SIZE) {
|
||||
ConsoleLogger.warning("YOU'RE USING THE SQLITE DATABASE WITH "
|
||||
+ accounts + "+ ACCOUNTS; FOR BETTER PERFORMANCE, PLEASE UPGRADE TO MYSQL!!");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the data source from the deprecated FLATFILE type to SQLITE.
|
||||
*
|
||||
* @param dataSource the data source to convert if necessary
|
||||
* @return the data source to use: the converted datasource (SQLite),
|
||||
* or the same data source if no conversion was performed
|
||||
*/
|
||||
private DataSource convertFlatfileToSqlite(DataSource dataSource) {
|
||||
if (DataSourceType.FILE == settings.getProperty(DatabaseSettings.BACKEND)) {
|
||||
ConsoleLogger.warning("FlatFile backend has been detected and is now deprecated; it will be changed "
|
||||
+ "to SQLite... Connection will be impossible until conversion is done!");
|
||||
FlatFile flatFile = (FlatFile) dataSource;
|
||||
try {
|
||||
SQLite sqlite = new SQLite(settings);
|
||||
ForceFlatToSqlite converter = new ForceFlatToSqlite(flatFile, sqlite);
|
||||
converter.execute(null);
|
||||
settings.setProperty(DatabaseSettings.BACKEND, DataSourceType.SQLITE);
|
||||
settings.save();
|
||||
return sqlite;
|
||||
} catch (Exception e) {
|
||||
ConsoleLogger.logException("Error during conversion from Flatfile to SQLite", e);
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
return dataSource;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@ package fr.xephi.authme.initialization;
|
||||
/**
|
||||
* Common interface for types which have data that becomes outdated
|
||||
* and that can be cleaned up periodically.
|
||||
*
|
||||
* @see fr.xephi.authme.task.CleanupTask
|
||||
*/
|
||||
public interface HasCleanup {
|
||||
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
package fr.xephi.authme.initialization;
|
||||
|
||||
import com.github.authme.configme.knownproperties.ConfigurationData;
|
||||
import com.github.authme.configme.resource.PropertyResource;
|
||||
import com.github.authme.configme.resource.YamlFileResource;
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.CacheDataSource;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.datasource.DataSourceType;
|
||||
import fr.xephi.authme.datasource.FlatFile;
|
||||
import fr.xephi.authme.datasource.MySQL;
|
||||
import fr.xephi.authme.datasource.SQLite;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.message.Messages;
|
||||
import fr.xephi.authme.output.ConsoleFilter;
|
||||
import fr.xephi.authme.output.Log4JFilter;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.MigrationService;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.SettingsMigrationService;
|
||||
import fr.xephi.authme.settings.properties.AuthMeSettingsRetriever;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
import fr.xephi.authme.util.FileUtils;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static fr.xephi.authme.service.BukkitService.TICKS_PER_MINUTE;
|
||||
import static fr.xephi.authme.settings.properties.EmailSettings.RECALL_PLAYERS;
|
||||
|
||||
/**
|
||||
* Initializes various services.
|
||||
*/
|
||||
public class Initializer {
|
||||
|
||||
private static final String FLATFILE_FILENAME = "auths.db";
|
||||
private static final int SQLITE_MAX_SIZE = 4000;
|
||||
|
||||
private AuthMe authMe;
|
||||
private BukkitService bukkitService;
|
||||
|
||||
public Initializer(AuthMe authMe, BukkitService bukkitService) {
|
||||
this.authMe = authMe;
|
||||
this.bukkitService = bukkitService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the plugin's settings.
|
||||
*
|
||||
* @param authMe the plugin instance
|
||||
* @return the settings instance, or null if it could not be constructed
|
||||
*/
|
||||
public static Settings createSettings(AuthMe authMe) throws Exception {
|
||||
File configFile = new File(authMe.getDataFolder(), "config.yml");
|
||||
if(!configFile.exists()) {
|
||||
configFile.createNewFile();
|
||||
}
|
||||
PropertyResource resource = new YamlFileResource(configFile);
|
||||
SettingsMigrationService migrationService = new SettingsMigrationService(authMe.getDataFolder());
|
||||
ConfigurationData configurationData = AuthMeSettingsRetriever.buildConfigurationData();
|
||||
return new Settings(authMe.getDataFolder(), resource, migrationService, configurationData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the data source.
|
||||
*
|
||||
* @param settings the settings
|
||||
* @return the constructed datasource
|
||||
* @throws ClassNotFoundException if no driver could be found for the datasource
|
||||
* @throws SQLException when initialization of a SQL datasource failed
|
||||
* @throws IOException if flat file cannot be read
|
||||
*/
|
||||
public DataSource setupDatabase(Settings settings) throws ClassNotFoundException, SQLException, IOException {
|
||||
DataSourceType dataSourceType = settings.getProperty(DatabaseSettings.BACKEND);
|
||||
DataSource dataSource;
|
||||
switch (dataSourceType) {
|
||||
case FILE:
|
||||
File source = new File(authMe.getDataFolder(), FLATFILE_FILENAME);
|
||||
dataSource = new FlatFile(source);
|
||||
break;
|
||||
case MYSQL:
|
||||
dataSource = new MySQL(settings);
|
||||
break;
|
||||
case SQLITE:
|
||||
dataSource = new SQLite(settings);
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown data source type '" + dataSourceType + "'");
|
||||
}
|
||||
|
||||
DataSource convertedSource = MigrationService.convertFlatfileToSqlite(settings, dataSource);
|
||||
dataSource = convertedSource == null ? dataSource : convertedSource;
|
||||
|
||||
if (settings.getProperty(DatabaseSettings.USE_CACHING)) {
|
||||
dataSource = new CacheDataSource(dataSource);
|
||||
}
|
||||
if (DataSourceType.SQLITE.equals(dataSourceType)) {
|
||||
checkDataSourceSize(dataSource);
|
||||
}
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
private void checkDataSourceSize(final DataSource dataSource) {
|
||||
bukkitService.runTaskAsynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int accounts = dataSource.getAccountsRegistered();
|
||||
if (accounts >= SQLITE_MAX_SIZE) {
|
||||
ConsoleLogger.warning("YOU'RE USING THE SQLITE DATABASE WITH "
|
||||
+ accounts + "+ ACCOUNTS; FOR BETTER PERFORMANCE, PLEASE UPGRADE TO MYSQL!!");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the console filter if enabled.
|
||||
*
|
||||
* @param settings the settings
|
||||
* @param logger the plugin logger
|
||||
*/
|
||||
public void setupConsoleFilter(Settings settings, Logger logger) {
|
||||
if (!settings.getProperty(SecuritySettings.REMOVE_PASSWORD_FROM_CONSOLE)) {
|
||||
return;
|
||||
}
|
||||
// Try to set the log4j filter
|
||||
try {
|
||||
Class.forName("org.apache.logging.log4j.core.filter.AbstractFilter");
|
||||
setLog4JFilter();
|
||||
} catch (ClassNotFoundException | NoClassDefFoundError e) {
|
||||
// log4j is not available
|
||||
ConsoleLogger.info("You're using Minecraft 1.6.x or older, Log4J support will be disabled");
|
||||
ConsoleFilter filter = new ConsoleFilter();
|
||||
logger.setFilter(filter);
|
||||
Bukkit.getLogger().setFilter(filter);
|
||||
Logger.getLogger("Minecraft").setFilter(filter);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the console filter to remove the passwords
|
||||
private static void setLog4JFilter() {
|
||||
org.apache.logging.log4j.core.Logger logger;
|
||||
logger = (org.apache.logging.log4j.core.Logger) LogManager.getRootLogger();
|
||||
logger.addFilter(new Log4JFilter());
|
||||
}
|
||||
|
||||
public void scheduleRecallEmailTask(Settings settings, final DataSource dataSource, final Messages messages) {
|
||||
if (!settings.getProperty(RECALL_PLAYERS)) {
|
||||
return;
|
||||
}
|
||||
bukkitService.runTaskTimerAsynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (PlayerAuth auth : dataSource.getLoggedPlayers()) {
|
||||
String email = auth.getEmail();
|
||||
if (StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email)) {
|
||||
Player player = bukkitService.getPlayerExact(auth.getRealName());
|
||||
if (player != null) {
|
||||
messages.send(player, MessageKey.ADD_EMAIL_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 1, TICKS_PER_MINUTE * settings.getProperty(EmailSettings.DELAY_RECALL));
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package fr.xephi.authme.initialization;
|
||||
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
import org.mcstats.Metrics;
|
||||
import org.mcstats.Metrics.Graph;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class MetricsManager {
|
||||
|
||||
private MetricsManager() {
|
||||
}
|
||||
|
||||
public static void sendMetrics(AuthMe plugin, Settings settings) {
|
||||
try {
|
||||
final Metrics metrics = new Metrics(plugin);
|
||||
|
||||
final Graph languageGraph = metrics.createGraph("Messages Language");
|
||||
final String messagesLanguage = settings.getProperty(PluginSettings.MESSAGES_LANGUAGE);
|
||||
languageGraph.addPlotter(new Metrics.Plotter(messagesLanguage) {
|
||||
@Override
|
||||
public int getValue() {
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
|
||||
final Graph databaseBackend = metrics.createGraph("Database Backend");
|
||||
final String dataSource = settings.getProperty(DatabaseSettings.BACKEND).toString();
|
||||
databaseBackend.addPlotter(new Metrics.Plotter(dataSource) {
|
||||
@Override
|
||||
public int getValue() {
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
|
||||
// Submit metrics
|
||||
metrics.start();
|
||||
} catch (IOException e) {
|
||||
// Failed to submit the metrics data
|
||||
ConsoleLogger.logException("Can't send Metrics data! The plugin will work anyway...", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,10 +76,8 @@ public class OnShutdownPlayerSaver {
|
||||
dataSource.updateQuitLoc(auth);
|
||||
}
|
||||
if (settings.getProperty(RestrictionSettings.TELEPORT_UNAUTHED_TO_SPAWN)
|
||||
&& !settings.getProperty(RestrictionSettings.NO_TELEPORT)) {
|
||||
if (!limboPlayerStorage.hasData(player)) {
|
||||
limboPlayerStorage.saveData(player);
|
||||
}
|
||||
&& !settings.getProperty(RestrictionSettings.NO_TELEPORT) && !limboPlayerStorage.hasData(player)) {
|
||||
limboPlayerStorage.saveData(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
package fr.xephi.authme.initialization;
|
||||
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.message.Messages;
|
||||
import fr.xephi.authme.output.ConsoleFilter;
|
||||
import fr.xephi.authme.output.Log4JFilter;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.mcstats.Metrics;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static fr.xephi.authme.service.BukkitService.TICKS_PER_MINUTE;
|
||||
import static fr.xephi.authme.settings.properties.EmailSettings.RECALL_PLAYERS;
|
||||
|
||||
/**
|
||||
* Contains actions such as migrations that should be performed on startup.
|
||||
*/
|
||||
public class OnStartupTasks {
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
@Inject
|
||||
private Settings settings;
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
@Inject
|
||||
private Messages messages;
|
||||
|
||||
OnStartupTasks() {
|
||||
}
|
||||
|
||||
public static void sendMetrics(AuthMe plugin, Settings settings) {
|
||||
try {
|
||||
final Metrics metrics = new Metrics(plugin);
|
||||
|
||||
final Metrics.Graph languageGraph = metrics.createGraph("Messages Language");
|
||||
final String messagesLanguage = settings.getProperty(PluginSettings.MESSAGES_LANGUAGE);
|
||||
languageGraph.addPlotter(new Metrics.Plotter(messagesLanguage) {
|
||||
@Override
|
||||
public int getValue() {
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
|
||||
final Metrics.Graph databaseBackend = metrics.createGraph("Database Backend");
|
||||
final String dataSource = settings.getProperty(DatabaseSettings.BACKEND).toString();
|
||||
databaseBackend.addPlotter(new Metrics.Plotter(dataSource) {
|
||||
@Override
|
||||
public int getValue() {
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
|
||||
// Submit metrics
|
||||
metrics.start();
|
||||
} catch (IOException e) {
|
||||
// Failed to submit the metrics data
|
||||
ConsoleLogger.logException("Can't send Metrics data! The plugin will work anyway...", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the console filter if enabled.
|
||||
*
|
||||
* @param settings the settings
|
||||
* @param logger the plugin logger
|
||||
*/
|
||||
public static void setupConsoleFilter(Settings settings, Logger logger) {
|
||||
if (!settings.getProperty(SecuritySettings.REMOVE_PASSWORD_FROM_CONSOLE)) {
|
||||
return;
|
||||
}
|
||||
// Try to set the log4j filter
|
||||
try {
|
||||
Class.forName("org.apache.logging.log4j.core.filter.AbstractFilter");
|
||||
setLog4JFilter();
|
||||
} catch (ClassNotFoundException | NoClassDefFoundError e) {
|
||||
// log4j is not available
|
||||
ConsoleLogger.info("You're using Minecraft 1.6.x or older, Log4J support will be disabled");
|
||||
ConsoleFilter filter = new ConsoleFilter();
|
||||
logger.setFilter(filter);
|
||||
Bukkit.getLogger().setFilter(filter);
|
||||
Logger.getLogger("Minecraft").setFilter(filter);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the console filter to remove the passwords
|
||||
private static void setLog4JFilter() {
|
||||
org.apache.logging.log4j.core.Logger logger;
|
||||
logger = (org.apache.logging.log4j.core.Logger) LogManager.getRootLogger();
|
||||
logger.addFilter(new Log4JFilter());
|
||||
}
|
||||
|
||||
public void scheduleRecallEmailTask() {
|
||||
if (!settings.getProperty(RECALL_PLAYERS)) {
|
||||
return;
|
||||
}
|
||||
bukkitService.runTaskTimerAsynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (PlayerAuth auth : dataSource.getLoggedPlayers()) {
|
||||
String email = auth.getEmail();
|
||||
if (StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email)) {
|
||||
Player player = bukkitService.getPlayerExact(auth.getRealName());
|
||||
if (player != null) {
|
||||
messages.send(player, MessageKey.ADD_EMAIL_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 1, TICKS_PER_MINUTE * settings.getProperty(EmailSettings.DELAY_RECALL));
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package fr.xephi.authme.initialization;
|
||||
|
||||
/**
|
||||
* Interface for reloadable entities.
|
||||
*
|
||||
* @see fr.xephi.authme.command.executable.authme.ReloadCommand
|
||||
*/
|
||||
public interface Reloadable {
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ import fr.xephi.authme.settings.Settings;
|
||||
|
||||
/**
|
||||
* Interface for classes that keep a local copy of certain settings.
|
||||
*
|
||||
* @see fr.xephi.authme.command.executable.authme.ReloadCommand
|
||||
*/
|
||||
public interface SettingsDependent {
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package fr.xephi.authme.initialization;
|
||||
|
||||
import com.github.authme.configme.knownproperties.ConfigurationData;
|
||||
import com.github.authme.configme.resource.PropertyResource;
|
||||
import com.github.authme.configme.resource.YamlFileResource;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.SettingsMigrationService;
|
||||
import fr.xephi.authme.settings.properties.AuthMeSettingsRetriever;
|
||||
import fr.xephi.authme.util.FileUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Initializes the settings.
|
||||
*/
|
||||
public class SettingsProvider implements Provider<Settings> {
|
||||
|
||||
@Inject
|
||||
@DataFolder
|
||||
private File dataFolder;
|
||||
@Inject
|
||||
private SettingsMigrationService migrationService;
|
||||
|
||||
SettingsProvider() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the plugin's settings.
|
||||
*
|
||||
* @return the settings instance, or null if it could not be constructed
|
||||
*/
|
||||
@Override
|
||||
public Settings get() {
|
||||
File configFile = new File(dataFolder, "config.yml");
|
||||
if (!configFile.exists()) {
|
||||
FileUtils.create(configFile);
|
||||
}
|
||||
PropertyResource resource = new YamlFileResource(configFile);
|
||||
ConfigurationData configurationData = AuthMeSettingsRetriever.buildConfigurationData();
|
||||
return new Settings(dataFolder, resource, migrationService, configurationData);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,14 +9,14 @@ import fr.xephi.authme.message.Messages;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import fr.xephi.authme.permission.PlayerStatePermission;
|
||||
import fr.xephi.authme.service.AntiBotService;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.ProtectionSettings;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
import fr.xephi.authme.util.Utils;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
@@ -68,10 +68,10 @@ class OnJoinVerifier implements Reloadable {
|
||||
* @param isAuthAvailable whether or not the player is registered
|
||||
*/
|
||||
public void checkAntibot(Player player, boolean isAuthAvailable) throws FailedVerificationException {
|
||||
if (permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT)) {
|
||||
if (isAuthAvailable || permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT)) {
|
||||
return;
|
||||
}
|
||||
if (antiBotService.shouldKick(isAuthAvailable)) {
|
||||
if (antiBotService.shouldKick()) {
|
||||
antiBotService.addPlayerKick(player.getName());
|
||||
throw new FailedVerificationException(MessageKey.KICK_ANTIBOT);
|
||||
}
|
||||
@@ -170,10 +170,9 @@ class OnJoinVerifier implements Reloadable {
|
||||
public void checkPlayerCountry(boolean isAuthAvailable,
|
||||
String playerIp) throws FailedVerificationException {
|
||||
if ((!isAuthAvailable || settings.getProperty(ProtectionSettings.ENABLE_PROTECTION_REGISTERED))
|
||||
&& settings.getProperty(ProtectionSettings.ENABLE_PROTECTION)) {
|
||||
if (!validationService.isCountryAdmitted(playerIp)) {
|
||||
&& settings.getProperty(ProtectionSettings.ENABLE_PROTECTION)
|
||||
&& !validationService.isCountryAdmitted(playerIp)) {
|
||||
throw new FailedVerificationException(MessageKey.COUNTRY_BANNED_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,14 +6,14 @@ import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.message.Messages;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import fr.xephi.authme.service.AntiBotService;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.TeleportationService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.SpawnLoader;
|
||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.TeleportationService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@@ -42,6 +42,7 @@ import org.bukkit.event.player.PlayerShearEntityEvent;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@@ -53,7 +54,7 @@ import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOW_UNAU
|
||||
*/
|
||||
public class PlayerListener implements Listener {
|
||||
|
||||
public static final ConcurrentHashMap<String, String> joinMessage = new ConcurrentHashMap<>();
|
||||
public static final Map<String, String> joinMessage = new ConcurrentHashMap<>();
|
||||
|
||||
@Inject
|
||||
private Settings settings;
|
||||
@@ -81,7 +82,7 @@ public class PlayerListener implements Listener {
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
|
||||
String cmd = event.getMessage().split(" ")[0].toLowerCase();
|
||||
if (settings.getProperty(HooksSettings.USE_ESSENTIALS_MOTD) && cmd.equals("/motd")) {
|
||||
if (settings.getProperty(HooksSettings.USE_ESSENTIALS_MOTD) && "/motd".equals(cmd)) {
|
||||
return;
|
||||
}
|
||||
if (settings.getProperty(RestrictionSettings.ALLOW_COMMANDS).contains(cmd)) {
|
||||
@@ -113,7 +114,7 @@ public class PlayerListener implements Listener {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
if (recipients.size() == 0) {
|
||||
if (recipients.isEmpty()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
@@ -156,9 +157,7 @@ public class PlayerListener implements Listener {
|
||||
if (spawn != null && spawn.getWorld() != null) {
|
||||
if (!player.getWorld().equals(spawn.getWorld())) {
|
||||
player.teleport(spawn);
|
||||
return;
|
||||
}
|
||||
if (spawn.distance(player.getLocation()) > settings.getProperty(ALLOWED_MOVEMENT_RADIUS)) {
|
||||
} else if (spawn.distance(player.getLocation()) > settings.getProperty(ALLOWED_MOVEMENT_RADIUS)) {
|
||||
player.teleport(spawn);
|
||||
}
|
||||
}
|
||||
@@ -208,9 +207,11 @@ public class PlayerListener implements Listener {
|
||||
final String name = player.getName();
|
||||
if (validationService.isUnrestricted(name)) {
|
||||
return;
|
||||
} else if (onJoinVerifier.refusePlayerForFullServer(event)) {
|
||||
}
|
||||
if (onJoinVerifier.refusePlayerForFullServer(event)) {
|
||||
return;
|
||||
} else if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) {
|
||||
}
|
||||
if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -222,9 +223,9 @@ public class PlayerListener implements Listener {
|
||||
// Get the auth later as this may cause the single session check to fail
|
||||
// Slow stuff
|
||||
final PlayerAuth auth = dataSource.getAuth(name);
|
||||
final boolean isAuthAvailable = (auth != null);
|
||||
onJoinVerifier.checkAntibot(player, isAuthAvailable);
|
||||
final boolean isAuthAvailable = auth != null;
|
||||
onJoinVerifier.checkKickNonRegistered(isAuthAvailable);
|
||||
onJoinVerifier.checkAntibot(player, isAuthAvailable);
|
||||
onJoinVerifier.checkNameCasing(player, auth);
|
||||
onJoinVerifier.checkPlayerCountry(isAuthAvailable, event.getAddress().getHostAddress());
|
||||
} catch (FailedVerificationException e) {
|
||||
@@ -233,7 +234,6 @@ public class PlayerListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
antiBotService.handlePlayerJoin();
|
||||
teleportationService.teleportOnJoin(player);
|
||||
}
|
||||
|
||||
@@ -306,27 +306,14 @@ public class PlayerListener implements Listener {
|
||||
* @note little hack cause InventoryOpenEvent cannot be cancelled for
|
||||
* real, cause no packet is send to server by client for the main inv
|
||||
*/
|
||||
bukkitService.scheduleSyncDelayedTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
player.closeInventory();
|
||||
}
|
||||
}, 1);
|
||||
bukkitService.scheduleSyncDelayedTask(player::closeInventory, 1);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerInventoryClick(InventoryClickEvent event) {
|
||||
if (event.getWhoClicked() == null) {
|
||||
return;
|
||||
if (listenerService.shouldCancelEvent(event.getWhoClicked())) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
if (!(event.getWhoClicked() instanceof Player)) {
|
||||
return;
|
||||
}
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
if (!listenerService.shouldCancelEvent(player)) {
|
||||
return;
|
||||
}
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package fr.xephi.authme.listener;
|
||||
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityAirChangeEvent;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Listener of player events for events introduced in Minecraft 1.11.
|
||||
*/
|
||||
public class PlayerListener111 implements Listener {
|
||||
|
||||
@Inject
|
||||
private ListenerService listenerService;
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerAirChange(EntityAirChangeEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,22 @@
|
||||
package fr.xephi.authme.mail;
|
||||
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.initialization.DataFolder;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.util.FileUtils;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
import org.apache.commons.mail.EmailConstants;
|
||||
import org.apache.commons.mail.EmailException;
|
||||
import org.apache.commons.mail.HtmlEmail;
|
||||
import org.bukkit.Server;
|
||||
|
||||
import javax.activation.CommandMap;
|
||||
import javax.activation.DataSource;
|
||||
import javax.activation.FileDataSource;
|
||||
import javax.activation.MailcapCommandMap;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.inject.Inject;
|
||||
import javax.mail.Session;
|
||||
@@ -27,18 +30,19 @@ import static fr.xephi.authme.settings.properties.EmailSettings.MAIL_PASSWORD;
|
||||
|
||||
|
||||
/**
|
||||
* @author Xephi59
|
||||
* Sends emails to players on behalf of the server.
|
||||
*/
|
||||
public class SendMailSSL {
|
||||
|
||||
@Inject
|
||||
private AuthMe plugin;
|
||||
@Inject
|
||||
private Settings settings;
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
private final File dataFolder;
|
||||
private final String serverName;
|
||||
private final Settings settings;
|
||||
|
||||
SendMailSSL() {
|
||||
@Inject
|
||||
SendMailSSL(@DataFolder File dataFolder, Server server, Settings settings) {
|
||||
this.dataFolder = dataFolder;
|
||||
this.serverName = server.getServerName();
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,62 +61,57 @@ public class SendMailSSL {
|
||||
* @param name the name of the player
|
||||
* @param mailAddress the player's email
|
||||
* @param newPass the new password
|
||||
* @return true if email could be sent, false otherwise
|
||||
*/
|
||||
public void sendPasswordMail(String name, String mailAddress, String newPass) {
|
||||
public boolean sendPasswordMail(String name, String mailAddress, String newPass) {
|
||||
if (!hasAllInformation()) {
|
||||
ConsoleLogger.warning("Cannot perform email registration: not all email settings are complete");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
final String mailText = replaceTagsForPasswordMail(settings.getPasswordEmailMessage(), name, newPass);
|
||||
bukkitService.runTaskAsynchronously(new Runnable() {
|
||||
HtmlEmail email;
|
||||
try {
|
||||
email = initializeMail(mailAddress);
|
||||
} catch (EmailException e) {
|
||||
ConsoleLogger.logException("Failed to create email with the given settings:", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
HtmlEmail email;
|
||||
try {
|
||||
email = initializeMail(mailAddress);
|
||||
} catch (EmailException e) {
|
||||
ConsoleLogger.logException("Failed to create email with the given settings:", e);
|
||||
return;
|
||||
}
|
||||
|
||||
String content = mailText;
|
||||
// Generate an image?
|
||||
File file = null;
|
||||
if (settings.getProperty(EmailSettings.PASSWORD_AS_IMAGE)) {
|
||||
try {
|
||||
file = generateImage(name, plugin, newPass);
|
||||
content = embedImageIntoEmailContent(file, email, content);
|
||||
} catch (IOException | EmailException e) {
|
||||
ConsoleLogger.logException(
|
||||
"Unable to send new password as image for email " + mailAddress + ":", e);
|
||||
}
|
||||
}
|
||||
|
||||
sendEmail(content, email);
|
||||
FileUtils.delete(file);
|
||||
String mailText = replaceTagsForPasswordMail(settings.getPasswordEmailMessage(), name, newPass);
|
||||
// Generate an image?
|
||||
File file = null;
|
||||
if (settings.getProperty(EmailSettings.PASSWORD_AS_IMAGE)) {
|
||||
try {
|
||||
file = generateImage(name, newPass);
|
||||
mailText = embedImageIntoEmailContent(file, email, mailText);
|
||||
} catch (IOException | EmailException e) {
|
||||
ConsoleLogger.logException(
|
||||
"Unable to send new password as image for email " + mailAddress + ":", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
boolean couldSendEmail = sendEmail(mailText, email);
|
||||
FileUtils.delete(file);
|
||||
return couldSendEmail;
|
||||
}
|
||||
|
||||
public void sendRecoveryCode(String name, String email, String code) {
|
||||
String message = replaceTagsForRecoveryCodeMail(settings.getRecoveryCodeEmailMessage(),
|
||||
name, code, settings.getProperty(SecuritySettings.RECOVERY_CODE_HOURS_VALID));
|
||||
|
||||
public boolean sendRecoveryCode(String name, String email, String code) {
|
||||
HtmlEmail htmlEmail;
|
||||
try {
|
||||
htmlEmail = initializeMail(email);
|
||||
} catch (EmailException e) {
|
||||
ConsoleLogger.logException("Failed to create email for recovery code:", e);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
sendEmail(message, htmlEmail);
|
||||
|
||||
String message = replaceTagsForRecoveryCodeMail(settings.getRecoveryCodeEmailMessage(),
|
||||
name, code, settings.getProperty(SecuritySettings.RECOVERY_CODE_HOURS_VALID));
|
||||
return sendEmail(message, htmlEmail);
|
||||
}
|
||||
|
||||
private static File generateImage(String name, AuthMe plugin, String newPass) throws IOException {
|
||||
private File generateImage(String name, String newPass) throws IOException {
|
||||
ImageGenerator gen = new ImageGenerator(newPass);
|
||||
File file = new File(plugin.getDataFolder(), name + "_new_pass.jpg");
|
||||
File file = new File(dataFolder, name + "_new_pass.jpg");
|
||||
ImageIO.write(gen.generateImage(), "jpg", file);
|
||||
return file;
|
||||
}
|
||||
@@ -124,7 +123,8 @@ public class SendMailSSL {
|
||||
return content.replace("<image />", "<img src=\"cid:" + tag + "\">");
|
||||
}
|
||||
|
||||
private HtmlEmail initializeMail(String emailAddress) throws EmailException {
|
||||
@VisibleForTesting
|
||||
HtmlEmail initializeMail(String emailAddress) throws EmailException {
|
||||
String senderMail = settings.getProperty(EmailSettings.MAIL_ACCOUNT);
|
||||
String senderName = StringUtils.isEmpty(settings.getProperty(EmailSettings.MAIL_SENDER_NAME))
|
||||
? senderMail
|
||||
@@ -145,8 +145,18 @@ public class SendMailSSL {
|
||||
return email;
|
||||
}
|
||||
|
||||
private static boolean sendEmail(String content, HtmlEmail email) {
|
||||
@VisibleForTesting
|
||||
boolean sendEmail(String content, HtmlEmail email) {
|
||||
Thread.currentThread().setContextClassLoader(SendMailSSL.class.getClassLoader());
|
||||
// Issue #999: Prevent UnsupportedDataTypeException: no object DCH for MIME type multipart/alternative
|
||||
// cf. http://stackoverflow.com/questions/21856211/unsupporteddatatypeexception-no-object-dch-for-mime-type
|
||||
MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
|
||||
mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
|
||||
mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
|
||||
mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
|
||||
mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
|
||||
mc.addMailcap("message/rfc822;; x-java-content- handler=com.sun.mail.handlers.message_rfc822");
|
||||
|
||||
try {
|
||||
email.setHtmlMsg(content);
|
||||
email.setTextMsg(content);
|
||||
@@ -166,14 +176,14 @@ public class SendMailSSL {
|
||||
private String replaceTagsForPasswordMail(String mailText, String name, String newPass) {
|
||||
return mailText
|
||||
.replace("<playername />", name)
|
||||
.replace("<servername />", plugin.getServer().getServerName())
|
||||
.replace("<servername />", serverName)
|
||||
.replace("<generatedpass />", newPass);
|
||||
}
|
||||
|
||||
private String replaceTagsForRecoveryCodeMail(String mailText, String name, String code, int hoursValid) {
|
||||
return mailText
|
||||
.replace("<playername />", name)
|
||||
.replace("<servername />", plugin.getServer().getServerName())
|
||||
.replace("<servername />", serverName)
|
||||
.replace("<recoverycode />", code)
|
||||
.replace("<hoursvalid />", String.valueOf(hoursValid));
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public class MessageFileHandler {
|
||||
|
||||
if (message == null) {
|
||||
ConsoleLogger.warning("Error getting message with key '" + key + "'. "
|
||||
+ "Please verify your config file at '" + filename + "'");
|
||||
+ "Please update your config file '" + filename + "' (or run /authme messages)");
|
||||
return getDefault(key);
|
||||
}
|
||||
return message;
|
||||
|
||||
@@ -5,156 +5,235 @@ package fr.xephi.authme.message;
|
||||
*/
|
||||
public enum MessageKey {
|
||||
|
||||
/** In order to use this command you must be authenticated! */
|
||||
DENIED_COMMAND("denied_command"),
|
||||
|
||||
/** A player with the same IP is already in game! */
|
||||
SAME_IP_ONLINE("same_ip_online"),
|
||||
|
||||
/** In order to chat you must be authenticated! */
|
||||
DENIED_CHAT("denied_chat"),
|
||||
|
||||
/** AntiBot protection mode is enabled! You have to wait some minutes before joining the server. */
|
||||
KICK_ANTIBOT("kick_antibot"),
|
||||
|
||||
/** Can't find the requested user in the database! */
|
||||
UNKNOWN_USER("unknown_user"),
|
||||
|
||||
/** Your quit location was unsafe, you have been teleported to the world's spawnpoint. */
|
||||
UNSAFE_QUIT_LOCATION("unsafe_spawn"),
|
||||
|
||||
/** You're not logged in! */
|
||||
NOT_LOGGED_IN("not_logged_in"),
|
||||
|
||||
/** You can register yourself to the server with the command "/register >password> >ConfirmPassword>" */
|
||||
REGISTER_VOLUNTARILY("reg_voluntarily"),
|
||||
|
||||
/** Usage: /login >password> */
|
||||
USAGE_LOGIN("usage_log"),
|
||||
|
||||
/** Wrong password! */
|
||||
WRONG_PASSWORD("wrong_pwd"),
|
||||
|
||||
/** Successfully unregistered! */
|
||||
UNREGISTERED_SUCCESS("unregistered"),
|
||||
|
||||
/** In-game registration is disabled! */
|
||||
REGISTRATION_DISABLED("reg_disabled"),
|
||||
|
||||
/** Logged-in due to Session Reconnection. */
|
||||
SESSION_RECONNECTION("valid_session"),
|
||||
|
||||
/** Successful login! */
|
||||
LOGIN_SUCCESS("login"),
|
||||
|
||||
/** Your account isn't activated yet, please check your emails! */
|
||||
ACCOUNT_NOT_ACTIVATED("vb_nonActiv"),
|
||||
|
||||
/** You already have registered this username! */
|
||||
NAME_ALREADY_REGISTERED("user_regged"),
|
||||
|
||||
/** You don't have the permission to perform this action! */
|
||||
NO_PERMISSION("no_perm"),
|
||||
|
||||
/** An unexpected error occurred, please contact an administrator! */
|
||||
ERROR("error"),
|
||||
|
||||
/** Please, login with the command "/login >password>" */
|
||||
LOGIN_MESSAGE("login_msg"),
|
||||
|
||||
/** Please, register to the server with the command "/register >password> >ConfirmPassword>" */
|
||||
REGISTER_MESSAGE("reg_msg"),
|
||||
|
||||
/** Please, register to the server with the command "/register >email> >confirmEmail>" */
|
||||
REGISTER_EMAIL_MESSAGE("reg_email_msg"),
|
||||
|
||||
/** You have exceeded the maximum number of registrations (%reg_count/%max_acc %reg_names) for your connection! */
|
||||
MAX_REGISTER_EXCEEDED("max_reg", "%max_acc", "%reg_count", "%reg_names"),
|
||||
|
||||
/** Usage: /register >password> >ConfirmPassword> */
|
||||
USAGE_REGISTER("usage_reg"),
|
||||
|
||||
/** Usage: /unregister >password> */
|
||||
USAGE_UNREGISTER("usage_unreg"),
|
||||
|
||||
/** Password changed successfully! */
|
||||
PASSWORD_CHANGED_SUCCESS("pwd_changed"),
|
||||
|
||||
/** This user isn't registered! */
|
||||
USER_NOT_REGISTERED("user_unknown"),
|
||||
|
||||
/** Passwords didn't match, check them again! */
|
||||
PASSWORD_MATCH_ERROR("password_error"),
|
||||
|
||||
/** You can't use your name as password, please choose another one... */
|
||||
PASSWORD_IS_USERNAME_ERROR("password_error_nick"),
|
||||
|
||||
/** The chosen password isn't safe, please choose another one... */
|
||||
PASSWORD_UNSAFE_ERROR("password_error_unsafe"),
|
||||
|
||||
/** Your password contains illegal characters. Allowed chars: REG_EX */
|
||||
PASSWORD_CHARACTERS_ERROR("password_error_chars", "REG_EX"),
|
||||
|
||||
/** Your IP has been changed and your session data has expired! */
|
||||
SESSION_EXPIRED("invalid_session"),
|
||||
|
||||
/** Only registered users can join the server! Please visit http://example.com to register yourself! */
|
||||
MUST_REGISTER_MESSAGE("reg_only"),
|
||||
|
||||
/** You're already logged in! */
|
||||
ALREADY_LOGGED_IN_ERROR("logged_in"),
|
||||
|
||||
/** Logged-out successfully! */
|
||||
LOGOUT_SUCCESS("logout"),
|
||||
|
||||
/** The same username is already playing on the server! */
|
||||
USERNAME_ALREADY_ONLINE_ERROR("same_nick"),
|
||||
|
||||
/** Successfully registered! */
|
||||
REGISTER_SUCCESS("registered"),
|
||||
|
||||
/** Your password is too short or too long! Please try with another one! */
|
||||
INVALID_PASSWORD_LENGTH("pass_len"),
|
||||
|
||||
/** Configuration and database have been reloaded correctly! */
|
||||
CONFIG_RELOAD_SUCCESS("reload"),
|
||||
|
||||
/** Login timeout exceeded, you have been kicked from the server, please try again! */
|
||||
LOGIN_TIMEOUT_ERROR("timeout"),
|
||||
|
||||
/** Usage: /changepassword >oldPassword> >newPassword> */
|
||||
USAGE_CHANGE_PASSWORD("usage_changepassword"),
|
||||
|
||||
/** Your username is either too short or too long! */
|
||||
INVALID_NAME_LENGTH("name_len"),
|
||||
|
||||
/** Your username contains illegal characters. Allowed chars: REG_EX */
|
||||
INVALID_NAME_CHARACTERS("regex", "REG_EX"),
|
||||
|
||||
/** Please add your email to your account with the command "/email add >yourEmail> >confirmEmail>" */
|
||||
ADD_EMAIL_MESSAGE("add_email"),
|
||||
|
||||
/** Forgot your password? Please use the command "/email recovery >yourEmail>" */
|
||||
FORGOT_PASSWORD_MESSAGE("recovery_email"),
|
||||
|
||||
/** To login you have to solve a captcha code, please use the command "/captcha >theCaptcha>" */
|
||||
USAGE_CAPTCHA("usage_captcha", "<theCaptcha>"),
|
||||
|
||||
/** Wrong captcha, please type "/captcha THE_CAPTCHA" into the chat! */
|
||||
CAPTCHA_WRONG_ERROR("wrong_captcha", "THE_CAPTCHA"),
|
||||
|
||||
/** Captcha code solved correctly! */
|
||||
CAPTCHA_SUCCESS("valid_captcha"),
|
||||
|
||||
/** A VIP player has joined the server when it was full! */
|
||||
KICK_FOR_VIP("kick_forvip"),
|
||||
|
||||
/** The server is full, try again later! */
|
||||
KICK_FULL_SERVER("kick_fullserver"),
|
||||
|
||||
/** Usage: /email add >email> >confirmEmail> */
|
||||
USAGE_ADD_EMAIL("usage_email_add"),
|
||||
|
||||
/** Usage: /email change >oldEmail> >newEmail> */
|
||||
USAGE_CHANGE_EMAIL("usage_email_change"),
|
||||
|
||||
/** Usage: /email recovery >Email> */
|
||||
USAGE_RECOVER_EMAIL("usage_email_recovery"),
|
||||
|
||||
/** Invalid new email, try again! */
|
||||
INVALID_NEW_EMAIL("new_email_invalid"),
|
||||
|
||||
/** Invalid old email, try again! */
|
||||
INVALID_OLD_EMAIL("old_email_invalid"),
|
||||
|
||||
/** Invalid email address, try again! */
|
||||
INVALID_EMAIL("email_invalid"),
|
||||
|
||||
/** Email address successfully added to your account! */
|
||||
EMAIL_ADDED_SUCCESS("email_added"),
|
||||
|
||||
/** Please confirm your email address! */
|
||||
CONFIRM_EMAIL_MESSAGE("email_confirm"),
|
||||
|
||||
/** Email address changed correctly! */
|
||||
EMAIL_CHANGED_SUCCESS("email_changed"),
|
||||
|
||||
/** Your current email address is: %email */
|
||||
EMAIL_SHOW("email_show", "%email"),
|
||||
|
||||
/** You currently don't have email address associated with this account. */
|
||||
SHOW_NO_EMAIL("show_no_email"),
|
||||
|
||||
/** Recovery email sent successfully! Please check your email inbox! */
|
||||
RECOVERY_EMAIL_SENT_MESSAGE("email_send"),
|
||||
|
||||
/** A recovery email was already sent! You can discard it and send a new one using the command below: */
|
||||
RECOVERY_EMAIL_ALREADY_SENT_MESSAGE("email_exists"),
|
||||
|
||||
/** Your country is banned from this server! */
|
||||
COUNTRY_BANNED_ERROR("country_banned"),
|
||||
|
||||
/** [AntiBotService] AntiBot enabled due to the huge number of connections! */
|
||||
ANTIBOT_AUTO_ENABLED_MESSAGE("antibot_auto_enabled"),
|
||||
|
||||
/** [AntiBotService] AntiBot disabled after %m minutes! */
|
||||
ANTIBOT_AUTO_DISABLED_MESSAGE("antibot_auto_disabled", "%m"),
|
||||
|
||||
/** The email address is already being used */
|
||||
EMAIL_ALREADY_USED_ERROR("email_already_used"),
|
||||
|
||||
/** Your secret code is %code. You can scan it from here %url */
|
||||
TWO_FACTOR_CREATE("two_factor_create", "%code", "%url"),
|
||||
|
||||
/** You are not the owner of this account. Please choose another name! */
|
||||
NOT_OWNER_ERROR("not_owner_error"),
|
||||
|
||||
/** You should join using username %valid, not %invalid. */
|
||||
INVALID_NAME_CASE("invalid_name_case", "%valid", "%invalid"),
|
||||
|
||||
/** You have been temporarily banned for failing to log in too many times. */
|
||||
TEMPBAN_MAX_LOGINS("tempban_max_logins"),
|
||||
|
||||
/** You own %count accounts: */
|
||||
ACCOUNTS_OWNED_SELF("accounts_owned_self", "%count"),
|
||||
|
||||
/** The player %name has %count accounts: */
|
||||
ACCOUNTS_OWNED_OTHER("accounts_owned_other", "%name", "%count"),
|
||||
|
||||
/** An admin just registered you; please log in again */
|
||||
KICK_FOR_ADMIN_REGISTER("kicked_admin_registered"),
|
||||
|
||||
/** Error: not all required settings are set for sending emails. Please contact an admin. */
|
||||
INCOMPLETE_EMAIL_SETTINGS("incomplete_email_settings"),
|
||||
|
||||
/** The email could not be sent. Please contact an administrator. */
|
||||
EMAIL_SEND_FAILURE("email_send_failure"),
|
||||
|
||||
/** A recovery code to reset your password has been sent to your email. */
|
||||
RECOVERY_CODE_SENT("recovery_code_sent"),
|
||||
|
||||
/** The recovery code is not correct! Use /email recovery [email] to generate a new one */
|
||||
INCORRECT_RECOVERY_CODE("recovery_code_incorrect");
|
||||
|
||||
private String key;
|
||||
|
||||
@@ -12,14 +12,9 @@ import org.apache.logging.log4j.message.Message;
|
||||
*
|
||||
* @author Xephi59
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class Log4JFilter extends AbstractFilter {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public Log4JFilter() {
|
||||
}
|
||||
private static final long serialVersionUID = -5594073755007974254L;
|
||||
|
||||
/**
|
||||
* Validates a Message instance and returns the {@link Result} value
|
||||
|
||||
@@ -10,6 +10,7 @@ import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Inject;
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -31,7 +32,8 @@ public class AuthGroupHandler implements Reloadable {
|
||||
private String unregisteredGroup;
|
||||
private String registeredGroup;
|
||||
|
||||
AuthGroupHandler() { }
|
||||
AuthGroupHandler() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the group of a player, by its AuthMe group type.
|
||||
@@ -114,6 +116,7 @@ public class AuthGroupHandler implements Reloadable {
|
||||
}
|
||||
|
||||
@Override
|
||||
@PostConstruct
|
||||
public void reload() {
|
||||
unloggedInGroup = settings.getProperty(SecuritySettings.UNLOGGEDIN_GROUP);
|
||||
unregisteredGroup = settings.getProperty(HooksSettings.UNREGISTERED_GROUP);
|
||||
|
||||
@@ -78,12 +78,12 @@ public class PermissionsManager implements Reloadable {
|
||||
if (handler != null) {
|
||||
// Show a success message and return
|
||||
this.handler = handler;
|
||||
ConsoleLogger.info("Hooked into " + type.getName() + "!");
|
||||
ConsoleLogger.info("Hooked into " + type.getDisplayName() + "!");
|
||||
return;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
// An error occurred, show a warning message
|
||||
ConsoleLogger.logException("Error while hooking into " + type.getName(), ex);
|
||||
ConsoleLogger.logException("Error while hooking into " + type.getDisplayName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ public class PermissionsManager implements Reloadable {
|
||||
|
||||
// Make sure the plugin is enabled before hooking
|
||||
if (!plugin.isEnabled()) {
|
||||
ConsoleLogger.info("Not hooking into " + type.getName() + " because it's disabled!");
|
||||
ConsoleLogger.info("Not hooking into " + type.getDisplayName() + " because it's disabled!");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -414,7 +414,7 @@ public class PermissionsManager implements Reloadable {
|
||||
*/
|
||||
public boolean setGroups(Player player, List<String> groupNames) {
|
||||
// If no permissions system is used or if there's no group supplied, return false
|
||||
if (!isEnabled() || groupNames.size() <= 0)
|
||||
if (!isEnabled() || groupNames.isEmpty())
|
||||
return false;
|
||||
|
||||
// Set the main group
|
||||
|
||||
@@ -33,21 +33,21 @@ public enum PermissionsSystemType {
|
||||
/**
|
||||
* The display name of the permissions system.
|
||||
*/
|
||||
public String name;
|
||||
private String displayName;
|
||||
|
||||
/**
|
||||
* The name of the permissions system plugin.
|
||||
*/
|
||||
public String pluginName;
|
||||
private String pluginName;
|
||||
|
||||
/**
|
||||
* Constructor for PermissionsSystemType.
|
||||
*
|
||||
* @param name Display name of the permissions system.
|
||||
* @param displayName Display name of the permissions system.
|
||||
* @param pluginName Name of the plugin.
|
||||
*/
|
||||
PermissionsSystemType(String name, String pluginName) {
|
||||
this.name = name;
|
||||
PermissionsSystemType(String displayName, String pluginName) {
|
||||
this.displayName = displayName;
|
||||
this.pluginName = pluginName;
|
||||
}
|
||||
|
||||
@@ -56,8 +56,8 @@ public enum PermissionsSystemType {
|
||||
*
|
||||
* @return Display name.
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name;
|
||||
public String getDisplayName() {
|
||||
return this.displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,7 +76,7 @@ public enum PermissionsSystemType {
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
return getDisplayName();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@ public enum PlayerStatePermission implements PermissionNode {
|
||||
BYPASS_FORCE_SURVIVAL("authme.bypassforcesurvival", DefaultPermission.OP_ONLY),
|
||||
|
||||
/**
|
||||
* Permission node to identify VIP users.
|
||||
* When the server is full and someone with this permission joins the server, someone will be kicked.
|
||||
*/
|
||||
IS_VIP("authme.vip", DefaultPermission.OP_ONLY),
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ public class BPermissionsHandler implements PermissionHandler {
|
||||
List<String> groups = getGroups(player);
|
||||
|
||||
// Make sure there is any group available, or return null
|
||||
if (groups.size() == 0)
|
||||
if (groups.isEmpty())
|
||||
return null;
|
||||
|
||||
// Return the first group
|
||||
|
||||
@@ -54,7 +54,7 @@ public class PermissionsBukkitHandler implements PermissionHandler {
|
||||
List<String> groups = getGroups(player);
|
||||
|
||||
// Make sure there is any group available, or return null
|
||||
if (groups.size() == 0)
|
||||
if (groups.isEmpty())
|
||||
return null;
|
||||
|
||||
// Return the first group
|
||||
|
||||
@@ -77,7 +77,7 @@ public class PermissionsExHandler implements PermissionHandler {
|
||||
PermissionUser user = permissionManager.getUser(player);
|
||||
|
||||
List<String> groups = user.getParentIdentifiers(null);
|
||||
if (groups.size() == 0)
|
||||
if (groups.isEmpty())
|
||||
return null;
|
||||
|
||||
return groups.get(0);
|
||||
|
||||
@@ -6,7 +6,7 @@ import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
import fr.xephi.authme.process.ProcessService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.security.PasswordSecurity;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -19,7 +19,7 @@ public class AsyncChangePassword implements AsynchronousProcess {
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private ProcessService processService;
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private PasswordSecurity passwordSecurity;
|
||||
@@ -27,7 +27,8 @@ public class AsyncChangePassword implements AsynchronousProcess {
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
AsyncChangePassword() { }
|
||||
AsyncChangePassword() {
|
||||
}
|
||||
|
||||
|
||||
public void changePassword(final Player player, String oldPassword, String newPassword) {
|
||||
@@ -38,15 +39,15 @@ public class AsyncChangePassword implements AsynchronousProcess {
|
||||
auth.setPassword(hashedPassword);
|
||||
|
||||
if (!dataSource.updatePassword(auth)) {
|
||||
processService.send(player, MessageKey.ERROR);
|
||||
commonService.send(player, MessageKey.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
playerCache.updatePlayer(auth);
|
||||
processService.send(player, MessageKey.PASSWORD_CHANGED_SUCCESS);
|
||||
commonService.send(player, MessageKey.PASSWORD_CHANGED_SUCCESS);
|
||||
ConsoleLogger.info(player.getName() + " changed his password");
|
||||
} else {
|
||||
processService.send(player, MessageKey.WRONG_PASSWORD);
|
||||
commonService.send(player, MessageKey.WRONG_PASSWORD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@ import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
import fr.xephi.authme.process.ProcessService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -18,7 +19,7 @@ import javax.inject.Inject;
|
||||
public class AsyncAddEmail implements AsynchronousProcess {
|
||||
|
||||
@Inject
|
||||
private ProcessService service;
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
@@ -26,6 +27,9 @@ public class AsyncAddEmail implements AsynchronousProcess {
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
AsyncAddEmail() { }
|
||||
|
||||
public void addEmail(Player player, String email) {
|
||||
@@ -37,9 +41,9 @@ public class AsyncAddEmail implements AsynchronousProcess {
|
||||
|
||||
if (currentEmail != null && !"your@email.com".equals(currentEmail)) {
|
||||
service.send(player, MessageKey.USAGE_CHANGE_EMAIL);
|
||||
} else if (!service.validateEmail(email)) {
|
||||
} else if (!validationService.validateEmail(email)) {
|
||||
service.send(player, MessageKey.INVALID_EMAIL);
|
||||
} else if (!service.isEmailFreeForRegistration(email, player)) {
|
||||
} else if (!validationService.isEmailFreeForRegistration(email, player)) {
|
||||
service.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR);
|
||||
} else {
|
||||
auth.setEmail(email);
|
||||
|
||||
@@ -5,7 +5,8 @@ import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
import fr.xephi.authme.process.ProcessService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -17,7 +18,7 @@ import javax.inject.Inject;
|
||||
public class AsyncChangeEmail implements AsynchronousProcess {
|
||||
|
||||
@Inject
|
||||
private ProcessService service;
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
@@ -25,6 +26,9 @@ public class AsyncChangeEmail implements AsynchronousProcess {
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
AsyncChangeEmail() { }
|
||||
|
||||
public void changeEmail(Player player, String oldEmail, String newEmail) {
|
||||
@@ -35,11 +39,11 @@ public class AsyncChangeEmail implements AsynchronousProcess {
|
||||
|
||||
if (currentEmail == null) {
|
||||
service.send(player, MessageKey.USAGE_ADD_EMAIL);
|
||||
} else if (newEmail == null || !service.validateEmail(newEmail)) {
|
||||
} else if (newEmail == null || !validationService.validateEmail(newEmail)) {
|
||||
service.send(player, MessageKey.INVALID_NEW_EMAIL);
|
||||
} else if (!oldEmail.equals(currentEmail)) {
|
||||
service.send(player, MessageKey.INVALID_OLD_EMAIL);
|
||||
} else if (!service.isEmailFreeForRegistration(newEmail, player)) {
|
||||
} else if (!validationService.isEmailFreeForRegistration(newEmail, player)) {
|
||||
service.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR);
|
||||
} else {
|
||||
saveNewEmail(auth, player, newEmail);
|
||||
|
||||
@@ -13,8 +13,9 @@ import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.permission.AuthGroupType;
|
||||
import fr.xephi.authme.permission.PlayerStatePermission;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
import fr.xephi.authme.process.ProcessService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.process.login.AsynchronousLogin;
|
||||
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
@@ -22,9 +23,7 @@ import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
import fr.xephi.authme.task.LimboPlayerTaskManager;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.util.PlayerUtils;
|
||||
import org.apache.commons.lang.reflect.MethodUtils;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
@@ -39,9 +38,6 @@ import static fr.xephi.authme.service.BukkitService.TICKS_PER_SECOND;
|
||||
*/
|
||||
public class AsynchronousJoin implements AsynchronousProcess {
|
||||
|
||||
private static final boolean DISABLE_COLLISIONS = MethodUtils
|
||||
.getAccessibleMethod(LivingEntity.class, "setCollidable", new Class[]{}) != null;
|
||||
|
||||
@Inject
|
||||
private AuthMe plugin;
|
||||
|
||||
@@ -49,7 +45,7 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
||||
private DataSource database;
|
||||
|
||||
@Inject
|
||||
private ProcessService service;
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
@@ -72,23 +68,20 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
||||
@Inject
|
||||
private AsynchronousLogin asynchronousLogin;
|
||||
|
||||
@Inject
|
||||
private CommandManager commandManager;
|
||||
|
||||
AsynchronousJoin() {
|
||||
}
|
||||
|
||||
|
||||
public void processJoin(final Player player) {
|
||||
final String name = player.getName().toLowerCase();
|
||||
final String ip = PlayerUtils.getPlayerIp(player);
|
||||
|
||||
if (isPlayerUnrestricted(name)) {
|
||||
if (service.getProperty(RestrictionSettings.UNRESTRICTED_NAMES).contains(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent player collisions in 1.9
|
||||
if (DISABLE_COLLISIONS) {
|
||||
player.setCollidable(false);
|
||||
}
|
||||
|
||||
if (service.getProperty(RestrictionSettings.FORCE_SURVIVAL_MODE)
|
||||
&& !service.hasPermission(player, PlayerStatePermission.BYPASS_FORCE_SURVIVAL)) {
|
||||
bukkitService.runTask(() -> player.setGameMode(GameMode.SURVIVAL));
|
||||
@@ -115,7 +108,6 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
final boolean isAuthAvailable = database.isAuthAvailable(name);
|
||||
|
||||
if (isAuthAvailable) {
|
||||
@@ -162,26 +154,23 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
||||
|
||||
final int registrationTimeout = service.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
|
||||
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
player.setOp(false);
|
||||
if (!service.getProperty(RestrictionSettings.ALLOW_UNAUTHED_MOVEMENT)
|
||||
&& service.getProperty(RestrictionSettings.REMOVE_SPEED)) {
|
||||
player.setFlySpeed(0.0f);
|
||||
player.setWalkSpeed(0.0f);
|
||||
}
|
||||
player.setNoDamageTicks(registrationTimeout);
|
||||
if (pluginHookService.isEssentialsAvailable() && service.getProperty(HooksSettings.USE_ESSENTIALS_MOTD)) {
|
||||
player.performCommand("motd");
|
||||
}
|
||||
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
||||
// Allow infinite blindness effect
|
||||
int blindTimeOut = (registrationTimeout <= 0) ? 99999 : registrationTimeout;
|
||||
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, blindTimeOut, 2));
|
||||
}
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> {
|
||||
player.setOp(false);
|
||||
if (!service.getProperty(RestrictionSettings.ALLOW_UNAUTHED_MOVEMENT)
|
||||
&& service.getProperty(RestrictionSettings.REMOVE_SPEED)) {
|
||||
player.setFlySpeed(0.0f);
|
||||
player.setWalkSpeed(0.0f);
|
||||
}
|
||||
|
||||
player.setNoDamageTicks(registrationTimeout);
|
||||
if (pluginHookService.isEssentialsAvailable() && service.getProperty(HooksSettings.USE_ESSENTIALS_MOTD)) {
|
||||
player.performCommand("motd");
|
||||
}
|
||||
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
||||
// Allow infinite blindness effect
|
||||
int blindTimeOut = (registrationTimeout <= 0) ? 99999 : registrationTimeout;
|
||||
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, blindTimeOut, 2));
|
||||
}
|
||||
commandManager.runCommandsOnJoin(player);
|
||||
});
|
||||
|
||||
// Timeout and message task
|
||||
@@ -189,10 +178,6 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
||||
limboPlayerTaskManager.registerMessageTask(name, isAuthAvailable);
|
||||
}
|
||||
|
||||
private boolean isPlayerUnrestricted(String name) {
|
||||
return service.getProperty(RestrictionSettings.UNRESTRICTED_NAMES).contains(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the name is restricted based on the restriction settings.
|
||||
*
|
||||
|
||||
@@ -16,7 +16,7 @@ import fr.xephi.authme.permission.PermissionsManager;
|
||||
import fr.xephi.authme.permission.PlayerPermission;
|
||||
import fr.xephi.authme.permission.PlayerStatePermission;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
import fr.xephi.authme.process.ProcessService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.process.SyncProcessManager;
|
||||
import fr.xephi.authme.security.PasswordSecurity;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
@@ -44,7 +44,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private ProcessService service;
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private PermissionsManager permissionsManager;
|
||||
@@ -224,7 +224,11 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
||||
player.setNoDamageTicks(0);
|
||||
|
||||
service.send(player, MessageKey.LOGIN_SUCCESS);
|
||||
displayOtherAccounts(auth, player);
|
||||
|
||||
// Other auths
|
||||
List<String> auths = dataSource.getAllAuthsByIp(auth.getIp());
|
||||
runCommandOtherAccounts(auths, player, auth.getIp());
|
||||
displayOtherAccounts(auths, player);
|
||||
|
||||
final String email = auth.getEmail();
|
||||
if (service.getProperty(EmailSettings.RECALL_PLAYERS)
|
||||
@@ -252,12 +256,29 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
||||
}
|
||||
}
|
||||
|
||||
private void displayOtherAccounts(PlayerAuth auth, Player player) {
|
||||
if (!service.getProperty(RestrictionSettings.DISPLAY_OTHER_ACCOUNTS) || auth == null) {
|
||||
private void runCommandOtherAccounts(List<String> auths, Player player, String ip) {
|
||||
int threshold = service.getProperty(RestrictionSettings.OTHER_ACCOUNTS_CMD_THRESHOLD);
|
||||
String command = service.getProperty(RestrictionSettings.OTHER_ACCOUNTS_CMD);
|
||||
|
||||
if(threshold < 2 || command.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (auths.size() < threshold) {
|
||||
return;
|
||||
}
|
||||
|
||||
bukkitService.dispatchConsoleCommand(command
|
||||
.replaceAll("%playername%", player.getName())
|
||||
.replaceAll("%playerip%", ip)
|
||||
);
|
||||
}
|
||||
|
||||
private void displayOtherAccounts(List<String> auths, Player player) {
|
||||
if (!service.getProperty(RestrictionSettings.DISPLAY_OTHER_ACCOUNTS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> auths = dataSource.getAllAuthsByIp(auth.getIp());
|
||||
if (auths.size() <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -8,38 +8,31 @@ import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.events.LoginEvent;
|
||||
import fr.xephi.authme.events.RestoreInventoryEvent;
|
||||
import fr.xephi.authme.listener.PlayerListener;
|
||||
import fr.xephi.authme.process.ProcessService;
|
||||
import fr.xephi.authme.process.SynchronousProcess;
|
||||
import fr.xephi.authme.service.BungeeService;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.BungeeService;
|
||||
import fr.xephi.authme.service.TeleportationService;
|
||||
import org.apache.commons.lang.reflect.MethodUtils;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static fr.xephi.authme.settings.properties.PluginSettings.KEEP_COLLISIONS_DISABLED;
|
||||
import static fr.xephi.authme.settings.properties.RestrictionSettings.PROTECT_INVENTORY_BEFORE_LOGIN;
|
||||
|
||||
public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
||||
|
||||
private static final boolean RESTORE_COLLISIONS = MethodUtils
|
||||
.getAccessibleMethod(LivingEntity.class, "setCollidable", new Class[]{}) != null;
|
||||
|
||||
@Inject
|
||||
private AuthMe plugin;
|
||||
|
||||
@Inject
|
||||
private BungeeService bungeeService;
|
||||
|
||||
@Inject
|
||||
private ProcessService service;
|
||||
|
||||
@Inject
|
||||
private LimboCache limboCache;
|
||||
|
||||
@@ -55,6 +48,12 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private CommandManager commandManager;
|
||||
|
||||
@Inject
|
||||
private Settings settings;
|
||||
|
||||
ProcessSyncPlayerLogin() {
|
||||
}
|
||||
|
||||
@@ -66,16 +65,6 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
||||
}
|
||||
}
|
||||
|
||||
private void forceCommands(Player player) {
|
||||
for (String command : service.getProperty(RegistrationSettings.FORCE_COMMANDS)) {
|
||||
player.performCommand(command.replace("%p", player.getName()));
|
||||
}
|
||||
for (String command : service.getProperty(RegistrationSettings.FORCE_COMMANDS_AS_CONSOLE)) {
|
||||
Bukkit.getServer().dispatchCommand(
|
||||
Bukkit.getServer().getConsoleSender(), command.replace("%p", player.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
public void processPlayerLogin(Player player) {
|
||||
final String name = player.getName().toLowerCase();
|
||||
|
||||
@@ -88,11 +77,7 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
||||
// because LimboCache#restoreData teleport player to last location.
|
||||
}
|
||||
|
||||
if (RESTORE_COLLISIONS && !service.getProperty(KEEP_COLLISIONS_DISABLED)) {
|
||||
player.setCollidable(true);
|
||||
}
|
||||
|
||||
if (service.getProperty(PROTECT_INVENTORY_BEFORE_LOGIN)) {
|
||||
if (settings.getProperty(PROTECT_INVENTORY_BEFORE_LOGIN)) {
|
||||
restoreInventory(player);
|
||||
}
|
||||
|
||||
@@ -100,19 +85,16 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
||||
teleportationService.teleportOnLogin(player, auth, limbo);
|
||||
|
||||
// We can now display the join message (if delayed)
|
||||
String jm = PlayerListener.joinMessage.get(name);
|
||||
if (jm != null) {
|
||||
if (!jm.isEmpty()) {
|
||||
for (Player p : bukkitService.getOnlinePlayers()) {
|
||||
if (p.isOnline()) {
|
||||
p.sendMessage(jm);
|
||||
}
|
||||
String joinMessage = PlayerListener.joinMessage.remove(name);
|
||||
if (!StringUtils.isEmpty(joinMessage)) {
|
||||
for (Player p : bukkitService.getOnlinePlayers()) {
|
||||
if (p.isOnline()) {
|
||||
p.sendMessage(joinMessage);
|
||||
}
|
||||
}
|
||||
PlayerListener.joinMessage.remove(name);
|
||||
}
|
||||
|
||||
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
||||
if (settings.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
||||
player.removePotionEffect(PotionEffectType.BLINDNESS);
|
||||
}
|
||||
|
||||
@@ -121,20 +103,20 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
||||
player.saveData();
|
||||
|
||||
// Login is done, display welcome message
|
||||
if (service.getProperty(RegistrationSettings.USE_WELCOME_MESSAGE)) {
|
||||
if (service.getProperty(RegistrationSettings.BROADCAST_WELCOME_MESSAGE)) {
|
||||
for (String s : service.getSettings().getWelcomeMessage()) {
|
||||
if (settings.getProperty(RegistrationSettings.USE_WELCOME_MESSAGE)) {
|
||||
if (settings.getProperty(RegistrationSettings.BROADCAST_WELCOME_MESSAGE)) {
|
||||
for (String s : settings.getWelcomeMessage()) {
|
||||
Bukkit.getServer().broadcastMessage(plugin.replaceAllInfo(s, player));
|
||||
}
|
||||
} else {
|
||||
for (String s : service.getSettings().getWelcomeMessage()) {
|
||||
for (String s : settings.getWelcomeMessage()) {
|
||||
player.sendMessage(plugin.replaceAllInfo(s, player));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Login is now finished; we can force all commands
|
||||
forceCommands(player);
|
||||
commandManager.runCommandsOnLogin(player);
|
||||
|
||||
// Send Bungee stuff. The service will check if it is enabled or not.
|
||||
bungeeService.connectPlayer(player);
|
||||
|
||||
@@ -6,7 +6,7 @@ import fr.xephi.authme.data.limbo.LimboCache;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
import fr.xephi.authme.process.ProcessService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.process.SyncProcessManager;
|
||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -19,7 +19,7 @@ public class AsynchronousLogout implements AsynchronousProcess {
|
||||
private DataSource database;
|
||||
|
||||
@Inject
|
||||
private ProcessService service;
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@@ -6,7 +6,7 @@ import fr.xephi.authme.events.LogoutEvent;
|
||||
import fr.xephi.authme.listener.protocollib.ProtocolLibService;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.permission.AuthGroupType;
|
||||
import fr.xephi.authme.process.ProcessService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.process.SynchronousProcess;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
@@ -25,7 +25,7 @@ import static fr.xephi.authme.service.BukkitService.TICKS_PER_SECOND;
|
||||
public class ProcessSynchronousPlayerLogout implements SynchronousProcess {
|
||||
|
||||
@Inject
|
||||
private ProcessService service;
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@@ -7,7 +7,7 @@ import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.datasource.CacheDataSource;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
import fr.xephi.authme.process.ProcessService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.process.SyncProcessManager;
|
||||
import fr.xephi.authme.settings.SpawnLoader;
|
||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
@@ -27,7 +27,7 @@ public class AsynchronousQuit implements AsynchronousProcess {
|
||||
private DataSource database;
|
||||
|
||||
@Inject
|
||||
private ProcessService service;
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@@ -7,7 +7,7 @@ import fr.xephi.authme.mail.SendMailSSL;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
import fr.xephi.authme.process.ProcessService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.process.SyncProcessManager;
|
||||
import fr.xephi.authme.process.login.AsynchronousLogin;
|
||||
import fr.xephi.authme.security.HashAlgorithm;
|
||||
@@ -51,7 +51,7 @@ public class AsyncRegister implements AsynchronousProcess {
|
||||
@Inject
|
||||
private PasswordSecurity passwordSecurity;
|
||||
@Inject
|
||||
private ProcessService service;
|
||||
private CommonService service;
|
||||
@Inject
|
||||
private SyncProcessManager syncProcessManager;
|
||||
@Inject
|
||||
@@ -148,8 +148,12 @@ public class AsyncRegister implements AsynchronousProcess {
|
||||
}
|
||||
database.updateEmail(auth);
|
||||
database.updateSession(auth);
|
||||
sendMailSsl.sendPasswordMail(name, email, password);
|
||||
syncProcessManager.processSyncEmailRegister(player);
|
||||
boolean couldSendMail = sendMailSsl.sendPasswordMail(name, email, password);
|
||||
if (couldSendMail) {
|
||||
syncProcessManager.processSyncEmailRegister(player);
|
||||
} else {
|
||||
service.send(player, MessageKey.EMAIL_SEND_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
private void passwordRegister(final Player player, String password, boolean autoLogin) {
|
||||
|
||||
@@ -3,7 +3,7 @@ package fr.xephi.authme.process.register;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.permission.AuthGroupType;
|
||||
import fr.xephi.authme.process.ProcessService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.process.SynchronousProcess;
|
||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||
import fr.xephi.authme.task.LimboPlayerTaskManager;
|
||||
@@ -16,13 +16,13 @@ import javax.inject.Inject;
|
||||
public class ProcessSyncEmailRegister implements SynchronousProcess {
|
||||
|
||||
@Inject
|
||||
private ProcessService service;
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private LimboPlayerTaskManager limboPlayerTaskManager;
|
||||
|
||||
ProcessSyncEmailRegister() { }
|
||||
|
||||
ProcessSyncEmailRegister() {
|
||||
}
|
||||
|
||||
public void processEmailRegister(Player player) {
|
||||
final String name = player.getName().toLowerCase();
|
||||
|
||||
@@ -4,15 +4,15 @@ import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.limbo.LimboCache;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.permission.AuthGroupType;
|
||||
import fr.xephi.authme.process.ProcessService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.process.SynchronousProcess;
|
||||
import fr.xephi.authme.service.BungeeService;
|
||||
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
import fr.xephi.authme.task.LimboPlayerTaskManager;
|
||||
import fr.xephi.authme.util.PlayerUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -25,7 +25,7 @@ public class ProcessSyncPasswordRegister implements SynchronousProcess {
|
||||
private BungeeService bungeeService;
|
||||
|
||||
@Inject
|
||||
private ProcessService service;
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private LimboCache limboCache;
|
||||
@@ -33,17 +33,10 @@ public class ProcessSyncPasswordRegister implements SynchronousProcess {
|
||||
@Inject
|
||||
private LimboPlayerTaskManager limboPlayerTaskManager;
|
||||
|
||||
ProcessSyncPasswordRegister() {
|
||||
}
|
||||
@Inject
|
||||
private CommandManager commandManager;
|
||||
|
||||
private void forceCommands(Player player) {
|
||||
for (String command : service.getProperty(RegistrationSettings.FORCE_REGISTER_COMMANDS)) {
|
||||
player.performCommand(command.replace("%p", player.getName()));
|
||||
}
|
||||
for (String command : service.getProperty(RegistrationSettings.FORCE_REGISTER_COMMANDS_AS_CONSOLE)) {
|
||||
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(),
|
||||
command.replace("%p", player.getName()));
|
||||
}
|
||||
ProcessSyncPasswordRegister() {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,7 +76,7 @@ public class ProcessSyncPasswordRegister implements SynchronousProcess {
|
||||
}
|
||||
|
||||
// Register is now finished; we can force all commands
|
||||
forceCommands(player);
|
||||
commandManager.runCommandsOnRegister(player);
|
||||
|
||||
// Request login after registration
|
||||
if (service.getProperty(RegistrationSettings.FORCE_LOGIN_AFTER_REGISTER)) {
|
||||
|
||||
@@ -9,7 +9,7 @@ import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.permission.AuthGroupHandler;
|
||||
import fr.xephi.authme.permission.AuthGroupType;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
import fr.xephi.authme.process.ProcessService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.security.PasswordSecurity;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
@@ -31,7 +31,7 @@ public class AsynchronousUnregister implements AsynchronousProcess {
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private ProcessService service;
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private PasswordSecurity passwordSecurity;
|
||||
|
||||
@@ -3,8 +3,7 @@ package fr.xephi.authme.security;
|
||||
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
||||
|
||||
/**
|
||||
* The list of hash algorithms supported by AuthMe. The linked {@link EncryptionMethod} implementation
|
||||
* must be able to be instantiated with the default constructor.
|
||||
* Hash algorithms supported by AuthMe.
|
||||
*/
|
||||
public enum HashAlgorithm {
|
||||
|
||||
@@ -18,8 +17,8 @@ public enum HashAlgorithm {
|
||||
MD5(fr.xephi.authme.security.crypts.MD5.class),
|
||||
MD5VB(fr.xephi.authme.security.crypts.MD5VB.class),
|
||||
MYBB(fr.xephi.authme.security.crypts.MYBB.class),
|
||||
PBKDF2(fr.xephi.authme.security.crypts.CryptPBKDF2.class),
|
||||
PBKDF2DJANGO(fr.xephi.authme.security.crypts.CryptPBKDF2Django.class),
|
||||
PBKDF2(fr.xephi.authme.security.crypts.Pbkdf2.class),
|
||||
PBKDF2DJANGO(fr.xephi.authme.security.crypts.Pbkdf2Django.class),
|
||||
PHPBB(fr.xephi.authme.security.crypts.PHPBB.class),
|
||||
PHPFUSION(fr.xephi.authme.security.crypts.PHPFUSION.class),
|
||||
@Deprecated
|
||||
|
||||
@@ -6,12 +6,14 @@ import fr.xephi.authme.events.PasswordEncryptionEvent;
|
||||
import fr.xephi.authme.initialization.Reloadable;
|
||||
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.settings.EnumSetProperty;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Inject;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Manager class for password-related operations.
|
||||
@@ -31,7 +33,7 @@ public class PasswordSecurity implements Reloadable {
|
||||
private Injector injector;
|
||||
|
||||
private HashAlgorithm algorithm;
|
||||
private boolean supportOldAlgorithm;
|
||||
private Collection<HashAlgorithm> legacyAlgorithms;
|
||||
|
||||
/**
|
||||
* Load or reload the configuration.
|
||||
@@ -40,7 +42,8 @@ public class PasswordSecurity implements Reloadable {
|
||||
@Override
|
||||
public void reload() {
|
||||
this.algorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH);
|
||||
this.supportOldAlgorithm = settings.getProperty(SecuritySettings.SUPPORT_OLD_PASSWORD_HASH);
|
||||
// TODO #1014: Need to cast to specific type because ConfigMe ignores fields of child Property types
|
||||
this.legacyAlgorithms = ((EnumSetProperty<HashAlgorithm>) SecuritySettings.LEGACY_HASHES).asEnumSet(settings);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,7 +86,7 @@ public class PasswordSecurity implements Reloadable {
|
||||
EncryptionMethod method = initializeEncryptionMethodWithEvent(algorithm, playerName);
|
||||
String playerLowerCase = playerName.toLowerCase();
|
||||
return methodMatches(method, password, hashedPassword, playerLowerCase)
|
||||
|| supportOldAlgorithm && compareWithAllEncryptionMethods(password, hashedPassword, playerLowerCase);
|
||||
|| compareWithLegacyHashes(password, hashedPassword, playerLowerCase);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,14 +100,12 @@ public class PasswordSecurity implements Reloadable {
|
||||
*
|
||||
* @return True if there was a password match with another encryption method, false otherwise
|
||||
*/
|
||||
private boolean compareWithAllEncryptionMethods(String password, HashedPassword hashedPassword, String playerName) {
|
||||
for (HashAlgorithm algorithm : HashAlgorithm.values()) {
|
||||
if (!HashAlgorithm.CUSTOM.equals(algorithm)) {
|
||||
EncryptionMethod method = initializeEncryptionMethod(algorithm);
|
||||
if (methodMatches(method, password, hashedPassword, playerName)) {
|
||||
hashPasswordForNewAlgorithm(password, playerName);
|
||||
return true;
|
||||
}
|
||||
private boolean compareWithLegacyHashes(String password, HashedPassword hashedPassword, String playerName) {
|
||||
for (HashAlgorithm algorithm : legacyAlgorithms) {
|
||||
EncryptionMethod method = initializeEncryptionMethod(algorithm);
|
||||
if (methodMatches(method, password, hashedPassword, playerName)) {
|
||||
hashPasswordForNewAlgorithm(password, playerName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
import fr.xephi.authme.security.pbkdf2.PBKDF2Engine;
|
||||
import fr.xephi.authme.security.pbkdf2.PBKDF2Parameters;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@Recommendation(Usage.DOES_NOT_WORK)
|
||||
public class CryptPBKDF2 extends HexSaltedMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
String result = "pbkdf2_sha256$10000$" + salt + "$";
|
||||
PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 10000);
|
||||
PBKDF2Engine engine = new PBKDF2Engine(params);
|
||||
|
||||
return result + Arrays.toString(engine.deriveKey(password, 64));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String password, HashedPassword hashedPassword, String unusedName) {
|
||||
String[] line = hashedPassword.getHash().split("\\$");
|
||||
if (line.length != 4) {
|
||||
return false;
|
||||
}
|
||||
String salt = line[2];
|
||||
String derivedKey = line[3];
|
||||
PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 10000, derivedKey.getBytes());
|
||||
PBKDF2Engine engine = new PBKDF2Engine(params);
|
||||
return engine.verifyKey(password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSaltLength() {
|
||||
return 12;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import fr.xephi.authme.security.HashUtils;
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
@Recommendation(Usage.RECOMMENDED)
|
||||
@Recommendation(Usage.ACCEPTABLE)
|
||||
public class JOOMLA extends HexSaltedMethod {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
/**
|
||||
* Plaintext password storage.
|
||||
*
|
||||
* @deprecated Using this is no longer supported. AuthMe will migrate to SHA256 on startup.
|
||||
*/
|
||||
@Deprecated
|
||||
public class PLAINTEXT extends UnsaltedMethod {
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import de.rtner.misc.BinTools;
|
||||
import de.rtner.security.auth.spi.PBKDF2Engine;
|
||||
import de.rtner.security.auth.spi.PBKDF2Parameters;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@Recommendation(Usage.RECOMMENDED)
|
||||
public class Pbkdf2 extends HexSaltedMethod {
|
||||
|
||||
private static final int DEFAULT_ROUNDS = 10_000;
|
||||
private int numberOfRounds;
|
||||
|
||||
@Inject
|
||||
Pbkdf2(Settings settings) {
|
||||
int configuredRounds = settings.getProperty(SecuritySettings.PBKDF2_NUMBER_OF_ROUNDS);
|
||||
this.numberOfRounds = configuredRounds > 0 ? configuredRounds : DEFAULT_ROUNDS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
String result = "pbkdf2_sha256$" + numberOfRounds + "$" + salt + "$";
|
||||
PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "UTF-8", salt.getBytes(), numberOfRounds);
|
||||
PBKDF2Engine engine = new PBKDF2Engine(params);
|
||||
|
||||
return result + BinTools.bin2hex(engine.deriveKey(password, 64));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String password, HashedPassword hashedPassword, String unusedName) {
|
||||
String[] line = hashedPassword.getHash().split("\\$");
|
||||
if (line.length != 4) {
|
||||
return false;
|
||||
}
|
||||
int iterations;
|
||||
try {
|
||||
iterations = Integer.parseInt(line[1]);
|
||||
} catch (NumberFormatException e) {
|
||||
ConsoleLogger.logException("Cannot read number of rounds for Pbkdf2", e);
|
||||
return false;
|
||||
}
|
||||
String salt = line[2];
|
||||
byte[] derivedKey = BinTools.hex2bin(line[3]);
|
||||
PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "UTF-8", salt.getBytes(), iterations, derivedKey);
|
||||
PBKDF2Engine engine = new PBKDF2Engine(params);
|
||||
return engine.verifyKey(password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSaltLength() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
}
|
||||
+5
-7
@@ -1,15 +1,14 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import de.rtner.security.auth.spi.PBKDF2Engine;
|
||||
import de.rtner.security.auth.spi.PBKDF2Parameters;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.security.crypts.description.AsciiRestricted;
|
||||
import fr.xephi.authme.security.pbkdf2.PBKDF2Engine;
|
||||
import fr.xephi.authme.security.pbkdf2.PBKDF2Parameters;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
@AsciiRestricted
|
||||
public class CryptPBKDF2Django extends HexSaltedMethod {
|
||||
public class Pbkdf2Django extends HexSaltedMethod {
|
||||
|
||||
private static final int DEFAULT_ITERATIONS = 24000;
|
||||
|
||||
@@ -19,7 +18,7 @@ public class CryptPBKDF2Django extends HexSaltedMethod {
|
||||
PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), DEFAULT_ITERATIONS);
|
||||
PBKDF2Engine engine = new PBKDF2Engine(params);
|
||||
|
||||
return result + String.valueOf(DatatypeConverter.printBase64Binary(engine.deriveKey(password, 32)));
|
||||
return result + DatatypeConverter.printBase64Binary(engine.deriveKey(password, 32));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -32,8 +31,7 @@ public class CryptPBKDF2Django extends HexSaltedMethod {
|
||||
try {
|
||||
iterations = Integer.parseInt(line[1]);
|
||||
} catch (NumberFormatException e) {
|
||||
ConsoleLogger.warning("Could not read number of rounds for CryptPBKDF2Django:"
|
||||
+ StringUtils.formatException(e));
|
||||
ConsoleLogger.logException("Could not read number of rounds for Pbkdf2Django:", e);
|
||||
return false;
|
||||
}
|
||||
String salt = line[2];
|
||||
@@ -18,14 +18,14 @@ public class XAUTH extends HexSaltedMethod {
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
String hash = getWhirlpool(salt + password).toLowerCase();
|
||||
int saltPos = (password.length() >= hash.length() ? hash.length() - 1 : password.length());
|
||||
int saltPos = password.length() >= hash.length() ? hash.length() - 1 : password.length();
|
||||
return hash.substring(0, saltPos) + salt + hash.substring(saltPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String password, HashedPassword hashedPassword, String playerName) {
|
||||
String hash = hashedPassword.getHash();
|
||||
int saltPos = (password.length() >= hash.length() ? hash.length() - 1 : password.length());
|
||||
int saltPos = password.length() >= hash.length() ? hash.length() - 1 : password.length();
|
||||
if (saltPos + 12 > hash.length()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
package fr.xephi.authme.security.pbkdf2;
|
||||
|
||||
/*
|
||||
* Free auxiliary functions. Copyright 2007, 2014, Matthias Gärtner
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this software; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Free auxiliary functions
|
||||
*
|
||||
* @author Matthias Gärtner
|
||||
*/
|
||||
public class BinTools {
|
||||
public static final String hex = "0123456789ABCDEF";
|
||||
|
||||
/**
|
||||
* Simple binary-to-hexadecimal conversion.
|
||||
*
|
||||
* @param b
|
||||
* Input bytes. May be <code>null</code>.
|
||||
* @return Hexadecimal representation of b. Uppercase A-F, two characters
|
||||
* per byte. Empty string on <code>null</code> input.
|
||||
*/
|
||||
public static String bin2hex(final byte[] b) {
|
||||
if (b == null) {
|
||||
return "";
|
||||
}
|
||||
StringBuffer sb = new StringBuffer(2 * b.length);
|
||||
for (int i = 0; i < b.length; i++) {
|
||||
int v = (256 + b[i]) % 256;
|
||||
sb.append(hex.charAt((v / 16) & 15));
|
||||
sb.append(hex.charAt((v % 16) & 15));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert hex string to array of bytes.
|
||||
*
|
||||
* @param s
|
||||
* String containing hexadecimal digits. May be <code>null</code>
|
||||
* . On odd length leading zero will be assumed.
|
||||
* @return Array on bytes, non-<code>null</code>.
|
||||
* @throws IllegalArgumentException
|
||||
* when string contains non-hex character
|
||||
*/
|
||||
public static byte[] hex2bin(final String s) {
|
||||
String m = s;
|
||||
if (s == null) {
|
||||
// Allow empty input string.
|
||||
m = "";
|
||||
} else if (s.length() % 2 != 0) {
|
||||
// Assume leading zero for odd string length
|
||||
m = "0" + s;
|
||||
}
|
||||
byte r[] = new byte[m.length() / 2];
|
||||
for (int i = 0, n = 0; i < m.length(); n++) {
|
||||
char h = m.charAt(i++);
|
||||
char l = m.charAt(i++);
|
||||
r[n] = (byte) (hex2bin(h) * 16 + hex2bin(l));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert hex digit to numerical value.
|
||||
*
|
||||
* @param c
|
||||
* 0-9, a-f, A-F allowd.
|
||||
* @return 0-15
|
||||
* @throws IllegalArgumentException
|
||||
* on non-hex character
|
||||
*/
|
||||
public static int hex2bin(char c) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
return (c - '0');
|
||||
}
|
||||
if (c >= 'A' && c <= 'F') {
|
||||
return (c - 'A' + 10);
|
||||
}
|
||||
if (c >= 'a' && c <= 'f') {
|
||||
return (c - 'a' + 10);
|
||||
}
|
||||
throw new IllegalArgumentException("Input string may only contain hex digits, but found '" + c + "'");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
byte b[] = new byte[256];
|
||||
byte bb = 0;
|
||||
for (int i = 0; i < 256; i++) {
|
||||
b[i] = bb++;
|
||||
}
|
||||
String s = bin2hex(b);
|
||||
byte c[] = hex2bin(s);
|
||||
String t = bin2hex(c);
|
||||
if (!s.equals(t)) {
|
||||
throw new AssertionError("Mismatch");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
package fr.xephi.authme.security.pbkdf2;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Default PRF implementation based on standard javax.crypt.Mac mechanisms.
|
||||
* </p>
|
||||
* <p>
|
||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
* </p>
|
||||
* <p>
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* </p>
|
||||
* <p>
|
||||
* For Details, see <a
|
||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
|
||||
* >http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||
* </p>
|
||||
*
|
||||
* @author Matthias Gärtner
|
||||
* @version 1.0
|
||||
*/
|
||||
public class MacBasedPRF implements PRF {
|
||||
|
||||
protected Mac mac;
|
||||
|
||||
protected int hLen;
|
||||
|
||||
protected final String macAlgorithm;
|
||||
|
||||
/**
|
||||
* Create Mac-based Pseudo Random Function.
|
||||
*
|
||||
* @param macAlgorithm Mac algorithm to use, i.e. HMacSHA1 or HMacMD5.
|
||||
*/
|
||||
public MacBasedPRF(String macAlgorithm) {
|
||||
this.macAlgorithm = macAlgorithm;
|
||||
try {
|
||||
mac = Mac.getInstance(macAlgorithm);
|
||||
hLen = mac.getMacLength();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public MacBasedPRF(String macAlgorithm, String provider) {
|
||||
this.macAlgorithm = macAlgorithm;
|
||||
try {
|
||||
mac = Mac.getInstance(macAlgorithm, provider);
|
||||
hLen = mac.getMacLength();
|
||||
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] doFinal(byte[] M) {
|
||||
byte[] r = mac.doFinal(M);
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHLen() {
|
||||
return hLen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(byte[] P) {
|
||||
try {
|
||||
mac.init(new SecretKeySpec(P, macAlgorithm));
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
package fr.xephi.authme.security.pbkdf2;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
* </p>
|
||||
* <p>
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* </p>
|
||||
* <p>
|
||||
* For Details, see <a
|
||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
|
||||
* >http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||
* </p>
|
||||
*
|
||||
* @author Matthias Gärtner
|
||||
* @version 1.0
|
||||
*/
|
||||
public interface PBKDF2 {
|
||||
|
||||
/**
|
||||
* Convert String-based input to internal byte array, then invoke PBKDF2.
|
||||
* Desired key length defaults to Pseudo Random Function block size.
|
||||
*
|
||||
* @param inputPassword Candidate password to compute the derived key for.
|
||||
*
|
||||
* @return internal byte array
|
||||
*/
|
||||
byte[] deriveKey(String inputPassword);
|
||||
|
||||
/**
|
||||
* Convert String-based input to internal byte array, then invoke PBKDF2.
|
||||
*
|
||||
* @param inputPassword Candidate password to compute the derived key for.
|
||||
* @param dkLen Specify desired key length
|
||||
*
|
||||
* @return internal byte array
|
||||
*/
|
||||
byte[] deriveKey(String inputPassword, int dkLen);
|
||||
|
||||
/**
|
||||
* Convert String-based input to internal byte arrays, then invoke PBKDF2
|
||||
* and verify result against the reference data that is supplied in the
|
||||
* PBKDF2Parameters.
|
||||
*
|
||||
* @param inputPassword Candidate password to compute the derived key for.
|
||||
*
|
||||
* @return <code>true</code> password match; <code>false</code> incorrect
|
||||
* password
|
||||
*/
|
||||
boolean verifyKey(String inputPassword);
|
||||
|
||||
/**
|
||||
* Allow reading of configured parameters.
|
||||
*
|
||||
* @return Currently set parameters.
|
||||
*/
|
||||
PBKDF2Parameters getParameters();
|
||||
|
||||
/**
|
||||
* Allow setting of configured parameters.
|
||||
*
|
||||
* @param parameters PBKDF2Parameters
|
||||
*/
|
||||
void setParameters(PBKDF2Parameters parameters);
|
||||
|
||||
/**
|
||||
* Get currently set Pseudo Random Function.
|
||||
*
|
||||
* @return Currently set Pseudo Random Function
|
||||
*/
|
||||
PRF getPseudoRandomFunction();
|
||||
|
||||
/**
|
||||
* Set the Pseudo Random Function to use. Note that deriveKeys/getPRF does
|
||||
* init this object using the supplied candidate password. If this is
|
||||
* undesired, one has to override getPRF.
|
||||
*
|
||||
* @param prf Pseudo Random Function to set.
|
||||
*/
|
||||
void setPseudoRandomFunction(PRF prf);
|
||||
}
|
||||
@@ -1,346 +0,0 @@
|
||||
package fr.xephi.authme.security.pbkdf2;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Request for Comments: 2898 PKCS #5: Password-Based Cryptography Specification
|
||||
* </p><p>
|
||||
* Version 2.0
|
||||
* </p>
|
||||
* <p>
|
||||
* PBKDF2 (P, S, c, dkLen)
|
||||
* </p>
|
||||
* Options:
|
||||
* <ul>
|
||||
* <li>PRF underlying pseudorandom function (hLen denotes the length in octets
|
||||
* of the pseudorandom function output). PRF is pluggable.</li>
|
||||
* </ul>
|
||||
* Input:
|
||||
* <ul>
|
||||
* <li>P password, an octet string</li>
|
||||
* <li>S salt, an octet string</li>
|
||||
* <li>c iteration count, a positive integer</li>
|
||||
* <li>dkLen intended length in octets of the derived key, a positive integer,
|
||||
* at most (2^32 - 1) * hLen</li>
|
||||
* </ul>
|
||||
* Output:
|
||||
* <ul>
|
||||
* <li>DK derived key, a dkLen-octet string</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
* </p>
|
||||
* <p>
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* </p>
|
||||
* <p>
|
||||
* For Details, see
|
||||
* <a href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html" >http://www.
|
||||
* gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||
* </p>
|
||||
*
|
||||
* @author Matthias Gärtner
|
||||
* @version 1.0
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898</a>
|
||||
*/
|
||||
public class PBKDF2Engine implements PBKDF2 {
|
||||
|
||||
protected PBKDF2Parameters parameters;
|
||||
|
||||
protected PRF prf;
|
||||
|
||||
/**
|
||||
* Constructor for PBKDF2 implementation object. PBKDF2 parameters must be
|
||||
* passed later.
|
||||
*/
|
||||
public PBKDF2Engine() {
|
||||
this.parameters = null;
|
||||
prf = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for PBKDF2 implementation object. PBKDF2 parameters are
|
||||
* passed so that this implementation knows iteration count, method to use
|
||||
* and String encoding.
|
||||
*
|
||||
* @param parameters Data holder for iteration count, method to use et cetera.
|
||||
*/
|
||||
public PBKDF2Engine(PBKDF2Parameters parameters) {
|
||||
this.parameters = parameters;
|
||||
prf = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for PBKDF2 implementation object. PBKDF2 parameters are
|
||||
* passed so that this implementation knows iteration count, method to use
|
||||
* and String encoding.
|
||||
*
|
||||
* @param parameters Data holder for iteration count, method to use et cetera.
|
||||
* @param prf Supply customer Pseudo Random Function.
|
||||
*/
|
||||
public PBKDF2Engine(PBKDF2Parameters parameters, PRF prf) {
|
||||
this.parameters = parameters;
|
||||
this.prf = prf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience client function. Convert supplied password with random 8-byte
|
||||
* salt and 1000 iterations using HMacSHA1. Assume that password is in
|
||||
* ISO-8559-1 encoding. Output result as
|
||||
* "Salt:iteration-count:PBKDF2" with binary data in hexadecimal
|
||||
* encoding.
|
||||
* <p>
|
||||
* Example: Password "password" (without the quotes) leads to
|
||||
* 48290A0B96C426C3:1000:973899B1D4AFEB3ED371060D0797E0EE0142BD04
|
||||
* </p>
|
||||
* @param args Supply the password as argument.
|
||||
*
|
||||
* @throws IOException an ioexception occured
|
||||
* @throws NoSuchAlgorithmException a NoSuchAlgorithmException occured
|
||||
*/
|
||||
public static void main(String[] args)
|
||||
throws IOException, NoSuchAlgorithmException {
|
||||
String password = "password";
|
||||
String candidate = null;
|
||||
PBKDF2Formatter formatter = new PBKDF2HexFormatter();
|
||||
|
||||
if (args.length >= 1) {
|
||||
password = args[0];
|
||||
}
|
||||
if (args.length >= 2) {
|
||||
candidate = args[1];
|
||||
}
|
||||
if (candidate == null) {
|
||||
// Creation mode
|
||||
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
|
||||
byte[] salt = new byte[8];
|
||||
sr.nextBytes(salt);
|
||||
int iterations = 1000;
|
||||
PBKDF2Parameters p = new PBKDF2Parameters("HmacSHA1", "ISO-8859-1", salt, iterations);
|
||||
PBKDF2Engine e = new PBKDF2Engine(p);
|
||||
p.setDerivedKey(e.deriveKey(password));
|
||||
candidate = formatter.toString(p);
|
||||
} else {
|
||||
// Verification mode
|
||||
PBKDF2Parameters p = new PBKDF2Parameters();
|
||||
p.setHashAlgorithm("HmacSHA1");
|
||||
p.setHashCharset("ISO-8859-1");
|
||||
if (formatter.fromString(p, candidate)) {
|
||||
throw new IllegalArgumentException("Candidate data does not have correct format (\"" + candidate + "\")");
|
||||
}
|
||||
PBKDF2Engine e = new PBKDF2Engine(p);
|
||||
boolean verifyOK = e.verifyKey(password);
|
||||
System.exit(verifyOK ? 0 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] deriveKey(String inputPassword) {
|
||||
return deriveKey(inputPassword, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] deriveKey(String inputPassword, int dkLen) {
|
||||
byte[] r = null;
|
||||
byte[] P = null;
|
||||
String charset = parameters.getHashCharset();
|
||||
if (inputPassword == null) {
|
||||
inputPassword = "";
|
||||
}
|
||||
try {
|
||||
if (charset == null) {
|
||||
P = inputPassword.getBytes();
|
||||
} else {
|
||||
P = inputPassword.getBytes(charset);
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
assertPRF(P);
|
||||
if (dkLen == 0) {
|
||||
dkLen = prf.getHLen();
|
||||
}
|
||||
r = PBKDF2(prf, parameters.getSalt(), parameters.getIterationCount(), dkLen);
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verifyKey(String inputPassword) {
|
||||
byte[] referenceKey = getParameters().getDerivedKey();
|
||||
if (referenceKey == null || referenceKey.length == 0) {
|
||||
return false;
|
||||
}
|
||||
byte[] inputKey = deriveKey(inputPassword, referenceKey.length);
|
||||
|
||||
if (inputKey == null || inputKey.length != referenceKey.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < inputKey.length; i++) {
|
||||
if (inputKey[i] != referenceKey[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method. Default implementation is (H)MAC-based. To be overridden
|
||||
* in derived classes.
|
||||
*
|
||||
* @param P User-supplied candidate password as array of bytes.
|
||||
*/
|
||||
protected void assertPRF(byte[] P) {
|
||||
if (prf == null) {
|
||||
prf = new MacBasedPRF(parameters.getHashAlgorithm());
|
||||
}
|
||||
prf.init(P);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PRF getPseudoRandomFunction() {
|
||||
return prf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPseudoRandomFunction(PRF prf) {
|
||||
this.prf = prf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Core Password Based Key Derivation Function 2.
|
||||
*
|
||||
* @param prf Pseudo Random Function (i.e. HmacSHA1)
|
||||
* @param S Salt as array of bytes. <code>null</code> means no salt.
|
||||
* @param c Iteration count (see RFC 2898 4.2)
|
||||
* @param dkLen desired length of derived key.
|
||||
*
|
||||
* @return internal byte array * @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2</a>
|
||||
*/
|
||||
protected byte[] PBKDF2(PRF prf, byte[] S, int c, int dkLen) {
|
||||
if (S == null) {
|
||||
S = new byte[0];
|
||||
}
|
||||
int hLen = prf.getHLen();
|
||||
int l = ceil(dkLen, hLen);
|
||||
int r = dkLen - (l - 1) * hLen;
|
||||
byte T[] = new byte[l * hLen];
|
||||
int ti_offset = 0;
|
||||
for (int i = 1; i <= l; i++) {
|
||||
_F(T, ti_offset, prf, S, c, i);
|
||||
ti_offset += hLen;
|
||||
}
|
||||
if (r < hLen) {
|
||||
// Incomplete last block
|
||||
byte DK[] = new byte[dkLen];
|
||||
System.arraycopy(T, 0, DK, 0, dkLen);
|
||||
return DK;
|
||||
}
|
||||
return T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Integer division with ceiling function.
|
||||
*
|
||||
* @param a Integer
|
||||
* @param b Integer
|
||||
*
|
||||
* @return ceil(a/b) * @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step
|
||||
* 2.</a>
|
||||
*/
|
||||
protected int ceil(int a, int b) {
|
||||
int m = 0;
|
||||
if (a % b > 0) {
|
||||
m = 1;
|
||||
}
|
||||
return a / b + m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function F.
|
||||
*
|
||||
* @param dest Destination byte buffer
|
||||
* @param offset Offset into destination byte buffer
|
||||
* @param prf Pseudo Random Function
|
||||
* @param S Salt as array of bytes
|
||||
* @param c Iteration count
|
||||
* @param blockIndex Integer
|
||||
*
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step
|
||||
* 3.</a>
|
||||
*/
|
||||
protected void _F(byte[] dest, int offset, PRF prf, byte[] S, int c,
|
||||
int blockIndex) {
|
||||
int hLen = prf.getHLen();
|
||||
byte U_r[] = new byte[hLen];
|
||||
|
||||
// U0 = S || INT (i);
|
||||
byte U_i[] = new byte[S.length + 4];
|
||||
System.arraycopy(S, 0, U_i, 0, S.length);
|
||||
INT(U_i, S.length, blockIndex);
|
||||
|
||||
for (int i = 0; i < c; i++) {
|
||||
U_i = prf.doFinal(U_i);
|
||||
xor(U_r, U_i);
|
||||
}
|
||||
System.arraycopy(U_r, 0, dest, offset, hLen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Block-Xor. Xor source bytes into destination byte buffer. Destination
|
||||
* buffer must be same length or less than source buffer.
|
||||
*
|
||||
* @param dest byte array
|
||||
* @param src byte array
|
||||
*/
|
||||
protected void xor(byte[] dest, byte[] src) {
|
||||
for (int i = 0; i < dest.length; i++) {
|
||||
dest[i] ^= src[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Four-octet encoding of the integer i, most significant octet first.
|
||||
*
|
||||
* @param dest byte array
|
||||
* @param offset Integer
|
||||
* @param i Integer
|
||||
*
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step
|
||||
* 3.</a>
|
||||
*/
|
||||
protected void INT(byte[] dest, int offset, int i) {
|
||||
dest[offset] = (byte) (i / (256 * 256 * 256));
|
||||
dest[offset + 1] = (byte) (i / (256 * 256));
|
||||
dest[offset + 2] = (byte) (i / (256));
|
||||
dest[offset + 3] = (byte) (i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PBKDF2Parameters getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParameters(PBKDF2Parameters parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package fr.xephi.authme.security.pbkdf2;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
* </p>
|
||||
* <p>
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* </p>
|
||||
* <p>
|
||||
* For Details, see <a
|
||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
|
||||
* >http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||
* </p>
|
||||
*
|
||||
* @author Matthias Gärtner
|
||||
* @version 1.0
|
||||
*/
|
||||
public interface PBKDF2Formatter {
|
||||
|
||||
/**
|
||||
* Convert parameters to String.
|
||||
*
|
||||
* @param p Parameters object to output.
|
||||
*
|
||||
* @return String representation
|
||||
*/
|
||||
String toString(PBKDF2Parameters p);
|
||||
|
||||
/**
|
||||
* Convert String to parameters. Depending on actual implementation, it may
|
||||
* be required to set further fields externally.
|
||||
*
|
||||
* @param s String representation of parameters to decode.
|
||||
* @param p PBKDF2Parameters
|
||||
*
|
||||
* @return <code>false</code> syntax OK, <code>true</code> some syntax
|
||||
* issue.
|
||||
*/
|
||||
boolean fromString(PBKDF2Parameters p, String s);
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package fr.xephi.authme.security.pbkdf2;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
* </p>
|
||||
* <p>
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* </p>
|
||||
* <p>
|
||||
* For Details, see <a
|
||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
|
||||
* >http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||
* </p>
|
||||
*
|
||||
* @author Matthias Gärtner
|
||||
* @version 1.0
|
||||
*/
|
||||
public class PBKDF2HexFormatter implements PBKDF2Formatter {
|
||||
|
||||
@Override
|
||||
public boolean fromString(PBKDF2Parameters p, String s) {
|
||||
if (p == null || s == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String[] p123 = s.split(":");
|
||||
if (p123.length != 3) {
|
||||
return true;
|
||||
}
|
||||
|
||||
byte salt[] = BinTools.hex2bin(p123[0]);
|
||||
int iterationCount = Integer.parseInt(p123[1]);
|
||||
byte bDK[] = BinTools.hex2bin(p123[2]);
|
||||
|
||||
p.setSalt(salt);
|
||||
p.setIterationCount(iterationCount);
|
||||
p.setDerivedKey(bDK);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(PBKDF2Parameters p) {
|
||||
String s = BinTools.bin2hex(p.getSalt()) + ":" + String.valueOf(p.getIterationCount()) + ":" + BinTools.bin2hex(p.getDerivedKey());
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
package fr.xephi.authme.security.pbkdf2;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parameter data holder for PBKDF2 configuration.
|
||||
* </p>
|
||||
* <p>
|
||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
* </p>
|
||||
* <p>
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* </p>
|
||||
* <p>
|
||||
* For Details, see <a
|
||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
|
||||
* >http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||
* </p>
|
||||
*
|
||||
* @author Matthias Gärtner
|
||||
* @version 1.0
|
||||
*/
|
||||
public class PBKDF2Parameters {
|
||||
|
||||
protected byte[] salt;
|
||||
|
||||
protected int iterationCount;
|
||||
|
||||
protected String hashAlgorithm;
|
||||
|
||||
protected String hashCharset;
|
||||
|
||||
/**
|
||||
* The derived key is actually only a convenience to store a reference
|
||||
* derived key. It is not used during computation.
|
||||
*/
|
||||
protected byte[] derivedKey;
|
||||
|
||||
/**
|
||||
* Constructor. Defaults to <code>null</code> for byte arrays, UTF-8 as
|
||||
* character set and 1000 for iteration count.
|
||||
*/
|
||||
public PBKDF2Parameters() {
|
||||
this.hashAlgorithm = null;
|
||||
this.hashCharset = "UTF-8";
|
||||
this.salt = null;
|
||||
this.iterationCount = 1000;
|
||||
this.derivedKey = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param hashAlgorithm for example HMacSHA1 or HMacMD5
|
||||
* @param hashCharset for example UTF-8
|
||||
* @param salt Salt as byte array, may be <code>null</code> (not recommended)
|
||||
* @param iterationCount Number of iterations to execute. Recommended value 1000.
|
||||
*/
|
||||
public PBKDF2Parameters(String hashAlgorithm, String hashCharset,
|
||||
byte[] salt, int iterationCount) {
|
||||
this.hashAlgorithm = hashAlgorithm;
|
||||
this.hashCharset = hashCharset;
|
||||
this.salt = salt;
|
||||
this.iterationCount = iterationCount;
|
||||
this.derivedKey = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param hashAlgorithm for example HMacSHA1 or HMacMD5
|
||||
* @param hashCharset for example UTF-8
|
||||
* @param salt Salt as byte array, may be <code>null</code> (not recommended)
|
||||
* @param iterationCount Number of iterations to execute. Recommended value 1000.
|
||||
* @param derivedKey Convenience data holder, not used during computation.
|
||||
*/
|
||||
public PBKDF2Parameters(String hashAlgorithm, String hashCharset,
|
||||
byte[] salt, int iterationCount, byte[] derivedKey) {
|
||||
this.hashAlgorithm = hashAlgorithm;
|
||||
this.hashCharset = hashCharset;
|
||||
this.salt = salt;
|
||||
this.iterationCount = iterationCount;
|
||||
this.derivedKey = derivedKey;
|
||||
}
|
||||
|
||||
public int getIterationCount() {
|
||||
return iterationCount;
|
||||
}
|
||||
|
||||
public void setIterationCount(int iterationCount) {
|
||||
this.iterationCount = iterationCount;
|
||||
}
|
||||
|
||||
public byte[] getSalt() {
|
||||
return salt;
|
||||
}
|
||||
|
||||
public void setSalt(byte[] salt) {
|
||||
this.salt = salt;
|
||||
}
|
||||
|
||||
public byte[] getDerivedKey() {
|
||||
return derivedKey;
|
||||
}
|
||||
|
||||
public void setDerivedKey(byte[] derivedKey) {
|
||||
this.derivedKey = derivedKey;
|
||||
}
|
||||
|
||||
public String getHashAlgorithm() {
|
||||
return hashAlgorithm;
|
||||
}
|
||||
|
||||
public void setHashAlgorithm(String hashAlgorithm) {
|
||||
this.hashAlgorithm = hashAlgorithm;
|
||||
}
|
||||
|
||||
public String getHashCharset() {
|
||||
return hashCharset;
|
||||
}
|
||||
|
||||
public void setHashCharset(String hashCharset) {
|
||||
this.hashCharset = hashCharset;
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package fr.xephi.authme.security.pbkdf2;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
* </p>
|
||||
* <p>
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* </p>
|
||||
* <p>
|
||||
* For Details, see <a
|
||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
|
||||
* >http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||
* </p>
|
||||
*
|
||||
* @author Matthias Gärtner
|
||||
* @version 1.0
|
||||
*/
|
||||
public interface PRF {
|
||||
|
||||
/**
|
||||
* Initialize this instance with the user-supplied password.
|
||||
*
|
||||
* @param P The password supplied as array of bytes. It is the caller's
|
||||
* task to convert String passwords to bytes as appropriate.
|
||||
*/
|
||||
void init(byte[] P);
|
||||
|
||||
/**
|
||||
* Pseudo Random Function
|
||||
*
|
||||
* @param M Input data/message etc. Together with any data supplied during
|
||||
* initilization.
|
||||
*
|
||||
* @return Random bytes of hLen length.
|
||||
*/
|
||||
byte[] doFinal(byte[] M);
|
||||
|
||||
/**
|
||||
* Query block size of underlying algorithm/mechanism.
|
||||
*
|
||||
* @return block size
|
||||
*/
|
||||
int getHLen();
|
||||
}
|
||||
@@ -7,10 +7,11 @@ import fr.xephi.authme.permission.AdminPermission;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.ProtectionSettings;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import static fr.xephi.authme.service.BukkitService.TICKS_PER_MINUTE;
|
||||
@@ -25,18 +26,18 @@ public class AntiBotService implements SettingsDependent {
|
||||
private final Messages messages;
|
||||
private final PermissionsManager permissionsManager;
|
||||
private final BukkitService bukkitService;
|
||||
|
||||
private final CopyOnWriteArrayList<String> antibotKicked = new CopyOnWriteArrayList<>();
|
||||
// Settings
|
||||
private int duration;
|
||||
private int sensibility;
|
||||
private int delay;
|
||||
|
||||
private int interval;
|
||||
// Service status
|
||||
private AntiBotStatus antiBotStatus;
|
||||
private boolean startup;
|
||||
private BukkitTask disableTask;
|
||||
private int antibotPlayers;
|
||||
private final CopyOnWriteArrayList<String> antibotKicked = new CopyOnWriteArrayList<>();
|
||||
private Instant lastFlaggedJoin;
|
||||
private int flagged = 0;
|
||||
|
||||
@Inject
|
||||
AntiBotService(Settings settings, Messages messages, PermissionsManager permissionsManager,
|
||||
@@ -47,7 +48,7 @@ public class AntiBotService implements SettingsDependent {
|
||||
this.bukkitService = bukkitService;
|
||||
// Initial status
|
||||
disableTask = null;
|
||||
antibotPlayers = 0;
|
||||
flagged = 0;
|
||||
antiBotStatus = AntiBotStatus.DISABLED;
|
||||
startup = true;
|
||||
// Load settings and start if required
|
||||
@@ -60,6 +61,7 @@ public class AntiBotService implements SettingsDependent {
|
||||
duration = settings.getProperty(ProtectionSettings.ANTIBOT_DURATION);
|
||||
sensibility = settings.getProperty(ProtectionSettings.ANTIBOT_SENSIBILITY);
|
||||
delay = settings.getProperty(ProtectionSettings.ANTIBOT_DELAY);
|
||||
interval = settings.getProperty(ProtectionSettings.ANTIBOT_INTERVAL);
|
||||
|
||||
// Stop existing protection
|
||||
stopProtection();
|
||||
@@ -71,15 +73,10 @@ public class AntiBotService implements SettingsDependent {
|
||||
}
|
||||
|
||||
// Bot activation task
|
||||
Runnable enableTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
antiBotStatus = AntiBotStatus.LISTENING;
|
||||
}
|
||||
};
|
||||
Runnable enableTask = () -> antiBotStatus = AntiBotStatus.LISTENING;
|
||||
|
||||
// Delay the schedule on first start
|
||||
if(startup) {
|
||||
if (startup) {
|
||||
bukkitService.scheduleSyncDelayedTask(enableTask, delay * TICKS_PER_SECOND);
|
||||
startup = false;
|
||||
} else {
|
||||
@@ -94,19 +91,12 @@ public class AntiBotService implements SettingsDependent {
|
||||
antiBotStatus = AntiBotStatus.ACTIVE;
|
||||
|
||||
// Inform admins
|
||||
for (Player player : bukkitService.getOnlinePlayers()) {
|
||||
if (permissionsManager.hasPermission(player, AdminPermission.ANTIBOT_MESSAGES)) {
|
||||
messages.send(player, MessageKey.ANTIBOT_AUTO_ENABLED_MESSAGE);
|
||||
}
|
||||
}
|
||||
bukkitService.getOnlinePlayers().stream()
|
||||
.filter(player -> permissionsManager.hasPermission(player, AdminPermission.ANTIBOT_MESSAGES))
|
||||
.forEach(player -> messages.send(player, MessageKey.ANTIBOT_AUTO_ENABLED_MESSAGE));
|
||||
|
||||
// Schedule auto-disable
|
||||
disableTask = bukkitService.runTaskLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
stopProtection();
|
||||
}
|
||||
}, duration * TICKS_PER_MINUTE);
|
||||
disableTask = bukkitService.runTaskLater(this::stopProtection, duration * TICKS_PER_MINUTE);
|
||||
}
|
||||
|
||||
private void stopProtection() {
|
||||
@@ -116,7 +106,7 @@ public class AntiBotService implements SettingsDependent {
|
||||
|
||||
// Change status
|
||||
antiBotStatus = AntiBotStatus.LISTENING;
|
||||
antibotPlayers = 0;
|
||||
flagged = 0;
|
||||
antibotKicked.clear();
|
||||
|
||||
// Cancel auto-disable task
|
||||
@@ -124,11 +114,10 @@ public class AntiBotService implements SettingsDependent {
|
||||
disableTask = null;
|
||||
|
||||
// Inform admins
|
||||
for (Player player : bukkitService.getOnlinePlayers()) {
|
||||
if (permissionsManager.hasPermission(player, AdminPermission.ANTIBOT_MESSAGES)) {
|
||||
messages.send(player, MessageKey.ANTIBOT_AUTO_DISABLED_MESSAGE, Integer.toString(duration));
|
||||
}
|
||||
}
|
||||
String durationString = Integer.toString(duration);
|
||||
bukkitService.getOnlinePlayers().stream()
|
||||
.filter(player -> permissionsManager.hasPermission(player, AdminPermission.ANTIBOT_MESSAGES))
|
||||
.forEach(player -> messages.send(player, MessageKey.ANTIBOT_AUTO_DISABLED_MESSAGE, durationString));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,36 +144,33 @@ public class AntiBotService implements SettingsDependent {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a player joining the server and checks if AntiBot needs to be activated.
|
||||
*/
|
||||
public void handlePlayerJoin() {
|
||||
if (antiBotStatus != AntiBotStatus.LISTENING) {
|
||||
return;
|
||||
}
|
||||
|
||||
antibotPlayers++;
|
||||
if (antibotPlayers > sensibility) {
|
||||
startProtection();
|
||||
return;
|
||||
}
|
||||
|
||||
bukkitService.scheduleSyncDelayedTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
antibotPlayers--;
|
||||
}
|
||||
}, 5 * TICKS_PER_SECOND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if a player should be kicked due to antibot service.
|
||||
*
|
||||
* @param isAuthAvailable if the player is registered
|
||||
* @return if the player should be kicked
|
||||
*/
|
||||
public boolean shouldKick(boolean isAuthAvailable) {
|
||||
return !isAuthAvailable && (antiBotStatus == AntiBotStatus.ACTIVE);
|
||||
public boolean shouldKick() {
|
||||
if (antiBotStatus == AntiBotStatus.DISABLED) {
|
||||
return false;
|
||||
} else if (antiBotStatus == AntiBotStatus.ACTIVE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lastFlaggedJoin == null) {
|
||||
lastFlaggedJoin = Instant.now();
|
||||
}
|
||||
if (ChronoUnit.SECONDS.between(lastFlaggedJoin, Instant.now()) <= interval) {
|
||||
flagged++;
|
||||
} else {
|
||||
// reset to 1 because this player is also count as not registered
|
||||
flagged = 1;
|
||||
lastFlaggedJoin = null;
|
||||
}
|
||||
if (flagged > sensibility) {
|
||||
startProtection();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -104,36 +104,22 @@ public class BackupService {
|
||||
dirBackup.mkdir();
|
||||
}
|
||||
String backupWindowsPath = settings.getProperty(BackupSettings.MYSQL_WINDOWS_PATH);
|
||||
if (checkWindows(backupWindowsPath)) {
|
||||
String executeCmd = backupWindowsPath + "\\bin\\mysqldump.exe -u " + dbUserName + " -p" + dbPassword + " " + dbName + " --tables " + tblname + " -r " + path + ".sql";
|
||||
Process runtimeProcess;
|
||||
try {
|
||||
runtimeProcess = Runtime.getRuntime().exec(executeCmd);
|
||||
int processComplete = runtimeProcess.waitFor();
|
||||
if (processComplete == 0) {
|
||||
ConsoleLogger.info("Backup created successfully.");
|
||||
return true;
|
||||
} else {
|
||||
ConsoleLogger.warning("Could not create the backup! (Windows)");
|
||||
}
|
||||
} catch (IOException | InterruptedException e) {
|
||||
ConsoleLogger.logException("Error during Windows backup:", e);
|
||||
}
|
||||
} else {
|
||||
String executeCmd = "mysqldump -u " + dbUserName + " -p" + dbPassword + " " + dbName + " --tables " + tblname + " -r " + path + ".sql";
|
||||
Process runtimeProcess;
|
||||
try {
|
||||
runtimeProcess = Runtime.getRuntime().exec(executeCmd);
|
||||
int processComplete = runtimeProcess.waitFor();
|
||||
if (processComplete == 0) {
|
||||
ConsoleLogger.info("Backup created successfully.");
|
||||
return true;
|
||||
} else {
|
||||
ConsoleLogger.warning("Could not create the backup!");
|
||||
}
|
||||
} catch (IOException | InterruptedException e) {
|
||||
ConsoleLogger.logException("Error during backup:", e);
|
||||
boolean isUsingWindows = checkWindows(backupWindowsPath);
|
||||
String backupCommand = isUsingWindows
|
||||
? backupWindowsPath + "\\bin\\mysqldump.exe" + buildMysqlDumpArguments()
|
||||
: "mysqldump" + buildMysqlDumpArguments();
|
||||
|
||||
try {
|
||||
Process runtimeProcess = Runtime.getRuntime().exec(backupCommand);
|
||||
int processComplete = runtimeProcess.waitFor();
|
||||
if (processComplete == 0) {
|
||||
ConsoleLogger.info("Backup created successfully. (Using Windows = " + isUsingWindows + ")");
|
||||
return true;
|
||||
} else {
|
||||
ConsoleLogger.warning("Could not create the backup! (Using Windows = " + isUsingWindows + ")");
|
||||
}
|
||||
} catch (IOException | InterruptedException e) {
|
||||
ConsoleLogger.logException("Error during backup (using Windows = " + isUsingWindows + "):", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -173,6 +159,16 @@ public class BackupService {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the command line arguments to pass along when running the {@code mysqldump} command.
|
||||
*
|
||||
* @return the mysqldump command line arguments
|
||||
*/
|
||||
private String buildMysqlDumpArguments() {
|
||||
return " -u " + dbUserName + " -p" + dbPassword + " " + dbName
|
||||
+ " --tables " + tblname + " -r " + path + ".sql";
|
||||
}
|
||||
|
||||
private static void copy(String src, String dst) throws IOException {
|
||||
InputStream in = new FileInputStream(src);
|
||||
OutputStream out = new FileOutputStream(dst);
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.bukkit.BanList;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
@@ -17,6 +18,7 @@ import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
@@ -40,7 +42,8 @@ public class BukkitService implements SettingsDependent {
|
||||
private Method getOnlinePlayers;
|
||||
private boolean useAsyncTasks;
|
||||
|
||||
public BukkitService(AuthMe authMe, Settings settings) {
|
||||
@Inject
|
||||
BukkitService(AuthMe authMe, Settings settings) {
|
||||
this.authMe = authMe;
|
||||
getOnlinePlayersIsCollection = initializeOnlinePlayersIsCollectionField();
|
||||
reload(settings);
|
||||
@@ -271,6 +274,27 @@ public class BukkitService implements SettingsDependent {
|
||||
return Bukkit.getWorld(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches a command on this server, and executes it if found.
|
||||
*
|
||||
* @param sender the apparent sender of the command
|
||||
* @param commandLine the command + arguments. Example: <code>test abc 123</code>
|
||||
* @return returns false if no target is found
|
||||
*/
|
||||
public boolean dispatchCommand(CommandSender sender, String commandLine) {
|
||||
return Bukkit.dispatchCommand(sender, commandLine);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches a command to be run as console user on this server, and executes it if found.
|
||||
*
|
||||
* @param commandLine the command + arguments. Example: <code>test abc 123</code>
|
||||
* @return returns false if no target is found
|
||||
*/
|
||||
public boolean dispatchConsoleCommand(String commandLine) {
|
||||
return Bukkit.dispatchCommand(Bukkit.getConsoleSender(), commandLine);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload(Settings settings) {
|
||||
useAsyncTasks = settings.getProperty(PluginSettings.USE_ASYNC_TASKS);
|
||||
@@ -307,5 +331,4 @@ public class BukkitService implements SettingsDependent {
|
||||
public BanEntry banIp(String ip, String reason, Date expires, String source) {
|
||||
return Bukkit.getServer().getBanList(BanList.Type.IP).addBan(ip, reason, expires, source);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+25
-29
@@ -1,4 +1,4 @@
|
||||
package fr.xephi.authme.process;
|
||||
package fr.xephi.authme.service;
|
||||
|
||||
import com.github.authme.configme.properties.Property;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
@@ -8,16 +8,15 @@ import fr.xephi.authme.permission.AuthGroupType;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Service for asynchronous and synchronous processes.
|
||||
* Service for the most common operations regarding settings, messages and permissions.
|
||||
*/
|
||||
public class ProcessService {
|
||||
public class CommonService {
|
||||
|
||||
@Inject
|
||||
private Settings settings;
|
||||
@@ -25,17 +24,17 @@ public class ProcessService {
|
||||
@Inject
|
||||
private Messages messages;
|
||||
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
@Inject
|
||||
private PermissionsManager permissionsManager;
|
||||
|
||||
@Inject
|
||||
private AuthGroupHandler authGroupHandler;
|
||||
|
||||
CommonService() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a property's value.
|
||||
* Retrieves a property's value.
|
||||
*
|
||||
* @param property the property to retrieve
|
||||
* @param <T> the property type
|
||||
@@ -46,16 +45,7 @@ public class ProcessService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the settings manager.
|
||||
*
|
||||
* @return settings manager
|
||||
*/
|
||||
public Settings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to the command sender.
|
||||
* Sends a message to the command sender.
|
||||
*
|
||||
* @param sender the command sender
|
||||
* @param key the message key
|
||||
@@ -65,7 +55,7 @@ public class ProcessService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to the command sender with the given replacements.
|
||||
* Sends a message to the command sender with the given replacements.
|
||||
*
|
||||
* @param sender the command sender
|
||||
* @param key the message key
|
||||
@@ -76,7 +66,7 @@ public class ProcessService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a message.
|
||||
* Retrieves a message.
|
||||
*
|
||||
* @param key the key of the message
|
||||
* @return the message, split by line
|
||||
@@ -86,7 +76,7 @@ public class ProcessService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a message as one piece.
|
||||
* Retrieves a message in one piece.
|
||||
*
|
||||
* @param key the key of the message
|
||||
* @return the message
|
||||
@@ -95,18 +85,24 @@ public class ProcessService {
|
||||
return messages.retrieveSingle(key);
|
||||
}
|
||||
|
||||
public boolean validateEmail(String email) {
|
||||
return validationService.validateEmail(email);
|
||||
}
|
||||
|
||||
public boolean isEmailFreeForRegistration(String email, CommandSender sender) {
|
||||
return validationService.isEmailFreeForRegistration(email, sender);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the player has the given permission.
|
||||
*
|
||||
* @param player the player
|
||||
* @param node the permission node to check
|
||||
* @return true if player has permission, false otherwise
|
||||
*/
|
||||
public boolean hasPermission(Player player, PermissionNode node) {
|
||||
return permissionsManager.hasPermission(player, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the permission group of the given player.
|
||||
*
|
||||
* @param player the player to process
|
||||
* @param group the group to add the player to
|
||||
* @return true on success, false otherwise
|
||||
*/
|
||||
public boolean setGroup(Player player, AuthGroupType group) {
|
||||
return authGroupHandler.setGroup(player, group);
|
||||
}
|
||||
@@ -17,6 +17,8 @@ import java.net.URLConnection;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import static com.maxmind.geoip.LookupService.GEOIP_MEMORY_CACHE;
|
||||
|
||||
public class GeoIpService {
|
||||
private static final String LICENSE =
|
||||
"[LICENSE] This product uses data from the GeoLite API created by MaxMind, available at http://www.maxmind.com";
|
||||
@@ -57,7 +59,7 @@ public class GeoIpService {
|
||||
boolean dataIsOld = (System.currentTimeMillis() - dataFile.lastModified()) > TimeUnit.DAYS.toMillis(30);
|
||||
if (!dataIsOld) {
|
||||
try {
|
||||
lookupService = new LookupService(dataFile);
|
||||
lookupService = new LookupService(dataFile, GEOIP_MEMORY_CACHE);
|
||||
ConsoleLogger.info(LICENSE);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
|
||||
@@ -57,7 +57,7 @@ public class MessageUpdater {
|
||||
|
||||
properties = buildPropertyEntriesForMessageKeys();
|
||||
settingsManager = new SettingsManager(
|
||||
new YamlFileResource(userFile), (r, p) -> true, new ConfigurationData((List) properties));
|
||||
new YamlFileResource(userFile), null, new ConfigurationData(properties));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,7 +85,6 @@ public class MessageUpdater {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void copyMissingMessages() {
|
||||
for (Property<String> property : properties) {
|
||||
String message = userConfiguration.getString(property.getPath());
|
||||
|
||||
@@ -40,7 +40,8 @@ public class ValidationService implements Reloadable {
|
||||
private Pattern passwordRegex;
|
||||
private Set<String> unrestrictedNames;
|
||||
|
||||
ValidationService() { }
|
||||
ValidationService() {
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package fr.xephi.authme.settings;
|
||||
|
||||
import com.github.authme.configme.SettingsManager;
|
||||
import com.github.authme.configme.properties.StringListProperty;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Property whose value is a set of entries of a given enum.
|
||||
*/
|
||||
// TODO #1014: This property type currently extends StringListProperty with a dedicated method to convert the values
|
||||
// into a Set of the selected enum due to multiple issues on ConfigMe's side.
|
||||
public class EnumSetProperty<E extends Enum<E>> extends StringListProperty {
|
||||
|
||||
private final Class<E> enumClass;
|
||||
|
||||
public EnumSetProperty(Class<E> enumClass, String path, String... values) {
|
||||
super(path, values);
|
||||
this.enumClass = enumClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value as a set of enum entries.
|
||||
*
|
||||
* @param settings the settings manager to look up the raw value with
|
||||
* @return the property's value as mapped enum entries
|
||||
*/
|
||||
public Set<E> asEnumSet(SettingsManager settings) {
|
||||
List<String> entries = settings.getProperty(this);
|
||||
return entries.stream()
|
||||
.map(str -> toEnum(str))
|
||||
.filter(e -> e != null)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private E toEnum(String str) {
|
||||
for (E e : enumClass.getEnumConstants()) {
|
||||
if (str.equalsIgnoreCase(e.name())) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,7 @@ public class Settings extends SettingsManager {
|
||||
private void loadSettingsFromFiles() {
|
||||
passwordEmailMessage = readFile("email.html");
|
||||
recoveryCodeEmailMessage = readFile("recovery_code_email.html");
|
||||
welcomeMessage = readFile("welcome.txt").split("\n");
|
||||
welcomeMessage = readFile("welcome.txt").split("\\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,15 +2,20 @@ package fr.xephi.authme.settings;
|
||||
|
||||
import com.github.authme.configme.migration.PlainMigrationService;
|
||||
import com.github.authme.configme.properties.Property;
|
||||
import com.github.authme.configme.properties.StringListProperty;
|
||||
import com.github.authme.configme.resource.PropertyResource;
|
||||
import com.google.common.base.Objects;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.initialization.DataFolder;
|
||||
import fr.xephi.authme.output.LogLevel;
|
||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.github.authme.configme.properties.PropertyInitializer.newListProperty;
|
||||
@@ -29,7 +34,17 @@ public class SettingsMigrationService extends PlainMigrationService {
|
||||
|
||||
private final File pluginFolder;
|
||||
|
||||
public SettingsMigrationService(File pluginFolder) {
|
||||
// Stores old commands that need to be migrated to the new commands configuration
|
||||
// We need to store it in here for retrieval when we build the CommandConfig. Retrieving it from the config.yml is
|
||||
// not possible since this migration service may trigger config.yml to be resaved. As the old command settings
|
||||
// don't exist in the code anymore, as soon as config.yml is resaved we lose this information.
|
||||
private List<String> onLoginCommands = Collections.emptyList();
|
||||
private List<String> onLoginConsoleCommands = Collections.emptyList();
|
||||
private List<String> onRegisterCommands = Collections.emptyList();
|
||||
private List<String> onRegisterConsoleCommands = Collections.emptyList();
|
||||
|
||||
@Inject
|
||||
SettingsMigrationService(@DataFolder File pluginFolder) {
|
||||
this.pluginFolder = pluginFolder;
|
||||
}
|
||||
|
||||
@@ -41,6 +56,8 @@ public class SettingsMigrationService extends PlainMigrationService {
|
||||
changes = true;
|
||||
}
|
||||
|
||||
gatherOldCommandSettings(resource);
|
||||
|
||||
// Note ljacqu 20160211: Concatenating migration methods with | instead of the usual ||
|
||||
// ensures that all migrations will be performed
|
||||
return changes
|
||||
@@ -49,6 +66,7 @@ public class SettingsMigrationService extends PlainMigrationService {
|
||||
| migrateForceSpawnSettings(resource)
|
||||
| changeBooleanSettingToLogLevelProperty(resource)
|
||||
| hasOldHelpHeaderProperty(resource)
|
||||
| hasSupportOldPasswordProperty(resource)
|
||||
|| hasDeprecatedProperties(resource);
|
||||
}
|
||||
|
||||
@@ -57,7 +75,9 @@ public class SettingsMigrationService extends PlainMigrationService {
|
||||
"Converter.Rakamak.newPasswordHash", "Hooks.chestshop", "Hooks.legacyChestshop", "Hooks.notifications",
|
||||
"Passpartu", "Performances", "settings.restrictions.enablePasswordVerifier", "Xenoforo.predefinedSalt",
|
||||
"VeryGames", "settings.restrictions.allowAllCommandsIfRegistrationIsOptional", "DataSource.mySQLWebsite",
|
||||
"Hooks.customAttributes", "Security.stop.kickPlayersBeforeStopping"};
|
||||
"Hooks.customAttributes", "Security.stop.kickPlayersBeforeStopping",
|
||||
"settings.restrictions.keepCollisionsDisabled", "settings.forceCommands", "settings.forceCommandsAsConsole",
|
||||
"settings.forceRegisterCommands", "settings.forceRegisterCommandsAsConsole"};
|
||||
for (String deprecatedPath : deprecatedProperties) {
|
||||
if (resource.contains(deprecatedPath)) {
|
||||
return true;
|
||||
@@ -66,6 +86,37 @@ public class SettingsMigrationService extends PlainMigrationService {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------
|
||||
// Forced commands relocation (from config.yml to commands.yml)
|
||||
// ----------------
|
||||
private void gatherOldCommandSettings(PropertyResource resource) {
|
||||
onLoginCommands = getStringList(resource, "settings.forceCommands");
|
||||
onLoginConsoleCommands = getStringList(resource, "settings.forceCommandsAsConsole");
|
||||
onRegisterCommands = getStringList(resource, "settings.forceRegisterCommands");
|
||||
onRegisterConsoleCommands = getStringList(resource, "settings.forceRegisterCommandsAsConsole");
|
||||
}
|
||||
|
||||
private List<String> getStringList(PropertyResource resource, String path) {
|
||||
List<String> entries = new StringListProperty(path).getFromResource(resource);
|
||||
return entries == null ? Collections.emptyList() : entries;
|
||||
}
|
||||
|
||||
public List<String> getOnLoginCommands() {
|
||||
return onLoginCommands;
|
||||
}
|
||||
|
||||
public List<String> getOnLoginConsoleCommands() {
|
||||
return onLoginConsoleCommands;
|
||||
}
|
||||
|
||||
public List<String> getOnRegisterCommands() {
|
||||
return onRegisterCommands;
|
||||
}
|
||||
|
||||
public List<String> getOnRegisterConsoleCommands() {
|
||||
return onRegisterConsoleCommands;
|
||||
}
|
||||
|
||||
// --------
|
||||
// Specific migrations
|
||||
// --------
|
||||
@@ -118,7 +169,7 @@ public class SettingsMigrationService extends PlainMigrationService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect old "force spawn loc on join" and "force spawn on these worlds" settings and moves them
|
||||
* Detects old "force spawn loc on join" and "force spawn on these worlds" settings and moves them
|
||||
* to the new paths.
|
||||
*
|
||||
* @param resource The property resource
|
||||
@@ -163,6 +214,16 @@ public class SettingsMigrationService extends PlainMigrationService {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean hasSupportOldPasswordProperty(PropertyResource resource) {
|
||||
String path = "settings.security.supportOldPasswordHash";
|
||||
if (resource.contains(path)) {
|
||||
ConsoleLogger.warning("Property '" + path + "' is no longer supported. "
|
||||
+ "Use '" + SecuritySettings.LEGACY_HASHES.getPath() + "' instead.");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for an old property path and moves it to a new path if present.
|
||||
*
|
||||
|
||||
@@ -48,10 +48,10 @@ public class SpawnLoader implements Reloadable {
|
||||
@Inject
|
||||
SpawnLoader(@DataFolder File pluginFolder, Settings settings, PluginHookService pluginHookService,
|
||||
DataSource dataSource) {
|
||||
File spawnFile = new File(pluginFolder, "spawn.yml");
|
||||
// TODO ljacqu 20160312: Check if resource could be copied and handle the case if not
|
||||
File spawnFile = new File(pluginFolder, "spawn.yml");
|
||||
FileUtils.copyFileFromResource(spawnFile, "spawn.yml");
|
||||
this.authMeConfigurationFile = new File(pluginFolder, "spawn.yml");
|
||||
this.authMeConfigurationFile = spawnFile;
|
||||
this.settings = settings;
|
||||
this.pluginHookService = pluginHookService;
|
||||
reload();
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package fr.xephi.authme.settings.commandconfig;
|
||||
|
||||
/**
|
||||
* Command to be run.
|
||||
*/
|
||||
public class Command {
|
||||
|
||||
/** The command to execute. */
|
||||
private String command;
|
||||
/** The executor of the command. */
|
||||
private Executor executor = Executor.PLAYER;
|
||||
|
||||
/**
|
||||
* Default constructor (for bean mapping).
|
||||
*/
|
||||
public Command() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param command the command
|
||||
* @param executor the executor of the command
|
||||
*/
|
||||
public Command(String command, Executor executor) {
|
||||
this.command = command;
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public void setCommand(String command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public Executor getExecutor() {
|
||||
return executor;
|
||||
}
|
||||
|
||||
public void setExecutor(Executor executor) {
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return command + " (" + executor + ")";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package fr.xephi.authme.settings.commandconfig;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Command configuration.
|
||||
*
|
||||
* @see CommandManager
|
||||
*/
|
||||
public class CommandConfig {
|
||||
|
||||
private Map<String, Command> onJoin = new LinkedHashMap<>();
|
||||
private Map<String, Command> onLogin = new LinkedHashMap<>();
|
||||
private Map<String, Command> onRegister = new LinkedHashMap<>();
|
||||
|
||||
public Map<String, Command> getOnJoin() {
|
||||
return onJoin;
|
||||
}
|
||||
|
||||
public void setOnJoin(Map<String, Command> onJoin) {
|
||||
this.onJoin = onJoin;
|
||||
}
|
||||
|
||||
public Map<String, Command> getOnLogin() {
|
||||
return onLogin;
|
||||
}
|
||||
|
||||
public void setOnLogin(Map<String, Command> onLogin) {
|
||||
this.onLogin = onLogin;
|
||||
}
|
||||
|
||||
public Map<String, Command> getOnRegister() {
|
||||
return onRegister;
|
||||
}
|
||||
|
||||
public void setOnRegister(Map<String, Command> onRegister) {
|
||||
this.onRegister = onRegister;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package fr.xephi.authme.settings.commandconfig;
|
||||
|
||||
import com.github.authme.configme.SettingsManager;
|
||||
import com.github.authme.configme.resource.YamlFileResource;
|
||||
import fr.xephi.authme.initialization.DataFolder;
|
||||
import fr.xephi.authme.initialization.Reloadable;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.util.FileUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Manages configurable commands to be run when various events occur.
|
||||
*/
|
||||
public class CommandManager implements Reloadable {
|
||||
|
||||
private final File dataFolder;
|
||||
private final BukkitService bukkitService;
|
||||
private final CommandMigrationService commandMigrationService;
|
||||
|
||||
private CommandConfig commandConfig;
|
||||
|
||||
@Inject
|
||||
CommandManager(@DataFolder File dataFolder, BukkitService bukkitService,
|
||||
CommandMigrationService commandMigrationService) {
|
||||
this.dataFolder = dataFolder;
|
||||
this.bukkitService = bukkitService;
|
||||
this.commandMigrationService = commandMigrationService;
|
||||
reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the configured commands for when a player has joined.
|
||||
*
|
||||
* @param player the joining player
|
||||
*/
|
||||
public void runCommandsOnJoin(Player player) {
|
||||
executeCommands(player, commandConfig.getOnJoin());
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the configured commands for when a player has successfully registered.
|
||||
*
|
||||
* @param player the player who has registered
|
||||
*/
|
||||
public void runCommandsOnRegister(Player player) {
|
||||
executeCommands(player, commandConfig.getOnRegister());
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the configured commands for when a player has logged in successfully.
|
||||
*
|
||||
* @param player the player that logged in
|
||||
*/
|
||||
public void runCommandsOnLogin(Player player) {
|
||||
executeCommands(player, commandConfig.getOnLogin());
|
||||
}
|
||||
|
||||
private void executeCommands(Player player, Map<String, Command> commands) {
|
||||
for (Command command : commands.values()) {
|
||||
final String execution = command.getCommand().replace("%p", player.getName());
|
||||
if (Executor.CONSOLE.equals(command.getExecutor())) {
|
||||
bukkitService.dispatchConsoleCommand(execution);
|
||||
} else {
|
||||
bukkitService.dispatchCommand(player, execution);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
File file = new File(dataFolder, "commands.yml");
|
||||
FileUtils.copyFileFromResource(file, "commands.yml");
|
||||
|
||||
SettingsManager settingsManager = new SettingsManager(
|
||||
new YamlFileResource(file), commandMigrationService, CommandSettingsHolder.class);
|
||||
commandConfig = settingsManager.getProperty(CommandSettingsHolder.COMMANDS);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package fr.xephi.authme.settings.commandconfig;
|
||||
|
||||
import com.github.authme.configme.migration.MigrationService;
|
||||
import com.github.authme.configme.properties.Property;
|
||||
import com.github.authme.configme.resource.PropertyResource;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.settings.SettingsMigrationService;
|
||||
import fr.xephi.authme.util.RandomStringUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Migrates the commands from their old location, in config.yml, to the dedicated commands configuration file.
|
||||
*/
|
||||
class CommandMigrationService implements MigrationService {
|
||||
|
||||
@Inject
|
||||
private SettingsMigrationService settingsMigrationService;
|
||||
|
||||
CommandMigrationService() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkAndMigrate(PropertyResource resource, List<Property<?>> properties) {
|
||||
final CommandConfig commandConfig = CommandSettingsHolder.COMMANDS.getValue(resource);
|
||||
final boolean didMoveCommands = transformOldCommands(commandConfig);
|
||||
|
||||
if (didMoveCommands) { // TODO ConfigMe/#29: Check that loaded file isn't completely empty
|
||||
resource.setValue("", commandConfig);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds command settings from their old location (in config.yml) to the given command configuration object.
|
||||
*
|
||||
* @param commandConfig the command config object to move old commands to
|
||||
* @return true if commands have been moved, false if no migration was necessary
|
||||
*/
|
||||
@VisibleForTesting
|
||||
boolean transformOldCommands(CommandConfig commandConfig) {
|
||||
boolean didMoveCommands = false;
|
||||
for (MigratableCommandSection section : MigratableCommandSection.values()) {
|
||||
didMoveCommands |= section.convertCommands(settingsMigrationService, commandConfig);
|
||||
}
|
||||
return didMoveCommands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum defining the forced command settings that should be moved from config.yml to the new commands.yml file.
|
||||
*/
|
||||
private enum MigratableCommandSection {
|
||||
|
||||
ON_JOIN(
|
||||
SettingsMigrationService::getOnLoginCommands,
|
||||
Executor.PLAYER,
|
||||
CommandConfig::getOnLogin),
|
||||
|
||||
ON_JOIN_CONSOLE(
|
||||
SettingsMigrationService::getOnLoginConsoleCommands,
|
||||
Executor.CONSOLE,
|
||||
CommandConfig::getOnLogin),
|
||||
|
||||
ON_REGISTER(
|
||||
SettingsMigrationService::getOnRegisterCommands,
|
||||
Executor.PLAYER,
|
||||
CommandConfig::getOnRegister),
|
||||
|
||||
ON_REGISTER_CONSOLE(
|
||||
SettingsMigrationService::getOnRegisterConsoleCommands,
|
||||
Executor.CONSOLE,
|
||||
CommandConfig::getOnRegister);
|
||||
|
||||
private final Function<SettingsMigrationService, List<String>> legacyCommandsGetter;
|
||||
private final Executor executor;
|
||||
private final Function<CommandConfig, Map<String, Command>> commandMapGetter;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param legacyCommandsGetter getter on MigrationService to get the deprecated command entries
|
||||
* @param executor the executor of the commands
|
||||
* @param commandMapGetter the getter for the commands map in the new settings structure to add the old
|
||||
* settings to after conversion
|
||||
*/
|
||||
MigratableCommandSection(Function<SettingsMigrationService, List<String>> legacyCommandsGetter,
|
||||
Executor executor,
|
||||
Function<CommandConfig, Map<String, Command>> commandMapGetter) {
|
||||
this.legacyCommandsGetter = legacyCommandsGetter;
|
||||
this.executor = executor;
|
||||
this.commandMapGetter = commandMapGetter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the commands from the sections' settings migration service to the appropriate place in the new
|
||||
* command config object.
|
||||
*
|
||||
* @param settingsMigrationService settings migration service to read old commands from
|
||||
* @param commandConfig command config object to add converted commands to
|
||||
* @return true if there were commands to migrate, false otherwise
|
||||
*/
|
||||
boolean convertCommands(SettingsMigrationService settingsMigrationService, CommandConfig commandConfig) {
|
||||
List<Command> commands = legacyCommandsGetter.apply(settingsMigrationService).stream()
|
||||
.map(cmd -> new Command(cmd, executor)).collect(Collectors.toList());
|
||||
|
||||
if (commands.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
Map<String, Command> commandMap = commandMapGetter.apply(commandConfig);
|
||||
commands.forEach(cmd -> commandMap.put(RandomStringUtils.generate(10), cmd));
|
||||
ConsoleLogger.info("Moving " + commands.size() + " commands of type " + this
|
||||
+ " from config.yml to commands.yml");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package fr.xephi.authme.settings.commandconfig;
|
||||
|
||||
import com.github.authme.configme.SectionComments;
|
||||
import com.github.authme.configme.SettingsHolder;
|
||||
import com.github.authme.configme.beanmapper.BeanProperty;
|
||||
import com.github.authme.configme.properties.Property;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Settings holder class for the commands.yml settings.
|
||||
*/
|
||||
public final class CommandSettingsHolder implements SettingsHolder {
|
||||
|
||||
public static final Property<CommandConfig> COMMANDS =
|
||||
new BeanProperty<>(CommandConfig.class, "", new CommandConfig());
|
||||
|
||||
|
||||
private CommandSettingsHolder() {
|
||||
}
|
||||
|
||||
@SectionComments
|
||||
public static Map<String, String[]> sectionComments() {
|
||||
String[] comments = {
|
||||
"This configuration file allows you to execute commands on various events.",
|
||||
"%p in commands will be replaced with the player name.",
|
||||
"For example, if you want to send a welcome message to a player who just registered:",
|
||||
"onRegister:",
|
||||
" welcome:",
|
||||
" command: 'msg %p Welcome to the server!'",
|
||||
" as: CONSOLE",
|
||||
"",
|
||||
"This will make the console execute the msg command to the player.",
|
||||
"Each command under an event has a name you can choose freely (e.g. 'welcome' as above),",
|
||||
"after which a mandatory 'command' field defines the command to run,",
|
||||
"and 'as' defines who will run the command (either PLAYER or CONSOLE). Longer example:",
|
||||
"onLogin:",
|
||||
" welcome:",
|
||||
" command: 'msg %p Welcome back!'",
|
||||
" as: PLAYER",
|
||||
" broadcast:",
|
||||
" command: 'broadcast %p has joined, welcome back!'",
|
||||
" as: CONSOLE",
|
||||
"",
|
||||
"Supported command events: onLogin, onJoin, onRegister"
|
||||
};
|
||||
Map<String, String[]> commentMap = new HashMap<>();
|
||||
// TODO ConfigMe/#25 cannot set comments on the root ("")
|
||||
commentMap.put("onLogin", comments);
|
||||
return commentMap;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package fr.xephi.authme.settings.commandconfig;
|
||||
|
||||
/**
|
||||
* The executor of the command.
|
||||
*/
|
||||
public enum Executor {
|
||||
|
||||
/** The player of the event. */
|
||||
PLAYER,
|
||||
|
||||
/** The console user. */
|
||||
CONSOLE
|
||||
|
||||
}
|
||||
@@ -6,8 +6,7 @@ import com.github.authme.configme.knownproperties.ConfigurationDataBuilder;
|
||||
import com.github.authme.configme.properties.Property;
|
||||
|
||||
/**
|
||||
* Utility class responsible for retrieving all {@link Property} fields
|
||||
* from {@link SettingsHolder} implementations via reflection.
|
||||
* Utility class responsible for retrieving all {@link Property} fields from {@link SettingsHolder} classes.
|
||||
*/
|
||||
public final class AuthMeSettingsRetriever {
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ public class HooksSettings implements SettingsHolder {
|
||||
|
||||
@Comment("Do we need to disable Essentials SocialSpy on join?")
|
||||
public static final Property<Boolean> DISABLE_SOCIAL_SPY =
|
||||
newProperty("Hooks.disableSocialSpy", true);
|
||||
newProperty("Hooks.disableSocialSpy", false);
|
||||
|
||||
@Comment("Do we need to force /motd Essentials command on join?")
|
||||
public static final Property<Boolean> USE_ESSENTIALS_MOTD =
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user