it = modules.iterator();
- while (it.hasNext()) {
- it.next().unload();
- it.remove();
- }
- }
-
-}
diff --git a/src/main/java/fr/xephi/authme/output/Messages.java b/src/main/java/fr/xephi/authme/output/Messages.java
index cf029275..8ac42a7b 100644
--- a/src/main/java/fr/xephi/authme/output/Messages.java
+++ b/src/main/java/fr/xephi/authme/output/Messages.java
@@ -76,6 +76,9 @@ public class Messages {
+ "Please verify your config file at '" + fileName + "'");
return formatMessage(getDefault(code));
}
+ if(message.isEmpty()) {
+ return new String[0];
+ }
return formatMessage(message);
}
diff --git a/src/main/java/fr/xephi/authme/permission/PermissionsManager.java b/src/main/java/fr/xephi/authme/permission/PermissionsManager.java
index 5805b8d6..ee27f82c 100644
--- a/src/main/java/fr/xephi/authme/permission/PermissionsManager.java
+++ b/src/main/java/fr/xephi/authme/permission/PermissionsManager.java
@@ -1,11 +1,10 @@
package fr.xephi.authme.permission;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.logging.Logger;
-
+import de.bananaco.bpermissions.api.ApiLayer;
+import de.bananaco.bpermissions.api.CalculableType;
+import fr.xephi.authme.command.CommandDescription;
+import fr.xephi.authme.util.CollectionUtils;
+import net.milkbowl.vault.permission.Permission;
import org.anjocaido.groupmanager.GroupManager;
import org.anjocaido.groupmanager.permissions.AnjoPermissionsHandler;
import org.bukkit.Bukkit;
@@ -18,15 +17,15 @@ import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.tyrannyofheaven.bukkit.zPermissions.ZPermissionsService;
-
-import de.bananaco.bpermissions.api.ApiLayer;
-import de.bananaco.bpermissions.api.CalculableType;
-import fr.xephi.authme.command.CommandDescription;
-import fr.xephi.authme.util.CollectionUtils;
-import net.milkbowl.vault.permission.Permission;
import ru.tehkode.permissions.PermissionUser;
import ru.tehkode.permissions.bukkit.PermissionsEx;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
/**
*
* PermissionsManager.
@@ -49,18 +48,10 @@ public class PermissionsManager implements PermissionsService {
* Server instance.
*/
private final Server server;
- /**
- * Plugin instance.
- */
- private final Plugin plugin;
/**
* Logger instance.
*/
private Logger log;
- /**
- * The permissions manager Bukkit listener instance.
- */
- private PermissionsManagerBukkitListener bukkitListener;
/**
* Type of permissions system that is currently used.
* Null if no permissions system is hooked and/or used.
@@ -79,28 +70,11 @@ public class PermissionsManager implements PermissionsService {
* Constructor.
*
* @param server Server instance
- * @param plugin Plugin instance
* @param log Logger
*/
- public PermissionsManager(Server server, Plugin plugin, Logger log) {
+ public PermissionsManager(Server server, Logger log) {
this.server = server;
- this.plugin = plugin;
this.log = log;
-
- // Create and register the Bukkit listener on the server if it's valid
- if(this.server != null) {
- // Create the Bukkit listener
- this.bukkitListener = new PermissionsManagerBukkitListener(this);
-
- // Get the plugin manager instance
- PluginManager pluginManager = this.server.getPluginManager();
-
- // Register the Bukkit listener
- pluginManager.registerEvents(this.bukkitListener, this.plugin);
-
- // Show a status message.
- //this.log.info("Started permission plugins state listener!");
- }
}
/**
@@ -282,15 +256,6 @@ public class PermissionsManager implements PermissionsService {
}
}
- /**
- * Get the permissions manager Bukkit listener instance.
- *
- * @return Listener instance.
- */
- public PermissionsManagerBukkitListener getListener() {
- return this.bukkitListener;
- }
-
/**
* Check if the command sender has permission for the given permissions node. If no permissions system is used or
* if the sender is not a player (e.g. console user), the player has to be OP in order to have the permission.
diff --git a/src/main/java/fr/xephi/authme/permission/PermissionsManagerBukkitListener.java b/src/main/java/fr/xephi/authme/permission/PermissionsManagerBukkitListener.java
deleted file mode 100644
index d87f1b3c..00000000
--- a/src/main/java/fr/xephi/authme/permission/PermissionsManagerBukkitListener.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package fr.xephi.authme.permission;
-
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.server.PluginDisableEvent;
-import org.bukkit.event.server.PluginEnableEvent;
-
-public class PermissionsManagerBukkitListener implements Listener {
-
- /**
- * The permissions manager instance.
- */
- private PermissionsManager permissionsManager;
-
- /**
- * Whether the listener is enabled or not.
- */
- private boolean enabled = true;
-
- /**
- * Constructor.\
- *
- * @param permissionsManager Permissions manager instance.
- */
- public PermissionsManagerBukkitListener(PermissionsManager permissionsManager) {
- this.permissionsManager = permissionsManager;
- }
-
- /**
- * Check whether the listener is enabled.
- *
- * @return True if the listener is enabled.
- */
- public boolean isEnabled() {
- return this.enabled;
- }
-
- /**
- * Set whether the listener is enabled.
- * Disabling the listener will stop the event handling until it's enabled again.
- *
- * @param enabled True if enabled, false if disabled.
- */
- public void setEnabled(boolean enabled) {
- this.enabled = enabled;
- }
-
- /**
- * Called when a plugin is enabled.
- *
- * @param event Event reference.
- */
- @EventHandler
- public void onPluginEnable(PluginEnableEvent event) {
- // Make sure the listener is enabled
- if(!isEnabled())
- return;
-
- // Make sure the permissions manager is set
- if(this.permissionsManager == null)
- return;
-
- // Call the onPluginEnable method in the permissions manager
- permissionsManager.onPluginEnable(event);
- }
-
- /**
- * Called when a plugin is disabled.
- *
- * @param event Event reference.
- */
- @EventHandler
- public void onPluginDisable(PluginDisableEvent event) {
- // Make sure the listener is enabled
- if(!isEnabled())
- return;
-
- // Make sure the permissions manager is set
- if(this.permissionsManager == null)
- return;
-
- // Call the onPluginDisable method in the permissions manager
- permissionsManager.onPluginDisable(event);
- }
-}
diff --git a/src/main/java/fr/xephi/authme/process/Management.java b/src/main/java/fr/xephi/authme/process/Management.java
index 4cea16fc..4b279c9a 100644
--- a/src/main/java/fr/xephi/authme/process/Management.java
+++ b/src/main/java/fr/xephi/authme/process/Management.java
@@ -41,7 +41,7 @@ public class Management {
}
public void performRegister(final Player player, final String password, final String email) {
- runTask(new AsyncRegister(player, password, email, plugin, dataSource, processService));
+ runTask(new AsyncRegister(player, password, email, plugin, dataSource, playerCache, processService));
}
public void performUnregister(final Player player, final String password, final boolean force) {
diff --git a/src/main/java/fr/xephi/authme/process/ProcessService.java b/src/main/java/fr/xephi/authme/process/ProcessService.java
index 7f696fe1..653be156 100644
--- a/src/main/java/fr/xephi/authme/process/ProcessService.java
+++ b/src/main/java/fr/xephi/authme/process/ProcessService.java
@@ -1,7 +1,6 @@
package fr.xephi.authme.process;
import fr.xephi.authme.AuthMe;
-import fr.xephi.authme.cache.IpAddressManager;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.hooks.PluginHooks;
import fr.xephi.authme.output.MessageKey;
@@ -11,10 +10,15 @@ import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.domain.Property;
+import fr.xephi.authme.util.BukkitService;
+import fr.xephi.authme.util.ValidationService;
import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.scheduler.BukkitTask;
+import java.util.Collection;
+
/**
* Service for asynchronous and synchronous processes.
*/
@@ -24,22 +28,24 @@ public class ProcessService {
private final Messages messages;
private final AuthMe authMe;
private final DataSource dataSource;
- private final IpAddressManager ipAddressManager;
private final PasswordSecurity passwordSecurity;
private final PluginHooks pluginHooks;
private final SpawnLoader spawnLoader;
+ private final ValidationService validationService;
+ private final BukkitService bukkitService;
public ProcessService(NewSetting settings, Messages messages, AuthMe authMe, DataSource dataSource,
- IpAddressManager ipAddressManager, PasswordSecurity passwordSecurity, PluginHooks pluginHooks,
- SpawnLoader spawnLoader) {
+ PasswordSecurity passwordSecurity, PluginHooks pluginHooks, SpawnLoader spawnLoader,
+ ValidationService validationService, BukkitService bukkitService) {
this.settings = settings;
this.messages = messages;
this.authMe = authMe;
this.dataSource = dataSource;
- this.ipAddressManager = ipAddressManager;
this.passwordSecurity = passwordSecurity;
this.pluginHooks = pluginHooks;
this.spawnLoader = spawnLoader;
+ this.validationService = validationService;
+ this.bukkitService = bukkitService;
}
/**
@@ -152,15 +158,6 @@ public class ProcessService {
return authMe;
}
- /**
- * Return the IP address manager.
- *
- * @return the ip address manager
- */
- public IpAddressManager getIpAddressManager() {
- return ipAddressManager;
- }
-
/**
* Compute the hash for the given password.
*
@@ -199,4 +196,31 @@ public class ProcessService {
return dataSource;
}
+ /**
+ * Verifies whether a password is valid according to the plugin settings.
+ *
+ * @param password the password to verify
+ * @param username the username the password is associated with
+ * @return message key with the password error, or {@code null} if password is valid
+ */
+ public MessageKey validatePassword(String password, String username) {
+ return validationService.validatePassword(password, username);
+ }
+
+ public boolean validateEmail(String email) {
+ return validationService.validateEmail(email);
+ }
+
+ public boolean isEmailFreeForRegistration(String email, CommandSender sender) {
+ return validationService.isEmailFreeForRegistration(email, sender);
+ }
+
+ public Collection extends Player> getOnlinePlayers() {
+ return bukkitService.getOnlinePlayers();
+ }
+
+ public BukkitService getBukkitService() {
+ return bukkitService;
+ }
+
}
diff --git a/src/main/java/fr/xephi/authme/process/email/AsyncAddEmail.java b/src/main/java/fr/xephi/authme/process/email/AsyncAddEmail.java
index d1e49b93..282f8f09 100644
--- a/src/main/java/fr/xephi/authme/process/email/AsyncAddEmail.java
+++ b/src/main/java/fr/xephi/authme/process/email/AsyncAddEmail.java
@@ -8,7 +8,6 @@ import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.properties.RegistrationSettings;
-import fr.xephi.authme.util.Utils;
import org.bukkit.entity.Player;
/**
@@ -41,9 +40,9 @@ public class AsyncAddEmail implements Process {
if (currentEmail != null && !"your@email.com".equals(currentEmail)) {
service.send(player, MessageKey.USAGE_CHANGE_EMAIL);
- } else if (!Utils.isEmailCorrect(email, service.getSettings())) {
+ } else if (!service.validateEmail(email)) {
service.send(player, MessageKey.INVALID_EMAIL);
- } else if (dataSource.isEmailStored(email)) {
+ } else if (!service.isEmailFreeForRegistration(email, player)) {
service.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR);
} else {
auth.setEmail(email);
diff --git a/src/main/java/fr/xephi/authme/process/email/AsyncChangeEmail.java b/src/main/java/fr/xephi/authme/process/email/AsyncChangeEmail.java
index 132decd5..7489327b 100644
--- a/src/main/java/fr/xephi/authme/process/email/AsyncChangeEmail.java
+++ b/src/main/java/fr/xephi/authme/process/email/AsyncChangeEmail.java
@@ -7,7 +7,6 @@ import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.properties.RegistrationSettings;
-import fr.xephi.authme.util.Utils;
import org.bukkit.entity.Player;
/**
@@ -41,11 +40,11 @@ public class AsyncChangeEmail implements Process {
if (currentEmail == null) {
service.send(player, MessageKey.USAGE_ADD_EMAIL);
- } else if (newEmail == null || !Utils.isEmailCorrect(newEmail, service.getSettings())) {
+ } else if (newEmail == null || !service.validateEmail(newEmail)) {
service.send(player, MessageKey.INVALID_NEW_EMAIL);
} else if (!oldEmail.equals(currentEmail)) {
service.send(player, MessageKey.INVALID_OLD_EMAIL);
- } else if (dataSource.isEmailStored(newEmail)) {
+ } else if (!service.isEmailFreeForRegistration(newEmail, player)) {
service.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR);
} else {
saveNewEmail(auth);
@@ -62,7 +61,6 @@ public class AsyncChangeEmail implements Process {
service.send(player, MessageKey.EMAIL_CHANGED_SUCCESS);
} else {
service.send(player, MessageKey.ERROR);
- auth.setEmail(newEmail);
}
}
diff --git a/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java b/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java
index 838ac0e6..37b0dfbd 100644
--- a/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java
+++ b/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java
@@ -14,23 +14,27 @@ import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
-import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.settings.properties.PluginSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
+import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.task.MessageTask;
import fr.xephi.authme.task.TimeoutTask;
import fr.xephi.authme.util.Utils;
import fr.xephi.authme.util.Utils.GroupType;
+import org.apache.commons.lang.reflect.MethodUtils;
import org.bukkit.Location;
import org.bukkit.Material;
+import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitTask;
+import static fr.xephi.authme.settings.properties.RestrictionSettings.PROTECT_INVENTORY_BEFORE_LOGIN;
+
/**
*/
public class AsynchronousJoin implements Process {
@@ -42,6 +46,9 @@ public class AsynchronousJoin implements Process {
private final ProcessService service;
private final PlayerCache playerCache;
+ private final boolean disableCollisions = MethodUtils
+ .getAccessibleMethod(LivingEntity.class, "setCollidable", new Class[]{}) != null;
+
public AsynchronousJoin(Player player, AuthMe plugin, DataSource database, PlayerCache playerCache,
ProcessService service) {
this.player = player;
@@ -62,14 +69,14 @@ public class AsynchronousJoin implements Process {
service.getPluginHooks().setEssentialsSocialSpyStatus(player, false);
}
- final String ip = service.getIpAddressManager().getPlayerIp(player);
- if (isNameRestricted(name, ip, player.getAddress().getHostName(), service.getSettings())) {
+ final String ip = Utils.getPlayerIp(player);
+ if (isNameRestricted(name, ip, player.getAddress().getHostName())) {
service.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
AuthMePlayerListener.causeByAuthMe.putIfAbsent(name, true);
player.kickPlayer(service.retrieveSingleMessage(MessageKey.NOT_OWNER_ERROR));
- if (Settings.banUnsafeIp) {
+ if (service.getProperty(RestrictionSettings.BAN_UNKNOWN_IP)) {
plugin.getServer().banIP(ip);
}
}
@@ -80,7 +87,7 @@ public class AsynchronousJoin implements Process {
&& !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)
&& !"127.0.0.1".equalsIgnoreCase(ip)
&& !"localhost".equalsIgnoreCase(ip)
- && hasJoinedIp(player.getName(), ip, service.getSettings())) {
+ && hasJoinedIp(player.getName(), ip)) {
service.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
@@ -89,10 +96,14 @@ public class AsynchronousJoin implements Process {
});
return;
}
+ // Prevent player collisions in 1.9
+ if (disableCollisions) {
+ ((LivingEntity) player).setCollidable(false);
+ }
final Location spawnLoc = service.getSpawnLoader().getSpawnLocation(player);
final boolean isAuthAvailable = database.isAuthAvailable(name);
if (isAuthAvailable) {
- if (!Settings.noTeleport) {
+ if (!service.getProperty(RestrictionSettings.NO_TELEPORT)) {
if (Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) {
service.scheduleSyncDelayedTask(new Runnable() {
@Override
@@ -111,12 +122,12 @@ public class AsynchronousJoin implements Process {
LimboCache.getInstance().updateLimboPlayer(player);
// protect inventory
- if (Settings.protectInventoryBeforeLogInEnabled && plugin.inventoryProtector != null) {
+ if (service.getProperty(PROTECT_INVENTORY_BEFORE_LOGIN) && plugin.inventoryProtector != null) {
ProtectInventoryEvent ev = new ProtectInventoryEvent(player);
plugin.getServer().getPluginManager().callEvent(ev);
if (ev.isCancelled()) {
plugin.inventoryProtector.sendInventoryPacket(player);
- if (!Settings.noConsoleSpam) {
+ if (!service.getProperty(SecuritySettings.REMOVE_SPAM_FROM_CONSOLE)) {
ConsoleLogger.info("ProtectInventoryEvent has been cancelled for " + player.getName() + "...");
}
}
@@ -134,7 +145,7 @@ public class AsynchronousJoin implements Process {
service.send(player, MessageKey.SESSION_RECONNECTION);
plugin.getManagement().performLogin(player, "dontneed", true);
return;
- } else if (Settings.sessionExpireOnIpChange) {
+ } else if (service.getProperty(PluginSettings.SESSIONS_EXPIRE_ON_IP_CHANGE)) {
service.send(player, MessageKey.SESSION_EXPIRED);
}
}
@@ -142,7 +153,7 @@ public class AsynchronousJoin implements Process {
if (!Settings.unRegisteredGroup.isEmpty()) {
Utils.setGroup(player, Utils.GroupType.UNREGISTERED);
}
- if (!Settings.isForcedRegistrationEnabled) {
+ if (!service.getProperty(RegistrationSettings.FORCE)) {
return;
}
@@ -173,12 +184,13 @@ public class AsynchronousJoin implements Process {
@Override
public void run() {
player.setOp(false);
- if (Settings.isRemoveSpeedEnabled) {
+ if (!service.getProperty(RestrictionSettings.ALLOW_UNAUTHED_MOVEMENT)
+ && service.getProperty(RestrictionSettings.REMOVE_SPEED)) {
player.setFlySpeed(0.0f);
player.setWalkSpeed(0.0f);
}
player.setNoDamageTicks(registrationTimeout);
- if (service.getProperty(HooksSettings.USE_ESSENTIALS_MOTD)) {
+ if (plugin.getPluginHooks().isEssentialsAvailable() && service.getProperty(HooksSettings.USE_ESSENTIALS_MOTD)) {
player.performCommand("motd");
}
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
@@ -200,12 +212,13 @@ public class AsynchronousJoin implements Process {
if (isAuthAvailable) {
msg = MessageKey.LOGIN_MESSAGE;
} else {
- msg = Settings.emailRegistration
+ msg = service.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)
? MessageKey.REGISTER_EMAIL_MESSAGE
: MessageKey.REGISTER_MESSAGE;
}
if (msgInterval > 0 && LimboCache.getInstance().getLimboPlayer(name) != null) {
- BukkitTask msgTask = service.runTask(new MessageTask(plugin, name, msg, msgInterval));
+ BukkitTask msgTask = service.runTask(new MessageTask(service.getBukkitService(), plugin.getMessages(),
+ name, msg, msgInterval));
LimboCache.getInstance().getLimboPlayer(name).setMessageTask(msgTask);
}
}
@@ -266,24 +279,22 @@ public class AsynchronousJoin implements Process {
* @param name The name to check
* @param ip The IP address of the player
* @param domain The hostname of the IP address
- * @param settings The settings instance
* @return True if the name is restricted (IP/domain is not allowed for the given name),
* false if the restrictions are met or if the name has no restrictions to it
*/
- private static boolean isNameRestricted(String name, String ip, String domain, NewSetting settings) {
- if (!settings.getProperty(RestrictionSettings.ENABLE_RESTRICTED_USERS)) {
+ private boolean isNameRestricted(String name, String ip, String domain) {
+ if (!service.getProperty(RestrictionSettings.ENABLE_RESTRICTED_USERS)) {
return false;
}
boolean nameFound = false;
- for (String entry : settings.getProperty(RestrictionSettings.ALLOWED_RESTRICTED_USERS)) {
+ for (String entry : service.getProperty(RestrictionSettings.ALLOWED_RESTRICTED_USERS)) {
String[] args = entry.split(";");
String testName = args[0];
String testIp = args[1];
if (testName.equalsIgnoreCase(name)) {
nameFound = true;
- if ((ip != null && testIp.equals(ip))
- || (domain != null && testIp.equalsIgnoreCase(domain))) {
+ if ((ip != null && testIp.equals(ip)) || (domain != null && testIp.equalsIgnoreCase(domain))) {
return false;
}
}
@@ -291,14 +302,14 @@ public class AsynchronousJoin implements Process {
return nameFound;
}
- private boolean hasJoinedIp(String name, String ip, NewSetting settings) {
+ private boolean hasJoinedIp(String name, String ip) {
int count = 0;
- for (Player player : Utils.getOnlinePlayers()) {
- if (ip.equalsIgnoreCase(service.getIpAddressManager().getPlayerIp(player))
+ for (Player player : service.getOnlinePlayers()) {
+ if (ip.equalsIgnoreCase(Utils.getPlayerIp(player))
&& !player.getName().equalsIgnoreCase(name)) {
count++;
}
}
- return count >= settings.getProperty(RestrictionSettings.MAX_JOIN_PER_IP);
+ return count >= service.getProperty(RestrictionSettings.MAX_JOIN_PER_IP);
}
}
diff --git a/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java b/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java
index bb039bf1..b7bb3f2b 100644
--- a/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java
+++ b/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java
@@ -17,6 +17,7 @@ import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.security.RandomString;
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.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
@@ -52,7 +53,7 @@ public class AsynchronousLogin implements Process {
this.forceLogin = forceLogin;
this.plugin = plugin;
this.database = data;
- this.ip = service.getIpAddressManager().getPlayerIp(player);
+ this.ip = Utils.getPlayerIp(player);
this.service = service;
}
@@ -96,8 +97,8 @@ public class AsynchronousLogin implements Process {
String[] msg = service.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)
? service.retrieveMessage(MessageKey.REGISTER_EMAIL_MESSAGE)
: service.retrieveMessage(MessageKey.REGISTER_MESSAGE);
- BukkitTask messageTask = service.runTask(
- new MessageTask(plugin, name, msg, service.getProperty(RegistrationSettings.MESSAGE_INTERVAL)));
+ BukkitTask messageTask = service.runTask(new MessageTask(service.getBukkitService(),
+ name, msg, service.getProperty(RegistrationSettings.MESSAGE_INTERVAL)));
limboPlayer.setMessageTask(messageTask);
}
return null;
@@ -166,11 +167,12 @@ public class AsynchronousLogin implements Process {
displayOtherAccounts(auth);
- if (Settings.recallEmail && (StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email))) {
+ if (service.getProperty(EmailSettings.RECALL_PLAYERS)
+ && (StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email))) {
service.send(player, MessageKey.ADD_EMAIL_MESSAGE);
}
- if (!Settings.noConsoleSpam) {
+ if (!service.getProperty(SecuritySettings.REMOVE_SPAM_FROM_CONSOLE)) {
ConsoleLogger.info(realName + " logged in!");
}
@@ -182,8 +184,7 @@ public class AsynchronousLogin implements Process {
// task, we schedule it in the end
// so that we can be sure, and have not to care if it might be
// processed in other order.
- ProcessSyncPlayerLogin syncPlayerLogin = new ProcessSyncPlayerLogin(
- player, plugin, database, service.getSettings());
+ ProcessSyncPlayerLogin syncPlayerLogin = new ProcessSyncPlayerLogin(player, plugin, database, service);
if (syncPlayerLogin.getLimbo() != null) {
if (syncPlayerLogin.getLimbo().getTimeoutTask() != null) {
syncPlayerLogin.getLimbo().getTimeoutTask().cancel();
@@ -213,7 +214,7 @@ public class AsynchronousLogin implements Process {
}
private void displayOtherAccounts(PlayerAuth auth) {
- if (!Settings.displayOtherAccounts || auth == null) {
+ if (!service.getProperty(RestrictionSettings.DISPLAY_OTHER_ACCOUNTS) || auth == null) {
return;
}
@@ -222,7 +223,7 @@ public class AsynchronousLogin implements Process {
return;
}
String message = "[AuthMe] " + StringUtils.join(", ", auths) + ".";
- for (Player player : Utils.getOnlinePlayers()) {
+ for (Player player : service.getOnlinePlayers()) {
if (plugin.getPermissionsManager().hasPermission(player, AdminPermission.SEE_OTHER_ACCOUNTS)
|| (player.getName().equals(this.player.getName())
&& plugin.getPermissionsManager().hasPermission(player, PlayerPermission.SEE_OWN_ACCOUNTS))) {
diff --git a/src/main/java/fr/xephi/authme/process/login/ProcessSyncPlayerLogin.java b/src/main/java/fr/xephi/authme/process/login/ProcessSyncPlayerLogin.java
index b454f370..9f5de6bd 100644
--- a/src/main/java/fr/xephi/authme/process/login/ProcessSyncPlayerLogin.java
+++ b/src/main/java/fr/xephi/authme/process/login/ProcessSyncPlayerLogin.java
@@ -1,18 +1,7 @@
package fr.xephi.authme.process.login;
-import fr.xephi.authme.settings.NewSetting;
-import fr.xephi.authme.settings.properties.HooksSettings;
-import fr.xephi.authme.settings.properties.RegistrationSettings;
-import fr.xephi.authme.settings.properties.RestrictionSettings;
-import org.bukkit.Bukkit;
-import org.bukkit.Location;
-import org.bukkit.entity.Player;
-import org.bukkit.plugin.PluginManager;
-import org.bukkit.potion.PotionEffectType;
-
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
-
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.backup.JsonCache;
@@ -24,14 +13,26 @@ import fr.xephi.authme.events.LoginEvent;
import fr.xephi.authme.events.RestoreInventoryEvent;
import fr.xephi.authme.events.SpawnTeleportEvent;
import fr.xephi.authme.listener.AuthMePlayerListener;
+import fr.xephi.authme.process.Process;
+import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.Settings;
+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.util.Utils;
import fr.xephi.authme.util.Utils.GroupType;
+import org.apache.commons.lang.reflect.MethodUtils;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.PluginManager;
+import org.bukkit.potion.PotionEffectType;
+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 Runnable {
+public class ProcessSyncPlayerLogin implements Process {
private final LimboPlayer limbo;
private final Player player;
@@ -40,7 +41,10 @@ public class ProcessSyncPlayerLogin implements Runnable {
private final AuthMe plugin;
private final PluginManager pm;
private final JsonCache playerCache;
- private final NewSetting settings;
+ private final ProcessService service;
+
+ private final boolean restoreCollisions = MethodUtils
+ .getAccessibleMethod(LivingEntity.class, "setCollidable", new Class[]{}) != null;
/**
* Constructor for ProcessSyncPlayerLogin.
@@ -48,10 +52,9 @@ public class ProcessSyncPlayerLogin implements Runnable {
* @param player Player
* @param plugin AuthMe
* @param database DataSource
- * @param settings The plugin settings
+ * @param service The process service
*/
- public ProcessSyncPlayerLogin(Player player, AuthMe plugin,
- DataSource database, NewSetting settings) {
+ public ProcessSyncPlayerLogin(Player player, AuthMe plugin, DataSource database, ProcessService service) {
this.plugin = plugin;
this.pm = plugin.getServer().getPluginManager();
this.player = player;
@@ -59,7 +62,7 @@ public class ProcessSyncPlayerLogin implements Runnable {
this.limbo = LimboCache.getInstance().getLimboPlayer(name);
this.auth = database.getAuth(name);
this.playerCache = new JsonCache();
- this.settings = settings;
+ this.service = service;
}
public LimboPlayer getLimbo() {
@@ -92,7 +95,7 @@ public class ProcessSyncPlayerLogin implements Runnable {
}
private void restoreSpeedEffects() {
- if (settings.getProperty(RestrictionSettings.REMOVE_SPEED)) {
+ if (!service.getProperty(RestrictionSettings.ALLOW_UNAUTHED_MOVEMENT) && service.getProperty(RestrictionSettings.REMOVE_SPEED)) {
player.setWalkSpeed(0.2F);
player.setFlySpeed(0.1F);
}
@@ -107,10 +110,10 @@ public class ProcessSyncPlayerLogin implements Runnable {
}
private void forceCommands() {
- for (String command : Settings.forceCommands) {
+ for (String command : service.getProperty(RegistrationSettings.FORCE_COMMANDS)) {
player.performCommand(command.replace("%p", player.getName()));
}
- for (String command : Settings.forceCommandsAsConsole) {
+ for (String command : service.getProperty(RegistrationSettings.FORCE_COMMANDS_AS_CONSOLE)) {
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), command.replace("%p", player.getName()));
}
}
@@ -148,10 +151,18 @@ public class ProcessSyncPlayerLogin implements Runnable {
}
}
- if (settings.getProperty(PROTECT_INVENTORY_BEFORE_LOGIN)) {
+ if (restoreCollisions && !service.getProperty(KEEP_COLLISIONS_DISABLED)) {
+ player.setCollidable(true);
+ }
+
+ if (service.getProperty(PROTECT_INVENTORY_BEFORE_LOGIN)) {
restoreInventory();
}
+ if (service.getProperty(RestrictionSettings.HIDE_TABLIST_BEFORE_LOGIN) && plugin.tablistHider != null) {
+ plugin.tablistHider.sendTablist(player);
+ }
+
// Cleanup no longer used temporary data
LimboCache.getInstance().deleteLimboPlayer(name);
if (playerCache.doesCacheExist(player)) {
@@ -163,7 +174,7 @@ public class ProcessSyncPlayerLogin implements Runnable {
String jm = AuthMePlayerListener.joinMessage.get(name);
if (jm != null) {
if (!jm.isEmpty()) {
- for (Player p : Utils.getOnlinePlayers()) {
+ for (Player p : service.getOnlinePlayers()) {
if (p.isOnline()) {
p.sendMessage(jm);
}
@@ -173,24 +184,24 @@ public class ProcessSyncPlayerLogin implements Runnable {
}
restoreSpeedEffects();
- if (settings.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
+ if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
player.removePotionEffect(PotionEffectType.BLINDNESS);
}
// The Login event now fires (as intended) after everything is processed
Bukkit.getServer().getPluginManager().callEvent(new LoginEvent(player));
player.saveData();
- if (settings.getProperty(HooksSettings.BUNGEECORD)) {
+ if (service.getProperty(HooksSettings.BUNGEECORD)) {
sendBungeeMessage();
}
// Login is done, display welcome message
- if (settings.getProperty(RegistrationSettings.USE_WELCOME_MESSAGE)) {
- if (settings.getProperty(RegistrationSettings.BROADCAST_WELCOME_MESSAGE)) {
- for (String s : settings.getWelcomeMessage()) {
+ if (service.getProperty(RegistrationSettings.USE_WELCOME_MESSAGE)) {
+ if (service.getProperty(RegistrationSettings.BROADCAST_WELCOME_MESSAGE)) {
+ for (String s : service.getSettings().getWelcomeMessage()) {
Bukkit.getServer().broadcastMessage(plugin.replaceAllInfo(s, player));
}
} else {
- for (String s : settings.getWelcomeMessage()) {
+ for (String s : service.getSettings().getWelcomeMessage()) {
player.sendMessage(plugin.replaceAllInfo(s, player));
}
}
@@ -198,15 +209,15 @@ public class ProcessSyncPlayerLogin implements Runnable {
// Login is now finished; we can force all commands
forceCommands();
-
+
sendTo();
}
private void sendTo() {
- if (!settings.getProperty(HooksSettings.BUNGEECORD_SERVER).isEmpty()) {
+ if (!service.getProperty(HooksSettings.BUNGEECORD_SERVER).isEmpty()) {
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF("Connect");
- out.writeUTF(settings.getProperty(HooksSettings.BUNGEECORD_SERVER));
+ out.writeUTF(service.getProperty(HooksSettings.BUNGEECORD_SERVER));
player.sendPluginMessage(plugin, "BungeeCord", out.toByteArray());
}
}
diff --git a/src/main/java/fr/xephi/authme/process/logout/ProcessSynchronousPlayerLogout.java b/src/main/java/fr/xephi/authme/process/logout/ProcessSynchronousPlayerLogout.java
index bc2ea16d..d6d66b90 100644
--- a/src/main/java/fr/xephi/authme/process/logout/ProcessSynchronousPlayerLogout.java
+++ b/src/main/java/fr/xephi/authme/process/logout/ProcessSynchronousPlayerLogout.java
@@ -74,7 +74,8 @@ public class ProcessSynchronousPlayerLogout implements Process {
BukkitTask id = service.runTaskLater(new TimeoutTask(plugin, name, player), timeOut);
LimboCache.getInstance().getLimboPlayer(name).setTimeoutTask(id);
}
- BukkitTask msgT = service.runTask(new MessageTask(plugin, name, MessageKey.LOGIN_MESSAGE, interval));
+ BukkitTask msgT = service.runTask(new MessageTask(service.getBukkitService(), plugin.getMessages(),
+ name, MessageKey.LOGIN_MESSAGE, interval));
LimboCache.getInstance().getLimboPlayer(name).setMessageTask(msgT);
if (player.isInsideVehicle() && player.getVehicle() != null) {
player.getVehicle().eject();
diff --git a/src/main/java/fr/xephi/authme/process/quit/AsynchronousQuit.java b/src/main/java/fr/xephi/authme/process/quit/AsynchronousQuit.java
index cb2a79a9..c4e1a7f5 100644
--- a/src/main/java/fr/xephi/authme/process/quit/AsynchronousQuit.java
+++ b/src/main/java/fr/xephi/authme/process/quit/AsynchronousQuit.java
@@ -43,7 +43,7 @@ public class AsynchronousQuit implements Process {
return;
}
- String ip = service.getIpAddressManager().getPlayerIp(player);
+ String ip = Utils.getPlayerIp(player);
if (PlayerCache.getInstance().isAuthenticated(name)) {
if (service.getProperty(RestrictionSettings.SAVE_QUIT_LOCATION)) {
@@ -94,7 +94,6 @@ public class AsynchronousQuit implements Process {
database.setUnlogged(name);
}
- service.getIpAddressManager().removeCache(player.getName());
if (plugin.isEnabled()) {
service.scheduleSyncDelayedTask(new ProcessSyncronousPlayerQuit(plugin, player, isOp, needToChange));
}
diff --git a/src/main/java/fr/xephi/authme/process/quit/ProcessSyncronousPlayerQuit.java b/src/main/java/fr/xephi/authme/process/quit/ProcessSyncronousPlayerQuit.java
index 3193ac49..bf7ab967 100644
--- a/src/main/java/fr/xephi/authme/process/quit/ProcessSyncronousPlayerQuit.java
+++ b/src/main/java/fr/xephi/authme/process/quit/ProcessSyncronousPlayerQuit.java
@@ -38,9 +38,6 @@ public class ProcessSyncronousPlayerQuit implements Runnable {
if (needToChange) {
player.setOp(isOp);
}
- try {
- player.getVehicle().eject();
- } catch (Exception ignored) {
- }
+ player.leaveVehicle();
}
}
diff --git a/src/main/java/fr/xephi/authme/process/register/AsyncRegister.java b/src/main/java/fr/xephi/authme/process/register/AsyncRegister.java
index 47b715a3..5cacb105 100644
--- a/src/main/java/fr/xephi/authme/process/register/AsyncRegister.java
+++ b/src/main/java/fr/xephi/authme/process/register/AsyncRegister.java
@@ -12,8 +12,13 @@ import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.security.crypts.TwoFactor;
import fr.xephi.authme.settings.Settings;
+import fr.xephi.authme.settings.properties.EmailSettings;
+import fr.xephi.authme.settings.properties.RegistrationSettings;
+import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.util.StringUtils;
+import fr.xephi.authme.util.Utils;
+
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@@ -30,43 +35,36 @@ public class AsyncRegister implements Process {
private final String email;
private final AuthMe plugin;
private final DataSource database;
+ private final PlayerCache playerCache;
private final ProcessService service;
public AsyncRegister(Player player, String password, String email, AuthMe plugin, DataSource data,
- ProcessService service) {
+ PlayerCache playerCache, ProcessService service) {
this.player = player;
this.password = password;
this.name = player.getName().toLowerCase();
this.email = email;
this.plugin = plugin;
this.database = data;
- this.ip = service.getIpAddressManager().getPlayerIp(player);
+ this.ip = Utils.getPlayerIp(player);
+ this.playerCache = playerCache;
this.service = service;
}
private boolean preRegisterCheck() {
- String passLow = password.toLowerCase();
- if (PlayerCache.getInstance().isAuthenticated(name)) {
+ if (playerCache.isAuthenticated(name)) {
service.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
return false;
- } else if (!Settings.isRegistrationEnabled) {
+ } else if (!service.getProperty(RegistrationSettings.IS_ENABLED)) {
service.send(player, MessageKey.REGISTRATION_DISABLED);
return false;
}
//check the password safety only if it's not a automatically generated password
if (service.getProperty(SecuritySettings.PASSWORD_HASH) != HashAlgorithm.TWO_FACTOR) {
- if (!passLow.matches(Settings.getPassRegex)) {
- service.send(player, MessageKey.PASSWORD_MATCH_ERROR);
- return false;
- } else if (passLow.equalsIgnoreCase(player.getName())) {
- service.send(player, MessageKey.PASSWORD_IS_USERNAME_ERROR);
- return false;
- } else if (password.length() < Settings.getPasswordMinLen || password.length() > Settings.passwordMaxLength) {
- service.send(player, MessageKey.INVALID_PASSWORD_LENGTH);
- return false;
- } else if (!Settings.unsafePasswords.isEmpty() && Settings.unsafePasswords.contains(password.toLowerCase())) {
- service.send(player, MessageKey.PASSWORD_UNSAFE_ERROR);
+ MessageKey passwordError = service.validatePassword(password, player.getName());
+ if (passwordError != null) {
+ service.send(player, passwordError);
return false;
}
}
@@ -75,15 +73,17 @@ public class AsyncRegister implements Process {
if (database.isAuthAvailable(name)) {
service.send(player, MessageKey.NAME_ALREADY_REGISTERED);
return false;
- } else if(Settings.getmaxRegPerIp > 0
- && !ip.equalsIgnoreCase("127.0.0.1")
- && !ip.equalsIgnoreCase("localhost")
+ }
+
+ final int maxRegPerIp = service.getProperty(RestrictionSettings.MAX_REGISTRATION_PER_IP);
+ if (maxRegPerIp > 0
+ && !"127.0.0.1".equalsIgnoreCase(ip)
+ && !"localhost".equalsIgnoreCase(ip)
&& !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)) {
- int maxReg = Settings.getmaxRegPerIp;
List otherAccounts = database.getAllAuthsByIp(ip);
- if (otherAccounts.size() >= maxReg) {
- service.send(player, MessageKey.MAX_REGISTER_EXCEEDED, Integer.toString(maxReg),
- Integer.toString(otherAccounts.size()), StringUtils.join(", ", otherAccounts.toString()));
+ if (otherAccounts.size() >= maxRegPerIp) {
+ service.send(player, MessageKey.MAX_REGISTER_EXCEEDED, Integer.toString(maxRegPerIp),
+ Integer.toString(otherAccounts.size()), StringUtils.join(", ", otherAccounts));
return false;
}
}
@@ -102,12 +102,12 @@ public class AsyncRegister implements Process {
}
private void emailRegister() {
- if (Settings.getmaxRegPerEmail > 0
+ final int maxRegPerEmail = service.getProperty(EmailSettings.MAX_REG_PER_EMAIL);
+ if (maxRegPerEmail > 0
&& !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)) {
- int maxReg = Settings.getmaxRegPerEmail;
int otherAccounts = database.countAuthsByEmail(email);
- if (otherAccounts >= maxReg) {
- service.send(player, MessageKey.MAX_REGISTER_EXCEEDED, Integer.toString(maxReg),
+ if (otherAccounts >= maxRegPerEmail) {
+ service.send(player, MessageKey.MAX_REGISTER_EXCEEDED, Integer.toString(maxRegPerEmail),
Integer.toString(otherAccounts), "@");
return;
}
diff --git a/src/main/java/fr/xephi/authme/process/register/ProcessSyncEmailRegister.java b/src/main/java/fr/xephi/authme/process/register/ProcessSyncEmailRegister.java
index a58fdded..461857aa 100644
--- a/src/main/java/fr/xephi/authme/process/register/ProcessSyncEmailRegister.java
+++ b/src/main/java/fr/xephi/authme/process/register/ProcessSyncEmailRegister.java
@@ -52,13 +52,13 @@ public class ProcessSyncEmailRegister implements Process {
limbo.setTimeoutTask(id);
}
BukkitTask messageTask = service.runTask(new MessageTask(
- service.getAuthMe(), name, service.retrieveMessage(MessageKey.LOGIN_MESSAGE), msgInterval));
+ service.getBukkitService(), name, service.retrieveMessage(MessageKey.LOGIN_MESSAGE), msgInterval));
limbo.setMessageTask(messageTask);
}
player.saveData();
if (!service.getProperty(SecuritySettings.REMOVE_SPAM_FROM_CONSOLE)) {
- ConsoleLogger.info(player.getName() + " registered " + service.getIpAddressManager().getPlayerIp(player));
+ ConsoleLogger.info(player.getName() + " registered " + Utils.getPlayerIp(player));
}
}
diff --git a/src/main/java/fr/xephi/authme/process/register/ProcessSyncPasswordRegister.java b/src/main/java/fr/xephi/authme/process/register/ProcessSyncPasswordRegister.java
index c77a7d03..b9505143 100644
--- a/src/main/java/fr/xephi/authme/process/register/ProcessSyncPasswordRegister.java
+++ b/src/main/java/fr/xephi/authme/process/register/ProcessSyncPasswordRegister.java
@@ -12,9 +12,11 @@ import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.Settings;
+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.settings.properties.RestrictionSettings;
+import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.task.MessageTask;
import fr.xephi.authme.task.TimeoutTask;
import fr.xephi.authme.util.Utils;
@@ -23,12 +25,15 @@ import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitTask;
+import static fr.xephi.authme.settings.properties.RestrictionSettings.HIDE_TABLIST_BEFORE_LOGIN;
+import static fr.xephi.authme.util.BukkitService.TICKS_PER_SECOND;
+
/**
*/
public class ProcessSyncPasswordRegister implements Process {
- protected final Player player;
- protected final String name;
+ private final Player player;
+ private final String name;
private final AuthMe plugin;
private final ProcessService service;
@@ -49,27 +54,33 @@ public class ProcessSyncPasswordRegister implements Process {
}
private void forceCommands() {
- for (String command : Settings.forceRegisterCommands) {
+ for (String command : service.getProperty(RegistrationSettings.FORCE_REGISTER_COMMANDS)) {
player.performCommand(command.replace("%p", player.getName()));
}
- for (String command : Settings.forceRegisterCommandsAsConsole) {
+ for (String command : service.getProperty(RegistrationSettings.FORCE_REGISTER_COMMANDS_AS_CONSOLE)) {
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(),
- command.replace("%p", player.getName()));
+ command.replace("%p", player.getName()));
}
}
- private void forceLogin(Player player) {
+ /**
+ * Request that the player log in.
+ *
+ * @param player the player
+ */
+ private void requestLogin(Player player) {
Utils.teleportToSpawn(player);
LimboCache cache = LimboCache.getInstance();
cache.updateLimboPlayer(player);
- int delay = service.getProperty(RestrictionSettings.TIMEOUT) * 20;
+ int delay = service.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
int interval = service.getProperty(RegistrationSettings.MESSAGE_INTERVAL);
BukkitTask task;
if (delay != 0) {
task = service.runTaskLater(new TimeoutTask(service.getAuthMe(), name, player), delay);
cache.getLimboPlayer(name).setTimeoutTask(task);
}
- task = service.runTask(new MessageTask(plugin, name, MessageKey.LOGIN_MESSAGE, interval));
+ task = service.runTask(new MessageTask(service.getBukkitService(), plugin.getMessages(),
+ name, MessageKey.LOGIN_MESSAGE, interval));
cache.getLimboPlayer(name).setMessageTask(task);
if (player.isInsideVehicle() && player.getVehicle() != null) {
player.getVehicle().eject();
@@ -80,11 +91,15 @@ public class ProcessSyncPasswordRegister implements Process {
public void run() {
LimboPlayer limbo = LimboCache.getInstance().getLimboPlayer(name);
if (limbo != null) {
+ if (service.getProperty(RestrictionSettings.HIDE_TABLIST_BEFORE_LOGIN) && plugin.tablistHider != null) {
+ plugin.tablistHider.sendTablist(player);
+ }
+
Utils.teleportToSpawn(player);
- if (Settings.protectInventoryBeforeLogInEnabled && plugin.inventoryProtector != null) {
+ if (service.getProperty(HIDE_TABLIST_BEFORE_LOGIN) && plugin.inventoryProtector != null) {
RestoreInventoryEvent event = new RestoreInventoryEvent(player);
- Bukkit.getPluginManager().callEvent(event);
+ service.callEvent(event);
if (!event.isCancelled()) {
plugin.inventoryProtector.sendInventoryPacket(player);
}
@@ -99,7 +114,7 @@ public class ProcessSyncPasswordRegister implements Process {
service.send(player, MessageKey.REGISTER_SUCCESS);
- if (!Settings.getmailAccount.isEmpty()) {
+ if (!service.getProperty(EmailSettings.MAIL_ACCOUNT).isEmpty()) {
service.send(player, MessageKey.ADD_EMAIL_MESSAGE);
}
@@ -111,42 +126,29 @@ public class ProcessSyncPasswordRegister implements Process {
plugin.getServer().getPluginManager().callEvent(new LoginEvent(player));
player.saveData();
- if (!Settings.noConsoleSpam) {
- ConsoleLogger.info(player.getName() + " registered " + service.getIpAddressManager().getPlayerIp(player));
+ if (!service.getProperty(SecuritySettings.REMOVE_SPAM_FROM_CONSOLE)) {
+ ConsoleLogger.info(player.getName() + " registered " + Utils.getPlayerIp(player));
}
// Kick Player after Registration is enabled, kick the player
- if (Settings.forceRegKick) {
+ if (service.getProperty(RegistrationSettings.FORCE_KICK_AFTER_REGISTER)) {
player.kickPlayer(service.retrieveSingleMessage(MessageKey.REGISTER_SUCCESS));
return;
}
- // Register is finish and player is logged, display welcome message
- if (service.getProperty(RegistrationSettings.USE_WELCOME_MESSAGE)) {
- if (service.getProperty(RegistrationSettings.BROADCAST_WELCOME_MESSAGE)) {
- for (String s : service.getSettings().getWelcomeMessage()) {
- plugin.getServer().broadcastMessage(plugin.replaceAllInfo(s, player));
- }
- } else {
- for (String s : service.getSettings().getWelcomeMessage()) {
- player.sendMessage(plugin.replaceAllInfo(s, player));
- }
- }
- }
+ // Register is now finished; we can force all commands
+ forceCommands();
- // Request Login after Registration
- if (Settings.forceRegLogin) {
- forceLogin(player);
+ // Request login after registration
+ if (service.getProperty(RegistrationSettings.FORCE_LOGIN_AFTER_REGISTER)) {
+ requestLogin(player);
return;
}
- if (Settings.bungee) {
+ if (service.getProperty(HooksSettings.BUNGEECORD)) {
sendBungeeMessage();
}
- // Register is now finished; we can force all commands
- forceCommands();
-
sendTo();
}
diff --git a/src/main/java/fr/xephi/authme/process/unregister/AsynchronousUnregister.java b/src/main/java/fr/xephi/authme/process/unregister/AsynchronousUnregister.java
index 29c2b8c3..cd3f41a2 100644
--- a/src/main/java/fr/xephi/authme/process/unregister/AsynchronousUnregister.java
+++ b/src/main/java/fr/xephi/authme/process/unregister/AsynchronousUnregister.java
@@ -20,7 +20,6 @@ import fr.xephi.authme.util.Utils.GroupType;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
-import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
public class AsynchronousUnregister implements Process {
@@ -73,13 +72,12 @@ public class AsynchronousUnregister implements Process {
LimboCache.getInstance().addLimboPlayer(player);
LimboPlayer limboPlayer = LimboCache.getInstance().getLimboPlayer(name);
int interval = service.getProperty(RegistrationSettings.MESSAGE_INTERVAL);
- BukkitScheduler scheduler = plugin.getServer().getScheduler();
if (timeOut != 0) {
- BukkitTask id = scheduler.runTaskLater(plugin, new TimeoutTask(plugin, name, player), timeOut);
+ BukkitTask id = service.runTaskLater(new TimeoutTask(plugin, name, player), timeOut);
limboPlayer.setTimeoutTask(id);
}
- limboPlayer.setMessageTask(scheduler.runTask(plugin,
- new MessageTask(plugin, name, MessageKey.REGISTER_MESSAGE, interval)));
+ limboPlayer.setMessageTask(service.runTask(new MessageTask(service.getBukkitService(),
+ plugin.getMessages(), name, MessageKey.REGISTER_MESSAGE, interval)));
service.send(player, MessageKey.UNREGISTERED_SUCCESS);
ConsoleLogger.info(player.getDisplayName() + " unregistered himself");
return;
@@ -99,7 +97,6 @@ public class AsynchronousUnregister implements Process {
}
service.send(player, MessageKey.UNREGISTERED_SUCCESS);
ConsoleLogger.info(player.getDisplayName() + " unregistered himself");
- Utils.teleportToSpawn(player);
} else {
service.send(player, MessageKey.WRONG_PASSWORD);
}
diff --git a/src/main/java/fr/xephi/authme/security/PasswordSecurity.java b/src/main/java/fr/xephi/authme/security/PasswordSecurity.java
index da506b6b..94a8abeb 100644
--- a/src/main/java/fr/xephi/authme/security/PasswordSecurity.java
+++ b/src/main/java/fr/xephi/authme/security/PasswordSecurity.java
@@ -8,46 +8,75 @@ import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.properties.SecuritySettings;
import org.bukkit.plugin.PluginManager;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
/**
* Manager class for password-related operations.
*/
public class PasswordSecurity {
+ private final NewSetting settings;
private HashAlgorithm algorithm;
private boolean supportOldAlgorithm;
private final DataSource dataSource;
private final PluginManager pluginManager;
public PasswordSecurity(DataSource dataSource, NewSetting settings, PluginManager pluginManager) {
+ this.settings = settings;
this.algorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH);
this.supportOldAlgorithm = settings.getProperty(SecuritySettings.SUPPORT_OLD_PASSWORD_HASH);
this.dataSource = dataSource;
this.pluginManager = pluginManager;
}
+ /**
+ * Compute the hash of the configured algorithm for the given password and username.
+ *
+ * @param password The password to hash
+ * @param playerName The player's name
+ *
+ * @return The password hash
+ */
public HashedPassword computeHash(String password, String playerName) {
- return computeHash(algorithm, password, playerName);
- }
-
- public HashedPassword computeHash(HashAlgorithm algorithm, String password, String playerName) {
String playerLowerCase = playerName.toLowerCase();
- EncryptionMethod method = initializeEncryptionMethod(algorithm, playerLowerCase);
+ EncryptionMethod method = initializeEncryptionMethodWithEvent(algorithm, playerLowerCase);
return method.computeHash(password, playerLowerCase);
}
+ /**
+ * Check if the given password matches the player's stored password.
+ *
+ * @param password The password to check
+ * @param playerName The player to check for
+ *
+ * @return True if the password is correct, false otherwise
+ */
public boolean comparePassword(String password, String playerName) {
HashedPassword auth = dataSource.getPassword(playerName);
return auth != null && comparePassword(password, auth, playerName);
}
+ /**
+ * Check if the given password matches the given hashed password.
+ *
+ * @param password The password to check
+ * @param hashedPassword The hashed password to check against
+ * @param playerName The player to check for
+ *
+ * @return True if the password matches, false otherwise
+ */
public boolean comparePassword(String password, HashedPassword hashedPassword, String playerName) {
- EncryptionMethod method = initializeEncryptionMethod(algorithm, playerName);
+ EncryptionMethod method = initializeEncryptionMethodWithEvent(algorithm, playerName);
String playerLowerCase = playerName.toLowerCase();
return methodMatches(method, password, hashedPassword, playerLowerCase)
|| supportOldAlgorithm && compareWithAllEncryptionMethods(password, hashedPassword, playerLowerCase);
}
- public void reload(NewSetting settings) {
+ /**
+ * Reload the configuration.
+ */
+ public void reload() {
this.algorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH);
this.supportOldAlgorithm = settings.getProperty(SecuritySettings.SUPPORT_OLD_PASSWORD_HASH);
}
@@ -63,11 +92,10 @@ public class PasswordSecurity {
*
* @return True if there was a password match with another encryption method, false otherwise
*/
- private boolean compareWithAllEncryptionMethods(String password, HashedPassword hashedPassword,
- String playerName) {
+ private boolean compareWithAllEncryptionMethods(String password, HashedPassword hashedPassword, String playerName) {
for (HashAlgorithm algorithm : HashAlgorithm.values()) {
if (!HashAlgorithm.CUSTOM.equals(algorithm)) {
- EncryptionMethod method = initializeEncryptionMethodWithoutEvent(algorithm);
+ EncryptionMethod method = initializeEncryptionMethod(algorithm, settings);
if (methodMatches(method, password, hashedPassword, playerName)) {
hashPasswordForNewAlgorithm(password, playerName);
return true;
@@ -85,6 +113,7 @@ public class PasswordSecurity {
* @param password The password to check
* @param hashedPassword The hash to check against
* @param playerName The name of the player
+ *
* @return True if the password matched, false otherwise
*/
private static boolean methodMatches(EncryptionMethod method, String password,
@@ -103,33 +132,45 @@ public class PasswordSecurity {
*
* @return The encryption method
*/
- private EncryptionMethod initializeEncryptionMethod(HashAlgorithm algorithm, String playerName) {
- EncryptionMethod method = initializeEncryptionMethodWithoutEvent(algorithm);
+ private EncryptionMethod initializeEncryptionMethodWithEvent(HashAlgorithm algorithm, String playerName) {
+ EncryptionMethod method = initializeEncryptionMethod(algorithm, settings);
PasswordEncryptionEvent event = new PasswordEncryptionEvent(method, playerName);
pluginManager.callEvent(event);
return event.getMethod();
}
/**
- * Initialize the encryption method corresponding to the given hash algorithm.
+ * Initialize the encryption method associated with the given hash algorithm.
*
* @param algorithm The algorithm to retrieve the encryption method for
+ * @param settings The settings instance to pass to the constructor if required
*
- * @return The associated encryption method
+ * @return The associated encryption method, or null if CUSTOM / deprecated
*/
- private static EncryptionMethod initializeEncryptionMethodWithoutEvent(HashAlgorithm algorithm) {
+ public static EncryptionMethod initializeEncryptionMethod(HashAlgorithm algorithm,
+ NewSetting settings) {
try {
- return HashAlgorithm.CUSTOM.equals(algorithm) || HashAlgorithm.PLAINTEXT.equals(algorithm)
- ? null
- : algorithm.getClazz().newInstance();
- } catch (InstantiationException | IllegalAccessException e) {
+ if (HashAlgorithm.CUSTOM.equals(algorithm) || HashAlgorithm.PLAINTEXT.equals(algorithm)) {
+ return null;
+ }
+ Constructor> constructor = algorithm.getClazz().getConstructors()[0];
+ Class>[] parameters = constructor.getParameterTypes();
+ if (parameters.length == 0) {
+ return (EncryptionMethod) constructor.newInstance();
+ } else if (parameters.length == 1 && parameters[0] == NewSetting.class) {
+ return (EncryptionMethod) constructor.newInstance(settings);
+ } else {
+ throw new UnsupportedOperationException("Did not find default constructor or constructor with settings "
+ + "parameter in class " + algorithm.getClazz().getSimpleName());
+ }
+ } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new UnsupportedOperationException("Constructor for '" + algorithm.getClazz().getSimpleName()
+ "' could not be invoked. (Is there no default constructor?)", e);
}
}
private void hashPasswordForNewAlgorithm(String password, String playerName) {
- HashedPassword hashedPassword = initializeEncryptionMethod(algorithm, playerName)
+ HashedPassword hashedPassword = initializeEncryptionMethodWithEvent(algorithm, playerName)
.computeHash(password, playerName);
dataSource.updatePassword(playerName, hashedPassword);
}
diff --git a/src/main/java/fr/xephi/authme/security/crypts/BCRYPT.java b/src/main/java/fr/xephi/authme/security/crypts/BCRYPT.java
index 181571b3..a114adc0 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/BCRYPT.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/BCRYPT.java
@@ -5,7 +5,8 @@ import fr.xephi.authme.security.crypts.description.HasSalt;
import fr.xephi.authme.security.crypts.description.Recommendation;
import fr.xephi.authme.security.crypts.description.SaltType;
import fr.xephi.authme.security.crypts.description.Usage;
-import fr.xephi.authme.settings.Settings;
+import fr.xephi.authme.settings.NewSetting;
+import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.util.StringUtils;
@@ -13,6 +14,12 @@ import fr.xephi.authme.util.StringUtils;
@HasSalt(value = SaltType.TEXT) // length depends on Settings.bCryptLog2Rounds
public class BCRYPT implements EncryptionMethod {
+ private final int bCryptLog2Rounds;
+
+ public BCRYPT(NewSetting settings) {
+ this.bCryptLog2Rounds = settings.getProperty(HooksSettings.BCRYPT_LOG2_ROUND);
+ }
+
@Override
public String computeHash(String password, String salt, String name) {
return BCryptService.hashpw(password, salt);
@@ -36,7 +43,7 @@ public class BCRYPT implements EncryptionMethod {
@Override
public String generateSalt() {
- return BCryptService.gensalt(Settings.bCryptLog2Rounds);
+ return BCryptService.gensalt(bCryptLog2Rounds);
}
@Override
diff --git a/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2Django.java b/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2Django.java
index 14b3e35b..27ca14f8 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2Django.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2Django.java
@@ -4,6 +4,7 @@ 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;
@@ -31,8 +32,8 @@ public class CryptPBKDF2Django extends HexSaltedMethod {
try {
iterations = Integer.parseInt(line[1]);
} catch (NumberFormatException e) {
- ConsoleLogger.logException("Could not read number of rounds in '" + hashedPassword.getHash()
- + " for CryptPBKDF2Django", e);
+ ConsoleLogger.showError("Could not read number of rounds for CryptPBKDF2Django:"
+ + StringUtils.formatException(e));
return false;
}
String salt = line[2];
diff --git a/src/main/java/fr/xephi/authme/security/crypts/EncryptionMethod.java b/src/main/java/fr/xephi/authme/security/crypts/EncryptionMethod.java
index 26efc156..b1c0b003 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/EncryptionMethod.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/EncryptionMethod.java
@@ -2,6 +2,10 @@ package fr.xephi.authme.security.crypts;
/**
* Public interface for custom password encryption methods.
+ *
+ * Note that {@link fr.xephi.authme.security.PasswordSecurity} requires classes implementing this interface
+ * to either have the default constructor or an accessible constructor with one parameter of type
+ * {@link fr.xephi.authme.settings.NewSetting}.
*/
public interface EncryptionMethod {
@@ -31,9 +35,9 @@ public interface EncryptionMethod {
/**
* Check whether the given hash matches the clear-text password.
*
- * @param password The clear-text password to verify
+ * @param password The clear-text password to verify
* @param hashedPassword The hash to check the password against
- * @param name The player name to do the check for (sometimes required for generating the salt)
+ * @param name The player name to do the check for (sometimes required for generating the salt)
*
* @return True if the password matches, false otherwise
*/
diff --git a/src/main/java/fr/xephi/authme/security/crypts/MYBB.java b/src/main/java/fr/xephi/authme/security/crypts/MYBB.java
index 555f3213..32ad154a 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/MYBB.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/MYBB.java
@@ -19,7 +19,7 @@ public class MYBB extends SeparateSaltMethod {
@Override
public String generateSalt() {
- return RandomString.generateHex(8);
+ return RandomString.generateLowerUpper(8);
}
}
diff --git a/src/main/java/fr/xephi/authme/security/crypts/SALTED2MD5.java b/src/main/java/fr/xephi/authme/security/crypts/SALTED2MD5.java
index 613bcd3f..27066f7a 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/SALTED2MD5.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/SALTED2MD5.java
@@ -5,7 +5,8 @@ import fr.xephi.authme.security.crypts.description.HasSalt;
import fr.xephi.authme.security.crypts.description.Recommendation;
import fr.xephi.authme.security.crypts.description.SaltType;
import fr.xephi.authme.security.crypts.description.Usage;
-import fr.xephi.authme.settings.Settings;
+import fr.xephi.authme.settings.NewSetting;
+import fr.xephi.authme.settings.properties.SecuritySettings;
import static fr.xephi.authme.security.HashUtils.md5;
@@ -13,6 +14,12 @@ import static fr.xephi.authme.security.HashUtils.md5;
@HasSalt(value = SaltType.TEXT) // length defined by Settings.saltLength
public class SALTED2MD5 extends SeparateSaltMethod {
+ private final int saltLength;
+
+ public SALTED2MD5(NewSetting settings) {
+ saltLength = settings.getProperty(SecuritySettings.DOUBLE_MD5_SALT_LENGTH);
+ }
+
@Override
public String computeHash(String password, String salt, String name) {
return md5(md5(password) + salt);
@@ -20,7 +27,7 @@ public class SALTED2MD5 extends SeparateSaltMethod {
@Override
public String generateSalt() {
- return RandomString.generateHex(Settings.saltLength);
+ return RandomString.generateHex(saltLength);
}
}
diff --git a/src/main/java/fr/xephi/authme/settings/Settings.java b/src/main/java/fr/xephi/authme/settings/Settings.java
index 5989e216..944f675d 100644
--- a/src/main/java/fr/xephi/authme/settings/Settings.java
+++ b/src/main/java/fr/xephi/authme/settings/Settings.java
@@ -8,10 +8,8 @@ import fr.xephi.authme.settings.properties.PluginSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
-import fr.xephi.authme.util.Wrapper;
import org.bukkit.configuration.file.FileConfiguration;
-import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -22,55 +20,27 @@ import java.util.regex.Pattern;
*/
public final class Settings {
- public static final File PLUGIN_FOLDER = Wrapper.getInstance().getDataFolder();
- public static final File MODULE_FOLDER = new File(PLUGIN_FOLDER, "modules");
- public static final File CACHE_FOLDER = new File(PLUGIN_FOLDER, "cache");
- // This is not an option!
- public static boolean antiBotInAction = false;
public static List allowCommands;
- public static List getJoinPermissions;
public static List getUnrestrictedName;
- public static List getRestrictedIp;
public static List getForcedWorlds;
public static List countries;
public static List countriesBlacklist;
- public static List forceCommands;
- public static List forceCommandsAsConsole;
- public static List forceRegisterCommands;
- public static List forceRegisterCommandsAsConsole;
- public static List unsafePasswords;
public static HashAlgorithm getPasswordHash;
public static Pattern nickPattern;
- public static boolean useLogging = false;
- public static boolean isChatAllowed, isPermissionCheckEnabled, isRegistrationEnabled,
+ public static boolean isPermissionCheckEnabled,
isForcedRegistrationEnabled, isTeleportToSpawnEnabled,
isSessionsEnabled, isAllowRestrictedIp,
- isMovementAllowed, isKickNonRegisteredEnabled,
isForceSingleSessionEnabled, isForceSpawnLocOnJoinEnabled,
- isSaveQuitLocationEnabled, isForceSurvivalModeEnabled,
- isKickOnWrongPasswordEnabled, enablePasswordConfirmation,
- protectInventoryBeforeLogInEnabled, isStopEnabled, reloadSupport,
- rakamakUseIp, noConsoleSpam, removePassword, displayOtherAccounts,
- emailRegistration, multiverse, bungee,
- banUnsafeIp, doubleEmailCheck, sessionExpireOnIpChange,
- disableSocialSpy, useEssentialsMotd,
- enableProtection, recallEmail, useWelcomeMessage,
- broadcastWelcomeMessage, forceRegKick, forceRegLogin,
- checkVeryGames, removeJoinMessage, removeLeaveMessage, delayJoinMessage,
- noTeleport, hideTablistBeforeLogin, denyTabcompleteBeforeLogin,
- kickPlayersBeforeStopping, allowAllCommandsIfRegIsOptional,
- customAttributes, isRemoveSpeedEnabled, preventOtherCase;
+ isSaveQuitLocationEnabled, protectInventoryBeforeLogInEnabled,
+ isStopEnabled, reloadSupport, rakamakUseIp,
+ removePassword, multiverse, bungee,
+ enableProtection, forceRegLogin, noTeleport,
+ allowAllCommandsIfRegIsOptional, isRemoveSpeedEnabled;
public static String getNickRegex, getUnloggedinGroup,
- unRegisteredGroup,
- backupWindowsPath, getRegisteredGroup,
- rakamakUsers, rakamakUsersIp, getmailAccount, defaultWorld,
- spawnPriority, crazyloginFileName, getPassRegex, sendPlayerTo;
- public static int getWarnMessageInterval, getSessionTimeout,
- getRegistrationTimeout, getMaxNickLength, getMinNickLength,
- getPasswordMinLen, getMovementRadius, getmaxRegPerIp,
- getNonActivatedGroup, passwordMaxLength, getRecoveryPassLength,
- getMailPort, maxLoginTry, captchaLength, saltLength,
- getmaxRegPerEmail, bCryptLog2Rounds, getMaxLoginPerIp, getMaxJoinPerIp;
+ unRegisteredGroup, backupWindowsPath, getRegisteredGroup,
+ rakamakUsers, rakamakUsersIp, defaultWorld, crazyloginFileName;
+ public static int getSessionTimeout, getMaxNickLength, getMinNickLength,
+ getNonActivatedGroup, maxLoginTry, captchaLength, getMaxLoginPerIp;
protected static FileConfiguration configFile;
/**
@@ -85,32 +55,19 @@ public final class Settings {
private static void loadVariables() {
isPermissionCheckEnabled = load(PluginSettings.ENABLE_PERMISSION_CHECK);
- isForcedRegistrationEnabled = configFile.getBoolean("settings.registration.force", true);
- isRegistrationEnabled = configFile.getBoolean("settings.registration.enabled", true);
+ isForcedRegistrationEnabled = load(RegistrationSettings.FORCE);
isTeleportToSpawnEnabled = load(RestrictionSettings.TELEPORT_UNAUTHED_TO_SPAWN);
- getWarnMessageInterval = load(RegistrationSettings.MESSAGE_INTERVAL);
isSessionsEnabled = load(PluginSettings.SESSIONS_ENABLED);
getSessionTimeout = configFile.getInt("settings.sessions.timeout", 10);
- getRegistrationTimeout = load(RestrictionSettings.TIMEOUT);
- isChatAllowed = load(RestrictionSettings.ALLOW_CHAT);
getMaxNickLength = configFile.getInt("settings.restrictions.maxNicknameLength", 20);
getMinNickLength = configFile.getInt("settings.restrictions.minNicknameLength", 3);
- getPasswordMinLen = configFile.getInt("settings.security.minPasswordLength", 4);
getNickRegex = configFile.getString("settings.restrictions.allowedNicknameCharacters", "[a-zA-Z0-9_?]*");
nickPattern = Pattern.compile(getNickRegex);
isAllowRestrictedIp = load(RestrictionSettings.ENABLE_RESTRICTED_USERS);
- getRestrictedIp = load(RestrictionSettings.ALLOWED_RESTRICTED_USERS);
- isMovementAllowed = configFile.getBoolean("settings.restrictions.allowMovement", false);
- isRemoveSpeedEnabled = configFile.getBoolean("settings.restrictions.removeSpeed", true);
- getMovementRadius = configFile.getInt("settings.restrictions.allowedMovementRadius", 100);
- getJoinPermissions = configFile.getStringList("GroupOptions.Permissions.PermissionsOnJoin");
- isKickOnWrongPasswordEnabled = configFile.getBoolean("settings.restrictions.kickOnWrongPassword", false);
- isKickNonRegisteredEnabled = configFile.getBoolean("settings.restrictions.kickNonRegistered", false);
- isForceSingleSessionEnabled = configFile.getBoolean("settings.restrictions.ForceSingleSession", true);
- isForceSpawnLocOnJoinEnabled = configFile.getBoolean("settings.restrictions.ForceSpawnLocOnJoinEnabled", false);
+ isRemoveSpeedEnabled = load(RestrictionSettings.REMOVE_SPEED);
+ isForceSingleSessionEnabled = load(RestrictionSettings.FORCE_SINGLE_SESSION);
+ isForceSpawnLocOnJoinEnabled = load(RestrictionSettings.FORCE_SPAWN_LOCATION_AFTER_LOGIN);
isSaveQuitLocationEnabled = configFile.getBoolean("settings.restrictions.SaveQuitLocation", false);
- isForceSurvivalModeEnabled = configFile.getBoolean("settings.GameMode.ForceSurvivalMode", false);
- getmaxRegPerIp = configFile.getInt("settings.restrictions.maxRegPerIp", 1);
getPasswordHash = load(SecuritySettings.PASSWORD_HASH);
getUnloggedinGroup = load(SecuritySettings.UNLOGGEDIN_GROUP);
getNonActivatedGroup = configFile.getInt("ExternalBoardOptions.nonActivedUserGroup", -1);
@@ -122,18 +79,12 @@ public final class Settings {
}
getRegisteredGroup = configFile.getString("GroupOptions.RegisteredPlayerGroup", "");
- enablePasswordConfirmation = load(RestrictionSettings.ENABLE_PASSWORD_CONFIRMATION);
-
protectInventoryBeforeLogInEnabled = load(RestrictionSettings.PROTECT_INVENTORY_BEFORE_LOGIN);
- denyTabcompleteBeforeLogin = load(RestrictionSettings.DENY_TABCOMPLETE_BEFORE_LOGIN);
- hideTablistBeforeLogin = load(RestrictionSettings.HIDE_TABLIST_BEFORE_LOGIN);
-
- passwordMaxLength = load(SecuritySettings.MAX_PASSWORD_LENGTH);
backupWindowsPath = configFile.getString("BackupSystem.MysqlWindowsPath", "C:\\Program Files\\MySQL\\MySQL Server 5.1\\");
isStopEnabled = configFile.getBoolean("Security.SQLProblem.stopServer", true);
reloadSupport = configFile.getBoolean("Security.ReloadCommand.useReloadCommandSupport", true);
- allowAllCommandsIfRegIsOptional = configFile.getBoolean("settings.restrictions.allowAllCommandsIfRegistrationIsOptional", false);
+ allowAllCommandsIfRegIsOptional = load(RestrictionSettings.ALLOW_ALL_COMMANDS_IF_REGISTRATION_IS_OPTIONAL);
allowCommands = new ArrayList<>();
allowCommands.addAll(Arrays.asList("/login", "/l", "/register", "/reg", "/email", "/captcha"));
for (String cmd : configFile.getStringList("settings.restrictions.allowCommands")) {
@@ -146,71 +97,20 @@ public final class Settings {
rakamakUsers = configFile.getString("Converter.Rakamak.fileName", "users.rak");
rakamakUsersIp = configFile.getString("Converter.Rakamak.ipFileName", "UsersIp.rak");
rakamakUseIp = configFile.getBoolean("Converter.Rakamak.useIp", false);
- noConsoleSpam = load(SecuritySettings.REMOVE_SPAM_FROM_CONSOLE);
removePassword = configFile.getBoolean("Security.console.removePassword", true);
- getmailAccount = configFile.getString("Email.mailAccount", "");
- getMailPort = configFile.getInt("Email.mailPort", 465);
- getRecoveryPassLength = configFile.getInt("Email.RecoveryPasswordLength", 8);
- displayOtherAccounts = configFile.getBoolean("settings.restrictions.displayOtherAccounts", true);
maxLoginTry = configFile.getInt("Security.captcha.maxLoginTry", 5);
captchaLength = configFile.getInt("Security.captcha.captchaLength", 5);
- emailRegistration = load(RegistrationSettings.USE_EMAIL_REGISTRATION);
- saltLength = configFile.getInt("settings.security.doubleMD5SaltLength", 8);
- getmaxRegPerEmail = configFile.getInt("Email.maxRegPerEmail", 1);
multiverse = load(HooksSettings.MULTIVERSE);
- bungee = configFile.getBoolean("Hooks.bungeecord", false);
+ bungee = load(HooksSettings.BUNGEECORD);
getForcedWorlds = configFile.getStringList("settings.restrictions.ForceSpawnOnTheseWorlds");
- banUnsafeIp = configFile.getBoolean("settings.restrictions.banUnsafedIP", false);
- doubleEmailCheck = configFile.getBoolean("settings.registration.doubleEmailCheck", false);
- sessionExpireOnIpChange = configFile.getBoolean("settings.sessions.sessionExpireOnIpChange", true);
- useLogging = configFile.getBoolean("Security.console.logConsole", false);
- disableSocialSpy = configFile.getBoolean("Hooks.disableSocialSpy", true);
- bCryptLog2Rounds = configFile.getInt("ExternalBoardOptions.bCryptLog2Round", 10);
- useEssentialsMotd = configFile.getBoolean("Hooks.useEssentialsMotd", false);
defaultWorld = configFile.getString("Purge.defaultWorld", "world");
enableProtection = configFile.getBoolean("Protection.enableProtection", false);
countries = configFile.getStringList("Protection.countries");
- forceCommands = configFile.getStringList("settings.forceCommands");
- forceCommandsAsConsole = configFile.getStringList("settings.forceCommandsAsConsole");
- recallEmail = configFile.getBoolean("Email.recallPlayers", false);
- useWelcomeMessage = load(RegistrationSettings.USE_WELCOME_MESSAGE);
- unsafePasswords = configFile.getStringList("settings.security.unsafePasswords");
countriesBlacklist = configFile.getStringList("Protection.countriesBlacklist");
- broadcastWelcomeMessage = load(RegistrationSettings.BROADCAST_WELCOME_MESSAGE);
- forceRegKick = configFile.getBoolean("settings.registration.forceKickAfterRegister", false);
forceRegLogin = load(RegistrationSettings.FORCE_LOGIN_AFTER_REGISTER);
- spawnPriority = load(RestrictionSettings.SPAWN_PRIORITY);
getMaxLoginPerIp = load(RestrictionSettings.MAX_LOGIN_PER_IP);
- getMaxJoinPerIp = load(RestrictionSettings.MAX_JOIN_PER_IP);
- checkVeryGames = load(HooksSettings.ENABLE_VERYGAMES_IP_CHECK);
- removeJoinMessage = load(RegistrationSettings.REMOVE_JOIN_MESSAGE);
- removeLeaveMessage = load(RegistrationSettings.REMOVE_LEAVE_MESSAGE);
- delayJoinMessage = load(RegistrationSettings.DELAY_JOIN_MESSAGE);
noTeleport = load(RestrictionSettings.NO_TELEPORT);
crazyloginFileName = configFile.getString("Converter.CrazyLogin.fileName", "accounts.db");
- getPassRegex = configFile.getString("settings.restrictions.allowedPasswordCharacters", "[\\x21-\\x7E]*");
- forceRegisterCommands = configFile.getStringList("settings.forceRegisterCommands");
- forceRegisterCommandsAsConsole = configFile.getStringList("settings.forceRegisterCommandsAsConsole");
- customAttributes = configFile.getBoolean("Hooks.customAttributes");
- preventOtherCase = configFile.getBoolean("settings.preventOtherCase", false);
- kickPlayersBeforeStopping = configFile.getBoolean("Security.stop.kickPlayersBeforeStopping", true);
- sendPlayerTo = configFile.getString("Hooks.sendPlayerTo", "");
-
- }
-
- /**
- * Method switchAntiBotMod.
- *
- * @param mode boolean
- */
- public static void switchAntiBotMod(boolean mode) {
- if (mode) {
- isKickNonRegisteredEnabled = true;
- antiBotInAction = true;
- } else {
- isKickNonRegisteredEnabled = configFile.getBoolean("settings.restrictions.kickNonRegistered", false);
- antiBotInAction = false;
- }
}
/**
diff --git a/src/main/java/fr/xephi/authme/settings/SettingsMigrationService.java b/src/main/java/fr/xephi/authme/settings/SettingsMigrationService.java
index a3d70dd1..0982713c 100644
--- a/src/main/java/fr/xephi/authme/settings/SettingsMigrationService.java
+++ b/src/main/java/fr/xephi/authme/settings/SettingsMigrationService.java
@@ -59,7 +59,7 @@ public class SettingsMigrationService {
private static boolean hasDeprecatedProperties(FileConfiguration configuration) {
String[] deprecatedProperties = {
"Converter.Rakamak.newPasswordHash", "Hooks.chestshop", "Hooks.legacyChestshop", "Hooks.notifications",
- "Passpartu", "Performances", "settings.restrictions.enablePasswordVerifier", "Xenoforo.predefinedSalt"};
+ "Passpartu", "Performances", "settings.restrictions.enablePasswordVerifier", "Xenoforo.predefinedSalt", "VeryGames"};
for (String deprecatedPath : deprecatedProperties) {
if (configuration.contains(deprecatedPath)) {
return true;
diff --git a/src/main/java/fr/xephi/authme/settings/properties/HooksSettings.java b/src/main/java/fr/xephi/authme/settings/properties/HooksSettings.java
index 95d91f85..087bb30d 100644
--- a/src/main/java/fr/xephi/authme/settings/properties/HooksSettings.java
+++ b/src/main/java/fr/xephi/authme/settings/properties/HooksSettings.java
@@ -35,10 +35,6 @@ public class HooksSettings implements SettingsClass {
public static final Property CACHE_CUSTOM_ATTRIBUTES =
newProperty("Hooks.customAttributes", false);
- @Comment("These features are only available on VeryGames Server Provider")
- public static final Property ENABLE_VERYGAMES_IP_CHECK =
- newProperty("VeryGames.enableIpCheck", false);
-
@Comment({
"-1 means disabled. If you want that only activated players",
"can log into your server, you can set here the group number",
diff --git a/src/main/java/fr/xephi/authme/settings/properties/PluginSettings.java b/src/main/java/fr/xephi/authme/settings/properties/PluginSettings.java
index 6fea29fb..cf0f7932 100644
--- a/src/main/java/fr/xephi/authme/settings/properties/PluginSettings.java
+++ b/src/main/java/fr/xephi/authme/settings/properties/PluginSettings.java
@@ -53,6 +53,12 @@ public class PluginSettings implements SettingsClass {
public static final Property ENABLE_PERMISSION_CHECK =
newProperty("permission.EnablePermissionCheck", false);
+ @Comment({
+ "Keeps collisions disabled for logged players",
+ "Works only with MC 1.9"
+ })
+ public static final Property KEEP_COLLISIONS_DISABLED =
+ newProperty("settings.restrictions.keepCollisionsDisabled", false);
private PluginSettings() {
}
diff --git a/src/main/java/fr/xephi/authme/settings/properties/RegistrationSettings.java b/src/main/java/fr/xephi/authme/settings/properties/RegistrationSettings.java
index c2c2bbe3..db1cb1ee 100644
--- a/src/main/java/fr/xephi/authme/settings/properties/RegistrationSettings.java
+++ b/src/main/java/fr/xephi/authme/settings/properties/RegistrationSettings.java
@@ -67,7 +67,7 @@ public class RegistrationSettings implements SettingsClass {
newListProperty("settings.forceRegisterCommandsAsConsole");
@Comment({
- "Enable to display the welcome message (welcome.txt) after a registration or a login",
+ "Enable to display the welcome message (welcome.txt) after a login",
"You can use colors in this welcome.txt + some replaced strings:",
"{PLAYER}: player name, {ONLINE}: display number of online players, {MAXPLAYERS}: display server slots,",
"{IP}: player ip, {LOGINS}: number of players logged, {WORLD}: player current world, {SERVER}: server name",
diff --git a/src/main/java/fr/xephi/authme/settings/properties/RestrictionSettings.java b/src/main/java/fr/xephi/authme/settings/properties/RestrictionSettings.java
index c2b2cb68..134f9e17 100644
--- a/src/main/java/fr/xephi/authme/settings/properties/RestrictionSettings.java
+++ b/src/main/java/fr/xephi/authme/settings/properties/RestrictionSettings.java
@@ -12,15 +12,19 @@ import static fr.xephi.authme.settings.domain.Property.newProperty;
public class RestrictionSettings implements SettingsClass {
@Comment({
- "Can not authenticated players chat and see the chat log?",
+ "Can not authenticated players chat?",
"Keep in mind that this feature also blocks all commands not",
"listed in the list below."})
public static final Property ALLOW_CHAT =
newProperty("settings.restrictions.allowChat", false);
+ @Comment("Hide the chat log from players who are not authenticated?")
+ public static final Property HIDE_CHAT =
+ newProperty("settings.restrictions.hideChat", false);
+
@Comment({
"Allow unlogged users to use all the commands if registration is not forced!",
- "WARNING: use this only if you need it!)"})
+ "WARNING: use this only if you need it!"})
public static final Property ALLOW_ALL_COMMANDS_IF_REGISTRATION_IS_OPTIONAL =
newProperty("settings.restrictions.allowAllCommandsIfRegistrationIsOptional", false);
@@ -29,8 +33,9 @@ public class RestrictionSettings implements SettingsClass {
newListProperty("settings.restrictions.allowCommands",
"login", "register", "l", "reg", "email", "captcha");
- @Comment("Max number of allowed registrations per IP")
- // TODO ljacqu 20160109: If 0 == unlimited, add this fact to the comment
+ @Comment({
+ "Max number of allowed registrations per IP",
+ "The value 0 means an unlimited number of registrations!"})
public static final Property MAX_REGISTRATION_PER_IP =
newProperty("settings.restrictions.maxRegPerIp", 1);
diff --git a/src/main/java/fr/xephi/authme/settings/properties/SettingsFieldRetriever.java b/src/main/java/fr/xephi/authme/settings/properties/SettingsFieldRetriever.java
index b4adfa07..ac8d65d9 100644
--- a/src/main/java/fr/xephi/authme/settings/properties/SettingsFieldRetriever.java
+++ b/src/main/java/fr/xephi/authme/settings/properties/SettingsFieldRetriever.java
@@ -38,7 +38,7 @@ public final class SettingsFieldRetriever {
for (Class> clazz : CONFIGURATION_CLASSES) {
Field[] declaredFields = clazz.getDeclaredFields();
for (Field field : declaredFields) {
- Property property = getPropertyField(field);
+ Property> property = getPropertyField(field);
if (property != null) {
properties.put(property, getCommentsForField(field));
}
@@ -64,7 +64,7 @@ public final class SettingsFieldRetriever {
field.setAccessible(true);
if (field.isAccessible() && Property.class.equals(field.getType()) && Modifier.isStatic(field.getModifiers())) {
try {
- return (Property) field.get(null);
+ return (Property>) field.get(null);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Could not fetch field '" + field.getName() + "' from class '"
+ field.getDeclaringClass().getSimpleName() + "': " + StringUtils.formatException(e));
diff --git a/src/main/java/fr/xephi/authme/settings/propertymap/PropertyMap.java b/src/main/java/fr/xephi/authme/settings/propertymap/PropertyMap.java
index 9cac52d3..aed4ac0e 100644
--- a/src/main/java/fr/xephi/authme/settings/propertymap/PropertyMap.java
+++ b/src/main/java/fr/xephi/authme/settings/propertymap/PropertyMap.java
@@ -31,7 +31,7 @@ public class PropertyMap {
* @param property The property to add
* @param comments The comments associated to the property
*/
- public void put(Property property, String[] comments) {
+ public void put(Property> property, String[] comments) {
comparator.add(property);
map.put(property, comments);
}
diff --git a/src/main/java/fr/xephi/authme/settings/propertymap/PropertyMapComparator.java b/src/main/java/fr/xephi/authme/settings/propertymap/PropertyMapComparator.java
index a7ec1cb3..e6bd9fb4 100644
--- a/src/main/java/fr/xephi/authme/settings/propertymap/PropertyMapComparator.java
+++ b/src/main/java/fr/xephi/authme/settings/propertymap/PropertyMapComparator.java
@@ -13,7 +13,7 @@ import java.util.Comparator;
* property, then "DataSource" properties will come before the "security" ones.
*
*/
-final class PropertyMapComparator implements Comparator {
+final class PropertyMapComparator implements Comparator> {
private Node parent = Node.createRoot();
@@ -22,12 +22,12 @@ final class PropertyMapComparator implements Comparator {
*
* @param property The property that is being added
*/
- public void add(Property property) {
+ public void add(Property> property) {
parent.addNode(property.getPath());
}
@Override
- public int compare(Property p1, Property p2) {
+ public int compare(Property> p1, Property> p2) {
return parent.compare(p1.getPath(), p2.getPath());
}
diff --git a/src/main/java/fr/xephi/authme/task/MessageTask.java b/src/main/java/fr/xephi/authme/task/MessageTask.java
index 56d1493d..e09d5039 100644
--- a/src/main/java/fr/xephi/authme/task/MessageTask.java
+++ b/src/main/java/fr/xephi/authme/task/MessageTask.java
@@ -1,10 +1,10 @@
package fr.xephi.authme.task;
-import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.output.MessageKey;
-import fr.xephi.authme.util.Utils;
+import fr.xephi.authme.output.Messages;
+import fr.xephi.authme.util.BukkitService;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
@@ -12,28 +12,27 @@ import org.bukkit.scheduler.BukkitTask;
*/
public class MessageTask implements Runnable {
- private final AuthMe plugin;
+ private final BukkitService bukkitService;
private final String name;
private final String[] msg;
private final int interval;
- /**
- * Constructor for MessageTask.
- *
- * @param plugin AuthMe
- * @param name String
- * @param lines String[]
- * @param interval int
+ /*
+ * Constructor.
*/
- public MessageTask(AuthMe plugin, String name, String[] lines, int interval) {
- this.plugin = plugin;
+ public MessageTask(BukkitService bukkitService, String name, String[] lines, int interval) {
+ this.bukkitService = bukkitService;
this.name = name;
this.msg = lines;
this.interval = interval;
}
- public MessageTask(AuthMe plugin, String name, MessageKey messageKey, int interval) {
- this(plugin, name, plugin.getMessages().retrieve(messageKey), interval);
+ /*
+ * Constructor.
+ */
+ public MessageTask(BukkitService bukkitService, Messages messages, String name, MessageKey messageKey,
+ int interval) {
+ this(bukkitService, name, messages.retrieve(messageKey), interval);
}
@Override
@@ -42,12 +41,12 @@ public class MessageTask implements Runnable {
return;
}
- for (Player player : Utils.getOnlinePlayers()) {
+ for (Player player : bukkitService.getOnlinePlayers()) {
if (player.getName().equalsIgnoreCase(name)) {
for (String ms : msg) {
player.sendMessage(ms);
}
- BukkitTask nextTask = plugin.getServer().getScheduler().runTaskLater(plugin, this, interval * 20);
+ BukkitTask nextTask = bukkitService.runTaskLater(this, interval * 20);
if (LimboCache.getInstance().hasLimboPlayer(name)) {
LimboCache.getInstance().getLimboPlayer(name).setMessageTask(nextTask);
}
diff --git a/src/main/java/fr/xephi/authme/util/BukkitService.java b/src/main/java/fr/xephi/authme/util/BukkitService.java
index 053fe789..ea405d80 100644
--- a/src/main/java/fr/xephi/authme/util/BukkitService.java
+++ b/src/main/java/fr/xephi/authme/util/BukkitService.java
@@ -1,7 +1,18 @@
package fr.xephi.authme.util;
import fr.xephi.authme.AuthMe;
+import fr.xephi.authme.ConsoleLogger;
import org.bukkit.Bukkit;
+import org.bukkit.OfflinePlayer;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitTask;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
/**
* Service for operations requiring server entities, such as for scheduling.
@@ -14,9 +25,12 @@ public class BukkitService {
public static final int TICKS_PER_MINUTE = 60 * TICKS_PER_SECOND;
private final AuthMe authMe;
+ private final boolean getOnlinePlayersIsCollection;
+ private Method getOnlinePlayers;
public BukkitService(AuthMe authMe) {
this.authMe = authMe;
+ getOnlinePlayersIsCollection = initializeOnlinePlayersIsCollectionField();
}
/**
@@ -44,6 +58,47 @@ public class BukkitService {
return Bukkit.getScheduler().scheduleSyncDelayedTask(authMe, task, delay);
}
+ /**
+ * Returns a task that will run on the next server tick.
+ *
+ * @param task the task to be run
+ * @return a BukkitTask that contains the id number
+ * @throws IllegalArgumentException if plugin is null
+ * @throws IllegalArgumentException if task is null
+ */
+ public BukkitTask runTask(Runnable task) {
+ return Bukkit.getScheduler().runTask(authMe, task);
+ }
+
+ /**
+ * Returns a task that will run after the specified number of server
+ * ticks.
+ *
+ * @param task the task to be run
+ * @param delay the ticks to wait before running the task
+ * @return a BukkitTask that contains the id number
+ * @throws IllegalArgumentException if plugin is null
+ * @throws IllegalArgumentException if task is null
+ */
+ public BukkitTask runTaskLater(Runnable task, long delay) {
+ return Bukkit.getScheduler().runTaskLater(authMe, task, delay);
+ }
+
+ /**
+ * Asynchronous tasks should never access any API in Bukkit. Great care
+ * should be taken to assure the thread-safety of asynchronous tasks.
+ *
+ * Returns a task that will run asynchronously.
+ *
+ * @param task the task to be run
+ * @return a BukkitTask that contains the id number
+ * @throws IllegalArgumentException if plugin is null
+ * @throws IllegalArgumentException if task is null
+ */
+ public BukkitTask runTaskAsynchronously(Runnable task) {
+ return Bukkit.getScheduler().runTaskAsynchronously(authMe, task);
+ }
+
/**
* Broadcast a message to all players.
*
@@ -54,4 +109,76 @@ public class BukkitService {
return Bukkit.broadcastMessage(message);
}
+ /**
+ * Gets the player with the exact given name, case insensitive.
+ *
+ * @param name Exact name of the player to retrieve
+ * @return a player object if one was found, null otherwise
+ */
+ public Player getPlayerExact(String name) {
+ return authMe.getServer().getPlayerExact(name);
+ }
+
+ /**
+ * Gets a set containing all banned players.
+ *
+ * @return a set containing banned players
+ */
+ public Set getBannedPlayers() {
+ return Bukkit.getBannedPlayers();
+ }
+
+ /**
+ * Safe way to retrieve the list of online players from the server. Depending on the
+ * implementation of the server, either an array of {@link Player} instances is being returned,
+ * or a Collection. Always use this wrapper to retrieve online players instead of {@link
+ * Bukkit#getOnlinePlayers()} directly.
+ *
+ * @return collection of online players
+ *
+ * @see SpigotMC
+ * forum
+ * @see StackOverflow
+ */
+ @SuppressWarnings("unchecked")
+ public Collection extends Player> getOnlinePlayers() {
+ if (getOnlinePlayersIsCollection) {
+ return Bukkit.getOnlinePlayers();
+ }
+ try {
+ // The lookup of a method via Reflections is rather expensive, so we keep a reference to it
+ if (getOnlinePlayers == null) {
+ getOnlinePlayers = Bukkit.class.getDeclaredMethod("getOnlinePlayers");
+ }
+ Object obj = getOnlinePlayers.invoke(null);
+ if (obj instanceof Collection>) {
+ return (Collection extends Player>) obj;
+ } else if (obj instanceof Player[]) {
+ return Arrays.asList((Player[]) obj);
+ } else {
+ String type = (obj != null) ? obj.getClass().getName() : "null";
+ ConsoleLogger.showError("Unknown list of online players of type " + type);
+ }
+ } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+ ConsoleLogger.logException("Could not retrieve list of online players:", e);
+ }
+ return Collections.emptyList();
+ }
+
+ /**
+ * Method run upon initialization to verify whether or not the Bukkit implementation
+ * returns the online players as a Collection.
+ *
+ * @see #getOnlinePlayers()
+ */
+ private static boolean initializeOnlinePlayersIsCollectionField() {
+ try {
+ Method method = Bukkit.class.getDeclaredMethod("getOnlinePlayers");
+ return method.getReturnType() == Collection.class;
+ } catch (NoSuchMethodException e) {
+ ConsoleLogger.showError("Error verifying if getOnlinePlayers is a collection! Method doesn't exist");
+ }
+ return false;
+ }
+
}
diff --git a/src/main/java/fr/xephi/authme/util/GeoLiteAPI.java b/src/main/java/fr/xephi/authme/util/GeoLiteAPI.java
index d5cba2d7..83594086 100644
--- a/src/main/java/fr/xephi/authme/util/GeoLiteAPI.java
+++ b/src/main/java/fr/xephi/authme/util/GeoLiteAPI.java
@@ -1,8 +1,8 @@
package fr.xephi.authme.util;
import com.maxmind.geoip.LookupService;
+import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
-import fr.xephi.authme.settings.Settings;
import java.io.File;
import java.io.FileOutputStream;
@@ -37,7 +37,8 @@ public class GeoLiteAPI {
if (lookupService != null) {
return true;
}
- final File data = new File(Settings.PLUGIN_FOLDER, "GeoIP.dat");
+ final File pluginFolder = AuthMe.getInstance().getDataFolder();
+ final File data = new File(pluginFolder, "GeoIP.dat");
boolean dataIsOld = (System.currentTimeMillis() - data.lastModified()) > TimeUnit.DAYS.toMillis(30);
if (dataIsOld && !data.delete()) {
ConsoleLogger.showError("Failed to delete GeoLiteAPI database");
diff --git a/src/main/java/fr/xephi/authme/util/MigrationService.java b/src/main/java/fr/xephi/authme/util/MigrationService.java
index 86f98e4c..7bf028f6 100644
--- a/src/main/java/fr/xephi/authme/util/MigrationService.java
+++ b/src/main/java/fr/xephi/authme/util/MigrationService.java
@@ -37,12 +37,17 @@ public final class MigrationService {
if (HashAlgorithm.PLAINTEXT == settings.getProperty(SecuritySettings.PASSWORD_HASH)) {
ConsoleLogger.showError("Your HashAlgorithm has been detected as plaintext and is now deprecated;"
+ " it will be changed and hashed now to the AuthMe default hashing method");
+ ConsoleLogger.showError("Don't stop your server; wait for the conversion to have been completed!");
List allAuths = dataSource.getAllAuths();
for (PlayerAuth auth : allAuths) {
- HashedPassword hashedPassword = authmeSha256.computeHash(
- auth.getPassword().getHash(), auth.getNickname());
- auth.setPassword(hashedPassword);
- dataSource.updatePassword(auth);
+ String hash = auth.getPassword().getHash();
+ if (hash.startsWith("$SHA$")) {
+ ConsoleLogger.showError("Skipping conversion for " + auth.getNickname() + "; detected SHA hash");
+ } else {
+ HashedPassword hashedPassword = authmeSha256.computeHash(hash, auth.getNickname());
+ auth.setPassword(hashedPassword);
+ dataSource.updatePassword(auth);
+ }
}
settings.setProperty(SecuritySettings.PASSWORD_HASH, HashAlgorithm.SHA256);
settings.save();
diff --git a/src/main/java/fr/xephi/authme/util/Utils.java b/src/main/java/fr/xephi/authme/util/Utils.java
index c399f655..5850645b 100644
--- a/src/main/java/fr/xephi/authme/util/Utils.java
+++ b/src/main/java/fr/xephi/authme/util/Utils.java
@@ -7,41 +7,23 @@ import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.cache.limbo.LimboPlayer;
import fr.xephi.authme.events.AuthMeTeleportEvent;
import fr.xephi.authme.permission.PermissionsManager;
-import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.Settings;
-import fr.xephi.authme.settings.properties.EmailSettings;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.entity.Player;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
/**
* Utility class for various operations used in the codebase.
*/
public final class Utils {
- private static AuthMe plugin;
- private static Wrapper wrapper;
-
- private static boolean getOnlinePlayersIsCollection = false;
- private static Method getOnlinePlayers;
-
- static {
- wrapper = Wrapper.getInstance();
- plugin = wrapper.getAuthMe();
- initializeOnlinePlayersIsCollectionField();
- }
+ private static AuthMe plugin = AuthMe.getInstance();
private Utils() {
- // Utility class
}
/**
@@ -170,12 +152,12 @@ public final class Utils {
final World world = theWorld;
final Location loc = new Location(world, x, y, z);
- Bukkit.getScheduler().scheduleSyncDelayedTask(wrapper.getAuthMe(), new Runnable() {
+ Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
@Override
public void run() {
AuthMeTeleportEvent tpEvent = new AuthMeTeleportEvent(pl, loc);
- wrapper.getServer().getPluginManager().callEvent(tpEvent);
+ plugin.getServer().getPluginManager().callEvent(tpEvent);
if (!tpEvent.isCancelled()) {
pl.teleport(tpEvent.getTo());
}
@@ -183,62 +165,6 @@ public final class Utils {
});
}
- /**
- * Safe way to retrieve the list of online players from the server. Depending on the
- * implementation of the server, either an array of {@link Player} instances is being returned,
- * or a Collection. Always use this wrapper to retrieve online players instead of {@link
- * Bukkit#getOnlinePlayers()} directly.
- *
- * @return collection of online players
- *
- * @see SpigotMC
- * forum
- * @see StackOverflow
- */
- @SuppressWarnings("unchecked")
- public static Collection extends Player> getOnlinePlayers() {
- if (getOnlinePlayersIsCollection) {
- return Bukkit.getOnlinePlayers();
- }
- try {
- // The lookup of a method via Reflections is rather expensive, so we keep a reference to it
- if (getOnlinePlayers == null) {
- getOnlinePlayers = Bukkit.class.getDeclaredMethod("getOnlinePlayers");
- }
- Object obj = getOnlinePlayers.invoke(null);
- if (obj instanceof Collection>) {
- return (Collection extends Player>) obj;
- } else if (obj instanceof Player[]) {
- return Arrays.asList((Player[]) obj);
- } else {
- String type = (obj != null) ? obj.getClass().getName() : "null";
- ConsoleLogger.showError("Unknown list of online players of type " + type);
- }
- } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
- ConsoleLogger.logException("Could not retrieve list of online players:", e);
- }
- return Collections.emptyList();
- }
-
- /**
- * Method run when the Utils class is loaded to verify whether or not the Bukkit implementation
- * returns the online players as a Collection.
- *
- * @see Utils#getOnlinePlayers()
- */
- private static void initializeOnlinePlayersIsCollectionField() {
- try {
- Method method = Bukkit.class.getDeclaredMethod("getOnlinePlayers");
- getOnlinePlayersIsCollection = method.getReturnType() == Collection.class;
- } catch (NoSuchMethodException e) {
- ConsoleLogger.showError("Error verifying if getOnlinePlayers is a collection! Method doesn't exist");
- }
- }
-
- public static Player getPlayer(String name) {
- return wrapper.getServer().getPlayerExact(name);
- }
-
public static boolean isNPC(Player player) {
return player.hasMetadata("NPC") || plugin.getPluginHooks().isNpcInCombatTagPlus(player);
}
@@ -247,45 +173,19 @@ public final class Utils {
if (Settings.isTeleportToSpawnEnabled && !Settings.noTeleport) {
Location spawn = plugin.getSpawnLocation(player);
AuthMeTeleportEvent tpEvent = new AuthMeTeleportEvent(player, spawn);
- wrapper.getServer().getPluginManager().callEvent(tpEvent);
+ plugin.getServer().getPluginManager().callEvent(tpEvent);
if (!tpEvent.isCancelled()) {
player.teleport(tpEvent.getTo());
}
}
}
- public static boolean isEmailCorrect(String email, NewSetting settings) {
- if (!email.contains("@") || "your@email.com".equalsIgnoreCase(email)) {
- return false;
- }
- final String emailDomain = email.split("@")[1];
-
- List whitelist = settings.getProperty(EmailSettings.DOMAIN_WHITELIST);
- if (!CollectionUtils.isEmpty(whitelist)) {
- return containsIgnoreCase(whitelist, emailDomain);
- }
-
- List blacklist = settings.getProperty(EmailSettings.DOMAIN_BLACKLIST);
- return CollectionUtils.isEmpty(blacklist) || !containsIgnoreCase(blacklist, emailDomain);
- }
-
- private static boolean containsIgnoreCase(Collection coll, String needle) {
- for (String entry : coll) {
- if (entry.equalsIgnoreCase(needle)) {
- return true;
- }
- }
- return false;
- }
-
public static String getUUIDorName(OfflinePlayer player) {
- String uuidOrName;
try {
- uuidOrName = player.getUniqueId().toString();
+ return player.getUniqueId().toString();
} catch (Exception ignore) {
- uuidOrName = player.getName();
+ return player.getName();
}
- return uuidOrName;
}
public enum GroupType {
@@ -294,4 +194,15 @@ public final class Utils {
NOTLOGGEDIN,
LOGGEDIN
}
+
+ /**
+ * Returns the IP of the given player.
+ *
+ * @param p The player to return the IP address for
+ *
+ * @return The player's IP address
+ */
+ public static String getPlayerIp(Player p) {
+ return p.getAddress().getAddress().getHostAddress();
+ }
}
diff --git a/src/main/java/fr/xephi/authme/util/ValidationService.java b/src/main/java/fr/xephi/authme/util/ValidationService.java
new file mode 100644
index 00000000..95dff810
--- /dev/null
+++ b/src/main/java/fr/xephi/authme/util/ValidationService.java
@@ -0,0 +1,133 @@
+package fr.xephi.authme.util;
+
+import fr.xephi.authme.datasource.DataSource;
+import fr.xephi.authme.output.MessageKey;
+import fr.xephi.authme.permission.PermissionsManager;
+import fr.xephi.authme.permission.PlayerStatePermission;
+import fr.xephi.authme.settings.NewSetting;
+import fr.xephi.authme.settings.domain.Property;
+import fr.xephi.authme.settings.properties.EmailSettings;
+import fr.xephi.authme.settings.properties.ProtectionSettings;
+import fr.xephi.authme.settings.properties.RestrictionSettings;
+import fr.xephi.authme.settings.properties.SecuritySettings;
+import org.bukkit.command.CommandSender;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Validation service.
+ */
+public class ValidationService {
+
+ private final NewSetting settings;
+ private final DataSource dataSource;
+ private final PermissionsManager permissionsManager;
+
+ public ValidationService(NewSetting settings, DataSource dataSource, PermissionsManager permissionsManager) {
+ this.settings = settings;
+ this.dataSource = dataSource;
+ this.permissionsManager = permissionsManager;
+ }
+
+ /**
+ * Verifies whether a password is valid according to the plugin settings.
+ *
+ * @param password the password to verify
+ * @param username the username the password is associated with
+ * @return message key with the password error, or {@code null} if password is valid
+ */
+ public MessageKey validatePassword(String password, String username) {
+ String passLow = password.toLowerCase();
+ if (!passLow.matches(settings.getProperty(RestrictionSettings.ALLOWED_PASSWORD_REGEX))) {
+ return MessageKey.PASSWORD_MATCH_ERROR;
+ } else if (passLow.equalsIgnoreCase(username)) {
+ return MessageKey.PASSWORD_IS_USERNAME_ERROR;
+ } else if (password.length() < settings.getProperty(SecuritySettings.MIN_PASSWORD_LENGTH)
+ || password.length() > settings.getProperty(SecuritySettings.MAX_PASSWORD_LENGTH)) {
+ return MessageKey.INVALID_PASSWORD_LENGTH;
+ } else if (settings.getProperty(SecuritySettings.UNSAFE_PASSWORDS).contains(passLow)) {
+ // TODO #602 20160312: The UNSAFE_PASSWORDS should be all lowercase
+ // -> introduce a lowercase String list property type
+ return MessageKey.PASSWORD_UNSAFE_ERROR;
+ }
+ return null;
+ }
+
+ /**
+ * Verifies whether the email is valid and admitted for use according to the plugin settings.
+ *
+ * @param email the email to verify
+ * @return true if the email is valid, false otherwise
+ */
+ public boolean validateEmail(String email) {
+ if (!email.contains("@") || "your@email.com".equalsIgnoreCase(email)) {
+ return false;
+ }
+ final String emailDomain = email.split("@")[1];
+ return validateWhitelistAndBlacklist(
+ emailDomain, EmailSettings.DOMAIN_WHITELIST, EmailSettings.DOMAIN_BLACKLIST);
+ }
+
+ /**
+ * Queries the database whether the email is still free for registration, i.e. whether the given
+ * command sender may use the email to register a new account (as defined by settings and permissions).
+ *
+ * @param email the email to verify
+ * @param sender the command sender
+ * @return true if the email may be used, false otherwise (registration threshold has been exceeded)
+ */
+ public boolean isEmailFreeForRegistration(String email, CommandSender sender) {
+ return permissionsManager.hasPermission(sender, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)
+ || dataSource.countAuthsByEmail(email) < settings.getProperty(EmailSettings.MAX_REG_PER_EMAIL);
+ }
+
+ /**
+ * Checks whether the player's country is allowed to join the server, based on the given IP address
+ * and the configured country whitelist or blacklist.
+ *
+ * @param hostAddress the IP address to verify
+ * @return true if the IP address' country is allowed, false otherwise
+ */
+ public boolean isCountryAdmitted(String hostAddress) {
+ // Check if we have restrictions on country, if not return true and avoid the country lookup
+ if (settings.getProperty(ProtectionSettings.COUNTRIES_WHITELIST).isEmpty()
+ && settings.getProperty(ProtectionSettings.COUNTRIES_BLACKLIST).isEmpty()) {
+ return true;
+ }
+
+ String countryCode = GeoLiteAPI.getCountryCode(hostAddress);
+ return validateWhitelistAndBlacklist(countryCode,
+ ProtectionSettings.COUNTRIES_WHITELIST,
+ ProtectionSettings.COUNTRIES_BLACKLIST);
+ }
+
+ /**
+ * Verifies whether the given value is allowed according to the given whitelist and blacklist settings.
+ * Whitelist has precedence over blacklist: if a whitelist is set, the value is rejected if not present
+ * in the whitelist.
+ *
+ * @param value the value to verify
+ * @param whitelist the whitelist property
+ * @param blacklist the blacklist property
+ * @return true if the value is admitted by the lists, false otherwise
+ */
+ private boolean validateWhitelistAndBlacklist(String value, Property> whitelist,
+ Property> blacklist) {
+ List whitelistValue = settings.getProperty(whitelist);
+ if (!CollectionUtils.isEmpty(whitelistValue)) {
+ return containsIgnoreCase(whitelistValue, value);
+ }
+ List blacklistValue = settings.getProperty(blacklist);
+ return CollectionUtils.isEmpty(blacklistValue) || !containsIgnoreCase(blacklistValue, value);
+ }
+
+ private static boolean containsIgnoreCase(Collection coll, String needle) {
+ for (String entry : coll) {
+ if (entry.equalsIgnoreCase(needle)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/fr/xephi/authme/util/Wrapper.java b/src/main/java/fr/xephi/authme/util/Wrapper.java
deleted file mode 100644
index bdd1d5a2..00000000
--- a/src/main/java/fr/xephi/authme/util/Wrapper.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package fr.xephi.authme.util;
-
-import fr.xephi.authme.AuthMe;
-import fr.xephi.authme.cache.auth.PlayerCache;
-import fr.xephi.authme.output.Messages;
-import org.bukkit.Bukkit;
-import org.bukkit.Server;
-import org.bukkit.scheduler.BukkitScheduler;
-
-import java.io.File;
-
-/**
- * Wrapper for the retrieval of common singletons used throughout the application.
- * This class simply delegates the calls.
- */
-public class Wrapper {
-
- private static Wrapper singleton;
-
- /**
- * Package-private constructor for testing purposes to inject a mock instance.
- */
- Wrapper() {
- }
-
- /**
- * Package-private setter of the singleton field used for tests to inject a mock instance.
- *
- * @param wrapper The wrapper to use as singleton
- */
- static void setSingleton(Wrapper wrapper) {
- Wrapper.singleton = wrapper;
- }
-
- public static Wrapper getInstance() {
- if (singleton == null) {
- singleton = new Wrapper();
- }
- return singleton;
- }
-
- public AuthMe getAuthMe() {
- return AuthMe.getInstance();
- }
-
- public Server getServer() {
- return getAuthMe().getServer();
- }
-
- public Messages getMessages() {
- return getAuthMe().getMessages();
- }
-
- public PlayerCache getPlayerCache() {
- return PlayerCache.getInstance();
- }
-
- /**
- * Return the folder containing plugin data via the AuthMe instance.
- *
- * @return The plugin data folder
- * @see AuthMe#getDataFolder()
- */
- public File getDataFolder() {
- return getAuthMe().getDataFolder();
- }
-
- public BukkitScheduler getScheduler() {
- return Bukkit.getScheduler();
- }
-
-
-
-}
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index dc52379a..17b62b37 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -67,6 +67,8 @@ settings:
# Care that this feature blocks also all the commands not
# listed in the list below.
allowChat: false
+ # Can not authenticated players see the chat log?
+ hideChat: false
# WARNING: use this only if you need it!
# Allow unlogged users to use all the commands if registration is not forced!
allowAllCommandsIfRegistrationIsOptional: false
@@ -159,6 +161,9 @@ settings:
noTeleport: false
# Regex syntax for allowed Chars in passwords.
allowedPasswordCharacters: '[\x21-\x7E]*'
+ # Keeps collisions disabled for logged players
+ # Works only with MC 1.9
+ keepCollisionsDisabled: false
GameMode:
# ForceSurvivalMode to player when join ?
ForceSurvivalMode: false
@@ -248,11 +253,11 @@ settings:
forceRegisterCommands: []
# Force these commands after /register as a server console, without any '/', use %p for replace with player name
forceRegisterCommandsAsConsole: []
- # Do we need to display the welcome message (welcome.txt) after a register or a login?
- # You can use colors in this welcome.txt + some replaced strings :
- # {PLAYER} : player name, {ONLINE} : display number of online players, {MAXPLAYERS} : display server slots,
- # {IP} : player ip, {LOGINS} : number of players logged, {WORLD} : player current world, {SERVER} : server name
- # {VERSION} : get current bukkit version, {COUNTRY} : player country
+ # Do we need to display the welcome message (welcome.txt) after a login?
+ # You can use colors in this welcome.txt + some replaced strings:
+ # {PLAYER}: player name, {ONLINE}: display number of online players, {MAXPLAYERS}: display server slots,
+ # {IP}: player ip, {LOGINS}: number of players logged, {WORLD}: player current world, {SERVER}: server name
+ # {VERSION}: get current bukkit version, {COUNTRY}: player country
useWelcomeMessage: true
# Do we need to broadcast the welcome message to all server or only to the player? set true for server or false for player
broadcastWelcomeMessage: false
@@ -418,6 +423,3 @@ Protection:
antiBotSensibility: 5
# Duration in minutes of the antibot automatic system
antiBotDuration: 10
-VeryGames:
- # These features are only available on VeryGames Server Provider
- enableIpCheck: false
diff --git a/src/main/resources/messages/messages_de.yml b/src/main/resources/messages/messages_de.yml
index 04345292..4cc59867 100644
--- a/src/main/resources/messages/messages_de.yml
+++ b/src/main/resources/messages/messages_de.yml
@@ -1,30 +1,30 @@
unknown_user: '&cBenutzer ist nicht in der Datenbank'
-unsafe_spawn: '&cDeine Logoutposition war unsicher, Du wurdest zum Spawn teleportiert'
+unsafe_spawn: '&cDeine Logoutposition war unsicher, du wurdest zum Spawn teleportiert'
not_logged_in: '&cNicht eingeloggt!'
-reg_voluntarily: 'Du kannst dich mit folgendem Befehl registrieren "/register "'
+reg_voluntarily: 'Du kannst dich mit folgendem Befehl registrieren: "/register "'
usage_log: '&cBenutze: /login '
wrong_pwd: '&cFalsches Passwort'
unregistered: '&cBenutzerkonto erfolgreich gelöscht!'
reg_disabled: '&cRegistrierungen sind deaktiviert'
valid_session: '&2Erfolgreich eingeloggt!'
login: '&2Erfolgreich eingeloggt!'
-vb_nonActiv: '&cDein Account wurde noch nicht aktiviert. Bitte prüfe Deine E-Mails!'
+vb_nonActiv: '&cDein Account wurde noch nicht aktiviert. Bitte prüfe deine E-Mails!'
user_regged: '&cDieser Benutzername ist schon vergeben'
usage_reg: '&cBenutze: /register '
-max_reg: '&cDu hast die maximale Anzahl an Accounts erreicht.'
+max_reg: '&cDu hast die maximale Anzahl an Accounts erreicht (%max_acc/%reg_count).'
no_perm: '&4Du hast keine Rechte, um diese Aktion auszuführen!'
error: '&4Ein Fehler ist aufgetreten. Bitte kontaktiere einen Administrator.'
-login_msg: '&cBitte logge Dich ein mit "/login "'
-reg_msg: '&3Bitte registriere Dich mit "/register "'
-reg_email_msg: '&3Bitte registriere Dich mit "/register "'
+login_msg: '&cBitte logge dich ein mit "/login "'
+reg_msg: '&3Bitte registriere dich mit "/register "'
+reg_email_msg: '&3Bitte registriere dich mit "/register "'
usage_unreg: '&cBenutze: /unregister '
pwd_changed: '&2Passwort geändert!'
user_unknown: '&cBenutzername nicht registriert!'
password_error: '&cPasswörter stimmen nicht überein!'
-password_error_nick: '&cDu kannst nicht Deinen Namen als Passwort nutzen!'
-password_error_unsafe: '&cDu kannst nicht unsichere Passwörter nutzen!'
-invalid_session: '&cUngültige Session. Bitte starte das Spiel neu oder warte, bis die Session abgelaufen ist'
-reg_only: '&4Nur für registrierte Spieler! Bitte besuche http://example.com zum Registrieren'
+password_error_nick: '&cDu kannst deinen Namen nicht als Passwort verwenden!'
+password_error_unsafe: '&cPasswort unsicher! Bitte wähle ein anderes.'
+invalid_session: '&cUngültige Session. Bitte starte das Spiel neu oder warte, bis die Session abgelaufen ist.'
+reg_only: '&4Nur für registrierte Spieler! Bitte besuche http://example.com um dich zu registrieren.'
logged_in: '&cBereits eingeloggt!'
logout: '&2Erfolgreich ausgeloggt'
same_nick: '&4Jemand mit diesem Namen spielt bereits auf dem Server!'
@@ -34,8 +34,8 @@ reload: '&2Konfiguration und Datenbank wurden erfolgreich neu geladen.'
timeout: '&4Zeitüberschreitung beim Login'
usage_changepassword: '&cBenutze: /changepassword '
name_len: '&4Dein Nickname ist zu kurz oder zu lang.'
-regex: '&4Dein Nickname enthält nicht erlaubte Zeichen. Zulässige Zeichen: REG_EX'
-add_email: '&3Bitte hinterlege Deine E-Mail-Adresse: /email add '
+regex: '&4Dein Nickname enthält unerlaubte Zeichen. Zulässige Zeichen: REG_EX'
+add_email: '&3Bitte hinterlege deine E-Mail-Adresse: /email add '
recovery_email: '&3Passwort vergessen? Nutze "/email recovery " für ein neues Passwort'
usage_captcha: '&3Um dich einzuloggen, tippe dieses Captcha so ein: /captcha '
wrong_captcha: '&cFalsches Captcha, bitte nutze: /captcha THE_CAPTCHA'
@@ -49,14 +49,14 @@ new_email_invalid: '&cDie neue E-Mail ist ungültig!'
old_email_invalid: '&cDie alte E-Mail ist ungültig!'
email_invalid: '&cUngültige E-Mail!'
email_added: '&2E-Mail hinzugefügt!'
-email_confirm: '&cBitte bestätige Deine E-Mail!'
+email_confirm: '&cBitte bestätige deine E-Mail!'
email_changed: '&2E-Mail aktualisiert!'
email_send: '&2Wiederherstellungs-E-Mail wurde gesendet!'
email_exists: '&cEine Wiederherstellungs-E-Mail wurde bereits versandt! Nutze folgenden Befehl um eine neue E-Mail zu versenden:'
country_banned: '&4Dein Land ist gesperrt!'
antibot_auto_enabled: '&4[AntiBotService] AntiBotMod wurde aufgrund hoher Netzauslastung automatisch aktiviert!'
antibot_auto_disabled: '&2[AntiBotService] AntiBotMod wurde nach %m Minuten deaktiviert, hoffentlich ist die Invasion vorbei.'
-kick_antibot: 'AntiBotMod ist aktiviert! Bitte warte einige Minuten, bevor Du Dich mit dem Server verbindest.'
+kick_antibot: 'AntiBotMod ist aktiviert! Bitte warte einige Minuten, bevor du dich mit dem Server verbindest.'
two_factor_create: '&2Dein geheimer Code ist %code. Du kannst ihn hier abfragen: %url'
email_already_used: '&4Diese E-Mail-Adresse wird bereits genutzt.'
invalid_name_case: 'Dein registrierter Benutzername ist &2%valid&f - nicht &4%invalid&f.'
diff --git a/src/main/resources/messages/messages_hu.yml b/src/main/resources/messages/messages_hu.yml
index b3f22882..7aa03b39 100644
--- a/src/main/resources/messages/messages_hu.yml
+++ b/src/main/resources/messages/messages_hu.yml
@@ -1,50 +1,50 @@
-reg_only: Csak regisztrált játékosoknak! Jelentkezni a mail@email.com e-mail címen lehet
-usage_unreg: '&cHasználat: /unregister jelszó'
-registered: '&aSikeres regisztráció. Üdvözöllek!'
-user_regged: '&cJátékosnév már regisztrálva'
-login_msg: '&cKérlek jelentkezz be: "/login jelszó"'
+reg_only: '&4Csak regisztrált játékosok tudnak csatlakozni a szerverhez! Kérlek kattints a http://example.com weboldalra és regisztráld magad!'
+usage_unreg: '&cHasználat: "/unregister "'
+registered: '&aSikeres regisztráció.'
+user_regged: '&cEz a játékosnév már regisztrálva van!'
+login_msg: '&cKérlek jelentkezz be: "/login "'
not_logged_in: '&cNem vagy bejelentkezve!'
logout: '&cSikeresen kijelentkeztél!'
-usage_log: '&cBejelentkezés: /login '
-unknown_user: '&cA kért felhasználó nem telálható az adatbázisban!'
-reg_voluntarily: Regisztrálhatod magad a szerveren a következö parancsal "/register "
+usage_log: '&cBejelentkezés: "/login "'
+unknown_user: '&cA kért felhasználó nem található az adatbázisban!'
+reg_voluntarily: Regisztrálhatod magad a szerveren a következö parancsal "/register "
reg_disabled: '&cRegisztráció letiltva!'
no_perm: '&cNincs jogod ehhez!'
-usage_reg: '&cHasználat: /register '
+usage_reg: '&cHasználat: "/register "'
password_error_nick: '&cNem használhatod a felhasználóneved jelszónak, kérlek válassz másikat...'
password_error_unsafe: '&cA választott jelszó nem biztonságos, kérlek válassz másikat...'
unregistered: '&cRegisztráció sikeresen törölve!'
same_nick: 'Ezzel a játékosnévvel már játszanak a szerveren.'
-valid_session: '&2A hálózati kapcsolat újraépítése megtörtént.'
+valid_session: '&2A megadott időkereten belül csatlakoztál vissza így a rendszer automatikusan beléptetett.'
pwd_changed: '&cJelszó cserélve!'
reload: 'Beálítások és adatbázis újratöltve!'
timeout: 'Bejelentkezési időtúllépés!'
-error: 'Hiba lépett fel; Lépj kapcsolatba a tulajjal'
+error: 'Hiba lépett fel! Lépj kapcsolatba a tulajjal!'
logged_in: '&cMár be vagy jelentkezve!'
login: '&aSikeresen beléptél!'
wrong_pwd: '&4Hibás jelszó!'
user_unknown: '&cEz a felhasználó nincs regisztrálva!'
-reg_msg: '&cKérlek Regisztrálj: "/register jelszó jelszóújra"'
+reg_msg: '&cKérlek Regisztrálj: "/register "'
reg_email_msg: '&cKérlek regisztrálj: "/register "'
-unsafe_spawn: 'A kilépési helyzeted nem biztonságos, teleportálás a Spawnra.'
-max_reg: 'Csak egy karakterrel registrálhatsz!'
+unsafe_spawn: 'A kilépési helyzeted nem biztonságos, teleportálás a kezdő pozícióra.'
+max_reg: '&cElérted a maximálisan beregisztrálható karakterek számát. (%reg_count/%max_acc %reg_names)!'
password_error: 'A két jelszó nem egyezik!'
-invalid_session: '&cAz IP címed megváltozott és a hálózati kapcsolatod lejárt. Kapcsolódj újra.'
+invalid_session: '&cAz IP címed megváltozott, ezért a visszacsatlakozási időkereted lejárt.'
pass_len: 'A jelszavad nem éri el a minimális hosszúságot!'
-vb_nonActiv: '&cA felhasználód aktiválása még nem történt meg, ellenőrizd a leveleid!'
-usage_changepassword: 'Használat: /changepassword <új Jelszó>'
+vb_nonActiv: '&cA felhasználód aktiválása még nem történt meg, ellenőrizd a megadott emailed!'
+usage_changepassword: 'Használat: "/changepassword <új Jelszó>"'
name_len: '&4A felhasználó neved túl hosszú, vagy túl rövid! Válassz másikat!'
regex: '&4A felhasználóneved nem használható karaktereket tartalmaz. Elfogadott karakterek: REG_EX'
add_email: '&3Kérlek add hozzá a felhasználódhoz az email címedet "/email add "'
recovery_email: '&3Ha elfelejtetted a jelszavad, használd az: "/email recovery "'
-usage_captcha: '&3A bejelentkezéshez CAPTCHA szükséges, kérem használd a következő parancsot "/captcha "'
-wrong_captcha: '&cHibás captcha, kérlek írd be a következő parancsot "/captcha THE_CAPTCHA" a chat-be!'
-valid_captcha: '&2Captcha sikeresen feloldva!'
+usage_captcha: '&3A bejelentkezéshez CAPTCHA szükséges, kérlek használd a következő parancsot "/captcha "'
+wrong_captcha: '&cHibás CAPTCHA, kérlek írd be a következő parancsot "/captcha THE_CAPTCHA"!'
+valid_captcha: '&2CAPTCHA sikeresen feloldva!'
kick_forvip: '&3VIP játékos csatlakozott a szerverhez!'
kick_fullserver: '&4A szerver megtelt, próbálj csatlakozni később!'
-usage_email_add: '&cHasználat: /email add '
-usage_email_change: '&cHasználat: /email change <új Email>'
-usage_email_recovery: '&cHasználat: /email recovery '
+usage_email_add: '&cHasználat: "/email add "'
+usage_email_change: '&cHasználat: "/email change <új Email>"'
+usage_email_recovery: '&cHasználat: "/email recovery "'
new_email_invalid: '&cHibás az új email cím, próbáld újra!'
old_email_invalid: '&cHibás a régi email cím, próbáld újra!'
email_invalid: '&cHibás az email cím, próbáld újra!'
@@ -52,12 +52,12 @@ email_added: '&2Az email címed rögzítése sikeresen megtörtént!'
email_confirm: '&cKérlek ellenőrízd az email címedet!'
email_changed: '&2Az email cím cseréje sikeresen megtörtént!'
email_send: '&2A jelszó visszaállításhoz szükséges emailt elküldtük! Ellenőrízd a leveleidet!'
-email_exists: '&cA visszaállító emailt elküldtük! Hiba esetén újkérheted az alábbi parancs segítségével:'
+email_exists: '&cA visszaállító emailt elküldtük! Hiba esetén újra kérheted az alábbi parancs segítségével:'
+email_already_used: '&4Ez az email cím már használatban van!'
country_banned: '&4Az országod tiltólistán van ezen a szerveren!'
-antibot_auto_enabled: '&4[AntiBot] Az AntiBot védelem bekapcsolt a nagy számú hálózati kapcsolat miatt!'
-antibot_auto_disabled: '&2[AntiBot] Az AntiBot kikapcsol %m múlva!'
-kick_antibot: 'Az AntiBot védelem bekapcsolva! Kérünk várj pár másodpercet a csatlakozáshoz.'
-# TODO email_already_used: '&4The email address is already being used'
-# TODO invalid_name_case: 'You should join using username %valid, not %invalid.'
-# TODO two_factor_create: '&2Your secret code is %code. You can scan it from here %url'
-# TODO not_owner_error: 'You are not the owner of this account. Please try another name!'
\ No newline at end of file
+antibot_auto_enabled: '&4[AntiBot] Az AntiBot védelem bekapcsolt, mert a megszabott időn belül több felhasználó csatlakozott!'
+antibot_auto_disabled: '&2[AntiBot] Az AntiBot kikapcsol %m perc múlva!'
+kick_antibot: 'Az AntiBot védelem bekapcsolva! Kérlek várj pár percet mielőtt csatlakozol.'
+not_owner_error: 'Ez nem a te felhasználód. Kérlek válassz másik nevet!'
+invalid_name_case: '%valid a felhasználó neved nem? Akkor ne %invalid névvel próbálj feljönni.'
+two_factor_create: '&2A te titkos kódod a következő: %code. Vagy skenneld be a következő oldalról: %url'
diff --git a/src/main/resources/messages/messages_it.yml b/src/main/resources/messages/messages_it.yml
index e7c77c89..6361a4c9 100644
--- a/src/main/resources/messages/messages_it.yml
+++ b/src/main/resources/messages/messages_it.yml
@@ -1,64 +1,64 @@
-#Lingua Italiana creata da Maxetto e sgdc3.
-unknown_user: 'L''utente non è presente nel database.'
-unsafe_spawn: 'Il tuo punto di disconnessione risulta ostruito o insicuro, sei stato teletrasportato al punto di rigenerazione!'
+# Lingua Italiana creata da Maxetto e sgdc3.
+kick_antibot: 'Il servizio di AntiBot è attualmente attivo! Devi aspettare qualche minuto prima di poter entrare nel server.'
+unknown_user: '&cL''utente non è presente nel database.'
+unsafe_spawn: '&cIl tuo punto di disconnessione risulta ostruito o insicuro, sei stato teletrasportato al punto di rigenerazione!'
not_logged_in: '&cNon hai ancora eseguito l''autenticazione!'
reg_voluntarily: 'Puoi eseguire la registrazione al server con il comando: "/register "'
usage_log: '&cUtilizzo: /login '
wrong_pwd: '&cPassword non corretta!'
-unregistered: '&cSei stato rimosso dal database con successo!'
+unregistered: '&2Sei stato correttamente rimosso dal database!'
reg_disabled: '&cLa registrazione tramite i comandi di gioco è disabilitata.'
-valid_session: '&cAutenticato automaticamente attraverso la precedente sessione!'
-login: '&cAutenticazone effettuata correttamente!'
-vb_nonActiv: 'Il tuo account non è stato ancora verificato, controlla fra le tue email per scoprire come attivarlo!'
+valid_session: '&2Autenticato automaticamente attraverso la precedente sessione!'
+login: '&2Autenticazone effettuata correttamente!'
+vb_nonActiv: '&cIl tuo account non è stato ancora verificato, controlla fra le tue email per scoprire come attivarlo!'
user_regged: '&cHai già effettuato la registrazione, non puoi eseguirla nuovamente.'
usage_reg: '&cUtilizzo: /register '
-error: 'Qualcosa è andato storto, riporta questo errore ad un Admin!'
-max_reg: 'Hai raggiunto il numero massimo di registrazioni per questo indirizzo IP!'
-no_perm: '&cNon hai il permesso di eseguire questa operazione.'
-login_msg: '&cPerfavore, esegui l''autenticazione con il comando: "/login "'
-reg_msg: '&cPerfavore, esegui la registrazione con il comando: "/register "'
-reg_email_msg: '&cPerfavore, esegui la registrazione con il comando: "/register "'
+max_reg: '&cHai raggiunto il numero massimo di registrazioni (%reg_count/%max_acc %reg_names) per questo indirizzo IP!'
+no_perm: '&4Non hai il permesso di eseguire questa operazione.'
+error: '&4Qualcosa è andato storto, riporta questo errore ad un Admin!'
+login_msg: '&cPer favore, esegui l''autenticazione con il comando: "/login "'
+reg_msg: '&3Per favore, esegui la registrazione con il comando: "/register "'
+reg_email_msg: '&3Per favore, esegui la registrazione con il comando: "/register "'
usage_unreg: '&cUtilizzo: /unregister '
-pwd_changed: '&cPassword cambiata con successo!'
+pwd_changed: '&2Password cambiata correttamente!'
user_unknown: '&cL''utente non ha ancora eseguito la registrazione.'
-password_error: 'Le Password non corrispondono!'
-password_error_nick: 'Non puoi usare il tuo nome utente come password, scegline un''altra!'
-password_error_unsafe: 'La password che hai inserito non è sicura, scegline un''altra!'
-invalid_session: 'I tuoi dati di connessione attuali non sono quelli utilizzati in precedenza. Attendi la fine della sessione attuale.'
-reg_only: 'Puoi giocare in questo server solo dopo aver effettuato la registrazione attraverso il sito web! Perfavore, vai su http://esempio.it per procedere!'
-logged_in: '&cHai già eseguito l''autenticazione, non devi eseguirla nuovamente!'
-logout: '&cDisconnessione avvenuta correttamente!'
-same_nick: 'Questo stesso nome utente è già online sul server!'
-registered: '&cRegistrato correttamente!'
-pass_len: 'La password che hai inserito è troppo corta o troppo lunga, scegline un''altra!'
-reload: 'La configurazione e il database sono stati ricaricati con successo!'
-timeout: 'Tempo scaduto per effettuare l''autenticazione'
-usage_changepassword: 'Utilizzo: /changepassword '
-name_len: '&cIl tuo nome utente è troppo corto o troppo lungo!'
-regex: '&cIl tuo nome utente contiene caratteri non consentiti. I caratteri consentiti sono: REG_EX'
-add_email: '&cPer poter recuperare la password in futuro, aggiungi un indirizzo email al tuo account con il comando: "/email add "'
-recovery_email: '&cHai dimenticato la tua password? Puoi recuperarla eseguendo il comando: "/email recovery "'
-usage_captcha: '&cAbbiamo bisogno che tu inserisca un captcha, perfavore scrivi: "/captcha "'
-wrong_captcha: '&cCaptcha sbagliato, perfavore riprova con il comando: "/captcha THE_CAPTCHA"'
-valid_captcha: '&cIl captcha inserito è valido!'
-kick_forvip: '&cUn utente VIP è entrato mentre il server era pieno e ha preso il tuo posto!'
-kick_fullserver: '&cIl server è attualmente pieno, riprova più tardi!'
-usage_email_add: '&fUtilizzo: /email add '
-usage_email_change: '&fUtilizzo: /email change '
-usage_email_recovery: '&fUtilizzo: /email recovery '
-new_email_invalid: 'Il nuovo indirizzo email inserito non è valido!'
-old_email_invalid: 'Il vecchio indirizzo email inserito non è valido!'
-email_invalid: 'L''indirizzo email inserito non è valido'
-email_added: 'Indirizzo email aggiunto correttamente!'
-email_confirm: 'Conferma il tuo indirizzo email!'
-email_changed: 'Indirizzo email cambiato correttamente!'
-email_send: 'Una email di recupero è stata appena inviata al tuo indirizzo email!'
-email_exists: 'Il tuo account ha già un''indirizzo email configurato. Se vuoi, puoi cambiarlo con il seguente comando:'
-country_banned: 'Il tuo paese è bandito da questo server!'
-antibot_auto_enabled: 'Il servizio di AntiBot è stato automaticamente abilitato a seguito delle numerose connessioni!'
-antibot_auto_disabled: "Il servizio di AntiBot è stato automaticamente disabilitato dopo %m Minuti, sperando che l'attacco sia finito!"
-kick_antibot: 'Il servizio di AntiBot è attualmente attivo! Devi aspettare qualche minuto prima di poter entrare nel server.'
+password_error: '&cLe password non corrispondono!'
+password_error_nick: '&cNon puoi usare il tuo nome utente come password, per favore scegline un''altra...'
+password_error_unsafe: '&cLa password che hai inserito non è sicura, per favore scegline un''altra...'
+invalid_session: '&cIl tuo indirizzo IP è cambiato e la tua sessione è stata terminata!'
+reg_only: '&4Puoi giocare in questo server solo dopo aver effettuato la registrazione attraverso il sito web! Per favore, vai su http://esempio.it per procedere!'
+logged_in: '&cHai già eseguito l''autenticazione, non è necessario eseguirla nuovamente!'
+logout: '&2Disconnessione avvenuta correttamente!'
+same_nick: '&4Questo stesso nome utente è già online sul server!'
+registered: '&2Registrato correttamente!'
+pass_len: '&cLa password che hai inserito è troppo corta o troppo lunga, per favore scegline un''altra...'
+reload: '&2La configurazione e il database sono stati ricaricati correttamente!'
+timeout: '&4Tempo scaduto per effettuare l''autenticazione, sei stato espulso dal server, per favore riprova!'
+usage_changepassword: '&cUtilizzo: /changepassword '
+name_len: '&4Il tuo nome utente è troppo corto o troppo lungo!'
+regex: '&4Il tuo nome utente contiene caratteri non consentiti. I caratteri consentiti sono: REG_EX'
+add_email: '&3Per poter recuperare la password in futuro, aggiungi un indirizzo email al tuo account con il comando: "/email add "'
+recovery_email: '&3Hai dimenticato la tua password? Puoi recuperarla eseguendo il comando: "/email recovery "'
+usage_captcha: '&3Per poterti autenticare devi risolvere un captcha, per favore scrivi: "/captcha "'
+wrong_captcha: '&cCaptcha sbagliato, per favore riprova scrivendo: "/captcha THE_CAPTCHA" in chat!'
+valid_captcha: '&2Il captcha inserito è valido!'
+kick_forvip: '&3Un utente VIP è entrato mentre il server era pieno e ha preso il tuo posto!'
+kick_fullserver: '&4Il server è attualmente pieno, riprova più tardi!'
+usage_email_add: '&cUtilizzo: /email add '
+usage_email_change: '&cUtilizzo: /email change '
+usage_email_recovery: '&cUtilizzo: /email recovery '
+new_email_invalid: '&cIl nuovo indirizzo email inserito non è valido, riprova!'
+old_email_invalid: '&cIl vecchio indirizzo email inserito non è valido, riprova!'
+email_invalid: '&cL''indirizzo email inserito non è valido, riprova!'
+email_added: '&2Indirizzo email aggiunto correttamente al tuo account!'
+email_confirm: '&cPer favore, conferma il tuo indirizzo email!'
+email_changed: '&2Indirizzo email cambiato correttamente!'
+email_send: '&2Una email di recupero è stata appena inviata al tuo indirizzo email!'
+email_exists: '&cUna email di recupero è già stata inviata! Se vuoi, puoi annullarla e mandarne un''altra con il seguente comando:'
+country_banned: '&4Il tuo paese è bandito da questo server!'
+antibot_auto_enabled: '&4Il servizio di AntiBot è stato automaticamente abilitato a seguito delle numerose connessioni!'
+antibot_auto_disabled: "&2Il servizio di AntiBot è stato automaticamente disabilitato dopo %m Minuti, sperando che l'attacco sia finito!"
+email_already_used: '&4L''indirizzo email inserito è già in uso'
two_factor_create: '&2Il tuo codice segreto è: &f%code&n&2Puoi anche scannerizzare il codice QR da qui: &f%url'
-# TODO email_already_used: '&4The email address is already being used'
-# TODO invalid_name_case: 'You should join using username %valid, not %invalid.'
-# TODO not_owner_error: 'You are not the owner of this account. Please try another name!'
\ No newline at end of file
+not_owner_error: 'Non sei il proprietario di questo account. Per favore scegli un altro nome!'
+invalid_name_case: 'Dovresti entrare con questo nome utente: "%valid", al posto di: "%invalid".'
diff --git a/src/main/resources/messages/messages_zhcn.yml b/src/main/resources/messages/messages_zhcn.yml
index 3c7fa1a2..fbf89b5e 100644
--- a/src/main/resources/messages/messages_zhcn.yml
+++ b/src/main/resources/messages/messages_zhcn.yml
@@ -1,68 +1,66 @@
-# Translator: uSoc_lifehome (http://lifeho.me) #
-# Translator: WaterXCubic 水方塊 #
+# Translator: Unknown #
+# Last modif: 1459528742 UTC #
# -------------------------------------------- #
-unknown_user: '&8[&6用戶系統&8] &f用戶資料並不存在於資料庫中。'
-unsafe_spawn: '&8[&6用戶系統&8] &f你的登出位置不安全,現在將傳送你到重生點。'
-not_logged_in: '&8[&6用戶系統&8] &c你還沒有登入 !'
-reg_voluntarily: '&8[&6用戶系統&8] &f你可以使用這個的指令來註冊: 《 /register <密碼> <重覆密碼> 》'
-usage_log: '&8[&6用戶系統&8] &c用法: 《 /login <密碼> 》'
-wrong_pwd: '&8[&6用戶系統&8] &c你輸入了錯誤的密碼。'
-unregistered: '&8[&6用戶系統&8] &c你已成功取消會員註冊記錄。'
-reg_disabled: '&8[&6用戶系統&8] &c本伺服器已停止新玩家註冊。'
-valid_session: '&8[&6用戶系統&8] &b嗨 ! 我記得你,歡迎回來~'
-login: '&8[&6用戶系統&8] &c你成功的登入了。'
-password_error_nick: '&f你不可以使用你的名字為密碼!'
-password_error_unsafe: '&f你不可以使用不安全的密碼'
-vb_nonActiv: '&8[&6用戶系統&8] &f你的帳戶還沒有經過電郵驗證 !'
-user_regged: '&8[&6用戶系統&8] &c此用戶名已經註冊過了。'
-usage_reg: '&8[&6用戶系統&8] &c用法: 《 /register <密碼> <重覆密碼> 》'
-max_reg: '&8[&6用戶系統&8] &f你的IP地址已達到註冊數上限。'
-no_perm: '&8[&6用戶系統&8] &b你可以到 CraftingHK 玩家百科中查看說明文件。'
-error: '&8[&6用戶系統&8] &f發生錯誤,請與管理員聯絡。'
-login_msg: '&8[&6用戶系統&8] &c請使用這個指令來登入: 《 /login <密碼> 》'
-reg_msg: '&8[&6用戶系統&8] &c請使用這個的指令來註冊: 《 /register <密碼> <重覆密碼> 》'
-reg_email_msg: '&8[&6用戶系統&8] &c請使用這個的指令來註冊: 《 /register <電郵> <重覆電郵> 》'
-usage_unreg: '&8[&6用戶系統&8] &c用法: 《 /unregister <密碼> 》'
-pwd_changed: '&8[&6用戶系統&8] &c你成功的更換了你的密碼 !'
-user_unknown: '&8[&6用戶系統&8] &c此用戶名沒有已登記資料。'
-password_error: '&8[&6用戶系統&8] &f密碼不符合。'
-invalid_session: '&8[&6用戶系統&8] &f登入階段資料已損壞,請等待登入階段結束。'
-reg_only: '&8[&6用戶系統&8] &f限已註冊會員,請先到 https://www.example.com/ 註冊。'
-logged_in: '&8[&6用戶系統&8] &c你已經登入過了。'
-logout: '&8[&6用戶系統&8] &b你成功的登出了。'
-same_nick: '&8[&6用戶系統&8] &f同名玩家已在遊玩。'
-registered: '&8[&6用戶系統&8] &b你成功的註冊了。'
-pass_len: '&8[&6用戶系統&8] &f你的密碼並不符合規定長度。'
-reload: '&8[&6用戶系統&8] &b登入系統設定及資料庫重新載入完畢。'
-timeout: '&8[&6用戶系統&8] &f登入逾時。'
-usage_changepassword: '&8[&6用戶系統&8] &f用法: 《 /changepassword <舊密碼> <新密碼> 》'
-name_len: '&8[&6用戶系統&8] &c你的用戶名不符合規定長度。'
-regex: '&8[&6用戶系統&8] &c你的用戶名含有不容許之字符。以下為准許之字母: REG_EX'
-add_email: '&8[&6用戶系統&8] &b請為你的帳戶立即添加電郵地址: 《 /email add <電郵地址> <重覆電郵地址> 》'
-bad_database_email: '&8[&6用戶系統&8] 此指令只適用於使用MySQL或SQLite之伺服器。'
-recovery_email: '&8[&6用戶系統&8] &c忘記密碼 ? 請使用這個的指令來更新密碼: 《 /email recovery <電郵地址> 》'
-usage_captcha: '&8[&6用戶系統&8] &c用法: 《 /captcha 》'
-# TODO wrong_captcha: Missing tag THE_CAPTCHA
-wrong_captcha: '&8[&6用戶系統&8] &c你輸入了錯誤的驗證碼,請使用 《 /captcha <驗證碼> 》 再次輸入。'
-valid_captcha: '&8[&6用戶系統&8] &c你所輸入的驗證碼是無效的 !'
-kick_forvip: '&c因為有VIP玩家登入了伺服器。'
-kick_fullserver: '&c抱歉! 因為伺服器滿人了,所以你目前未能登入伺服器。'
-usage_email_add: '&8[&6用戶系統&8] &f用法: 《 /email add <電郵> <重覆電郵> 》'
-usage_email_change: '&8[&6用戶系統&8] &f用法: 《 /email change <舊電郵> <新電郵> 》'
-usage_email_recovery: '&8[&6用戶系統&8] &f用法: 《 /email recovery <電郵> 》'
-new_email_invalid: '&8[&6用戶系統&8] 你所填寫的新電郵地址並不正確。'
-old_email_invalid: '&8[&6用戶系統&8] 你所填寫的舊電郵地址並不正確。'
-email_invalid: '&8[&6用戶系統&8] 你所填寫的電郵地址並不正確。'
-email_added: '&8[&6用戶系統&8] 已加入你的電郵地址記錄。'
-email_confirm: '&8[&6用戶系統&8] 請重覆輸入你的電郵地址。'
-email_changed: '&8[&6用戶系統&8] 你的電郵地址記錄已更改。'
-email_send: '&8[&6用戶系統&8] 忘記密碼信件已寄出,請查收。'
-country_banned: '&8[&6用戶系統&8] 本伺服器已停止對你的國家提供遊戲服務。'
-antibot_auto_enabled: '&8[&6用戶系統&8] 防止機械人程序已因應現時大量不尋常的連線而啟用。'
-antibot_auto_disabled: '&8[&6用戶系統&8] 防止機械人程序檢查到不正常連接數已減少,並於 %m 分鐘後停止運作。'
-# TODO email_already_used: '&4The email address is already being used'
-# TODO kick_antibot: 'AntiBot protection mode is enabled! You have to wait some minutes before joining the server.'
-# TODO email_exists: '&cA recovery email was already sent! You can discard it and send a new one using the command below:'
-# TODO invalid_name_case: 'You should join using username %valid, not %invalid.'
-# TODO two_factor_create: '&2Your secret code is %code. You can scan it from here %url'
-# TODO not_owner_error: 'You are not the owner of this account. Please try another name!'
\ No newline at end of file
+kick_antibot: '&8[&6玩家系统&8] &f防机器人程序已启用 !请稍等几分钟後才再次进入服务器'
+unknown_user: '&8[&6玩家系统&8] &f&f数据库里找不到此用户'
+unsafe_spawn: '&8[&6玩家系统&8] &f你退出服务器时的位置不安全,正在传送你到此世界的出生点'
+not_logged_in: '&8[&6玩家系统&8] &c你还未登录!'
+reg_voluntarily: '&8[&6玩家系统&8] &f你可以在服务器里使用这个指令以注册:“/register <密码> <再输入一次以确定密码>”'
+usage_log: '&8[&6玩家系统&8] &c正确用法:“/login <密码>”'
+wrong_pwd: '&8[&6玩家系统&8] &c错误的密码'
+unregistered: '&8[&6玩家系统&8] &c成功删除此用户!'
+reg_disabled: '&8[&6玩家系统&8] &c目前服务器暂时禁止注册,请到服务器论坛以得到更多资讯'
+valid_session: '&8[&6玩家系统&8] &c欢迎回来,已帮你自动登录到此服务器'
+login: '&8[&6玩家系统&8] &c已成功登录!'
+vb_nonActiv: '&8[&6玩家系统&8] &f你的帐号还未激活,请查看你的邮箱!'
+user_regged: '&8[&6玩家系统&8] &c此用户已经在此服务器注册过'
+usage_reg: '&8[&6玩家系统&8] &c正确用法:“/register <密码> <再输入一次以确定密码>”'
+max_reg: '&8[&6玩家系统&8] &f你不允许再为你的IP在服务器注册更多用户了!'
+no_perm: '&8[&6玩家系统&8] &c没有权限'
+error: '&8[&6玩家系统&8] &f发现错误,请联系管理员'
+login_msg: '&8[&6玩家系统&8] &c请输入“/login <密码>”以登录'
+reg_msg: '&8[&6玩家系统&8] &c请输入“/register <密码> <再输入一次以确定密码>”以注册'
+reg_email_msg: '&8[&6玩家系统&8] &c请输入 "/register <邮箱> <确认电子邮件>"'
+usage_unreg: '&8[&6玩家系统&8] &c正确用法:“/unregister <密码>”'
+pwd_changed: '&8[&6玩家系统&8] &c密码已成功修改!'
+user_unknown: '&8[&6玩家系统&8] &c此用户名还未注册过'
+password_error: '&8[&6玩家系统&8] &f密码不相同'
+password_error_nick: '&8[&6玩家系统&8] &f你不能使用你的名字作为密码。 '
+password_error_unsafe: '&8[&6玩家系统&8] &f你不能使用安全性过低的码。 '
+invalid_session: '&8[&6玩家系统&8] &f登陆数据异常,请等待登陆结束'
+reg_only: '&8[&6玩家系统&8] &f只允许注册过的玩家进服!请到 https://example.cn 注册'
+logged_in: '&8[&6玩家系统&8] &c你已经登陆过了!'
+logout: '&8[&6玩家系统&8] &c已成功登出!'
+same_nick: '&8[&6玩家系统&8] &f同样的用户名现在在线且已经登录了!'
+registered: '&8[&6玩家系统&8] &c已成功注册!'
+pass_len: '&8[&6玩家系统&8] &你的密码没有达到要求!'
+reload: '&8[&6玩家系统&8] &f配置以及数据已经重新加载完毕'
+timeout: '&8[&6玩家系统&8] &f给你登录的时间已经过了'
+usage_changepassword: '&8[&6玩家系统&8] &f正确用法:“/changepassword 旧密码 新密码”'
+name_len: '&8[&6玩家系统&8] &c你的用户名太短或者太长了'
+regex: '&8[&6玩家系统&8] &c你的用户名包含非法字母,用户名里允许的字母: REG_EX'
+add_email: '&8[&6玩家系统&8] &c请输入“/email add <你的邮箱> <再输入一次以确认>”以把你的邮箱添加到此帐号'
+recovery_email: '&8[&6玩家系统&8] &c忘了你的密码?请输入:“/email recovery <你的邮箱>”'
+usage_captcha: '&8[&6玩家系统&8] &c正确用法:/captcha '
+wrong_captcha: '&8[&6玩家系统&8] &c错误的验证码,请输入:“/captcha THE_CAPTCHA”'
+valid_captcha: '&8[&6玩家系统&8] &c你的验证码是有效的!'
+kick_forvip: '&8[&6玩家系统&8] &cA VIP玩家加入了已满的服务器!'
+kick_fullserver: '&8[&6玩家系统&8] &c抱歉,服务器已满!'
+usage_email_add: '&8[&6玩家系统&8] &f用法: /email add <邮箱> <确认电子邮件> '
+usage_email_change: '&8[&6玩家系统&8] &f用法: /email change <旧邮箱> <新邮箱> '
+usage_email_recovery: '&8[&6玩家系统&8] &f用法: /email recovery <邮箱>'
+new_email_invalid: '&8[&6玩家系统&8] &f新邮箱无效!'
+old_email_invalid: '&8[&6玩家系统&8] &f旧邮箱无效!'
+email_invalid: '&8[&6玩家系统&8] &f无效的邮箱'
+email_added: '&8[&6玩家系统&8] &f邮箱已添加 !'
+email_confirm: '&8[&6玩家系统&8] &f确认你的邮箱 !'
+email_changed: '&8[&6玩家系统&8] &f邮箱已改变 !'
+email_send: '&8[&6玩家系统&8] &f恢复邮件已发送 !'
+country_banned: '这个服务器禁止该国家登陆'
+antibot_auto_enabled: '&8[&6玩家系统&8] &f防机器人程序由于大量异常连接而启用'
+antibot_auto_disabled: '&8[&6玩家系统&8] &f防机器人程序由于异常连接减少而在 %m 分钟后停止'
+email_already_used: '&8[&6玩家系统&8] &4邮箱已被使用'
+email_exists: '&8[&6玩家系统&8] &c恢复邮件已发送 ! 你可以丢弃它然後使用以下的指令来发送新的邮件:'
+two_factor_create: '&8[&6玩家系统&8] &2你的代码是 %code,你可以使用 %url 来扫描'
+not_owner_error: '&8[&6玩家系统&8] &4警告! &c你并不是此帐户持有人,请立即登出。 '
+invalid_name_case: '&8[&6玩家系统&8] &c你应该使用「%valid」而并非「%invalid」登入游戏。 '
\ No newline at end of file
diff --git a/src/main/resources/messages/messages_zhhk.yml b/src/main/resources/messages/messages_zhhk.yml
index 2eacb1f6..3dc579c7 100644
--- a/src/main/resources/messages/messages_zhhk.yml
+++ b/src/main/resources/messages/messages_zhhk.yml
@@ -1,67 +1,66 @@
-#----------------------------------------#
-#translated by i998979
-#----------------------------------------#
-unknown_user: '&f用戶資料並不存在於資料庫中。'
-unsafe_spawn: '&f你的登出的位置不安全,將傳送你至重生點。'
-not_logged_in: '&c你並未登入!'
-reg_voluntarily: '&f請使用: /register <密碼> <重覆密碼> 來註冊。'
-usage_log: '&c用法: /login <密碼>'
-wrong_pwd: '&c密碼錯誤。'
-unregistered: '&c成功取消該名用戶的註冊記錄。'
-reg_disabled: '&c新玩家註冊已停用。'
-valid_session: '&cIP記憶,自動登入。'
-login: '&c登入成功。'
-vb_nonActiv: '&f你的帳戶並未啟用,請檢查你的電郵!'
-user_regged: '&c此用戶名已有註冊記錄。'
-usage_reg: '&c用法: /register <密碼> <重覆密碼>'
-max_reg: '&f你的IP地址已達到註冊帳號上限。'
-no_perm: '&c你沒有足夠的權限。'
-error: '&f發生錯誤,請與管理員聯絡。'
-login_msg: '&c請使用 /login <密碼> 來登入。'
-reg_msg: '&c請使用 /register <密碼> <重覆密碼> 來註冊。'
-reg_email_msg: '&c請使用 /register <電郵> <重覆電郵> 來註冊。'
-usage_unreg: '&c用法: /unregister <密碼>'
-pwd_changed: '&c密碼更改成功!'
-user_unknown: '&c該用戶並未註冊。'
-password_error: '&f密碼不符合。'
-password_error_nick: '&f你不能使用你的名字作為密碼。'
-password_error_unsafe: '&f你不能使用安全性過低的碼。'
-invalid_session: '&f登入階段資料不相同,請等待登入階段結束。'
-reg_only: '&f只限已註冊用戶,請先到 https://www.example.com 註冊。'
-logged_in: '&c你已經登入過了。'
-logout: '&b登出成功。'
-same_nick: '&f同名玩家已在遊玩。'
-registered: '&b註冊成功。'
-pass_len: '&f你的密碼太短或太長。'
-reload: '&b系統設定及資料庫已重新載入。'
-timeout: '&f登入逾時,請重新登入。'
-usage_changepassword: '&f用法: /changepassword <舊密碼> <新密碼>'
-name_len: '&c你的用戶名太短或太長。'
-regex: '&c你的用戶名含有不容許的字符。以下為准許之字母: REG_EX。'
-add_email: '&b請為你的帳戶添加電郵地址: /email add <電郵地址> <重覆電郵地址>。'
-bad_database_email: '/email 只適用於使用MySQL或SQLite之伺服器,請聯絡管理員。'
-recovery_email: '&c忘記密碼?請使用 /email recovery <電郵地址> 來更新密碼。'
-usage_captcha: '&c用法: /captcha '
-wrong_captcha: '&c驗證碼錯誤,請再次輸入 /captcha THE_CAPTCHA。'
-valid_captcha: '&c驗證碼無效!'
-kick_forvip: '&cVIP玩家登入了滿人的伺服器。'
-kick_fullserver: '&c因為伺服器滿人,請稍候再試。'
-usage_email_add: '&f用法: /email add <電郵> <重覆電郵>'
-usage_email_change: '&f用法: /email change <舊電郵> <新電郵>'
-usage_email_recovery: '&f用法: /email recovery <電郵>'
-new_email_invalid: '新電郵地址不正確。'
-old_email_invalid: '舊電郵地址不正確。'
-email_invalid: '電郵地址不正確。'
-email_added: '電郵地址已加入。'
-email_confirm: '請確認電郵地址。'
-email_changed: '電郵地址已更改。'
-email_send: '已寄出忘記密碼信件。'
-country_banned: '你的國家已被本伺服器封禁。'
-antibot_auto_enabled: '防止機械人程序因大量不尋常連線而啟用。'
-antibot_auto_disabled: '防止機械人程序將於 %m 分鐘後停止運作。'
-email_already_used: '&4邮箱已被使用'
-kick_antibot: '[AuthMe] 防机器人程序已启用 !请稍等几分钟後才再次进入服务器'
-email_exists: '&c恢复邮件已发送 ! 你可以丢弃它然後使用以下的指令来发送新的邮件:'
-two_factor_create: '&2你的代码是 %code,你可以使用 %url 来扫描'
-# TODO invalid_name_case: 'You should join using username %valid, not %invalid.'
-# TODO not_owner_error: 'You are not the owner of this account. Please try another name!'
\ No newline at end of file
+# Translator: lifehome #
+# Last modif: 1459528742 UTC #
+# -------------------------------------------- #
+kick_antibot: '&8[&6用戶系統&8] &c伺服器錯誤!請稍候再嘗試登入吧。 &7(err: kick_due2_bot)'
+unknown_user: '&8[&6用戶系統&8] &f用戶資料並不存在。'
+unsafe_spawn: '&8[&6用戶系統&8] &f你的登出位置不安全,現在將傳送你到重生點。'
+not_logged_in: '&8[&6用戶系統&8] &c你還沒有登入 !'
+reg_voluntarily: '&8[&6用戶系統&8] &f你可以使用這個指令來註冊: 《 /register <密碼> <重覆密碼> 》'
+usage_log: '&8[&6用戶系統&8] &f用法: 《 /login <密碼> 》'
+wrong_pwd: '&8[&6用戶系統&8] &c你輸入了錯誤的密碼。'
+unregistered: '&8[&6用戶系統&8] &c你已成功刪除會員註冊記錄。'
+reg_disabled: '&8[&6用戶系統&8] &c本伺服器已停止新玩家註冊。'
+valid_session: '&8[&6用戶系統&8] &b嗨 ! 歡迎回來喔~'
+login: '&8[&6用戶系統&8] &c你成功登入了。'
+vb_nonActiv: '&8[&6用戶系統&8] &f你的帳戶還沒有經過電郵驗證 !'
+user_regged: '&8[&6用戶系統&8] &c此用戶名已經註冊過了。'
+usage_reg: '&8[&6用戶系統&8] &f用法: 《 /register <密碼> <重覆密碼> 》'
+max_reg: '&8[&6用戶系統&8] &f你的IP地址已達到註冊數上限。'
+no_perm: '&8[&6用戶系統&8] &b嗯~你想幹甚麼?'
+error: '&8[&6用戶系統&8] &f發生錯誤,請與管理員聯絡。'
+login_msg: '&8[&6用戶系統&8] &c請使用這個指令來登入: 《 /login <密碼> 》'
+reg_msg: '&8[&6用戶系統&8] &c請使用這個指令來註冊: 《 /register <密碼> <重覆密碼> 》'
+reg_email_msg: '&8[&6用戶系統&8] &c請使用這個指令來註冊: 《 /register <電郵> <重覆電郵> 》'
+usage_unreg: '&8[&6用戶系統&8] &f用法: 《 /unregister <密碼> 》'
+pwd_changed: '&8[&6用戶系統&8] &c你成功更換了你的密碼 !'
+user_unknown: '&8[&6用戶系統&8] &c此用戶名沒有已登記資料。'
+password_error: '&8[&6用戶系統&8] &f密碼不符合。'
+password_error_nick: '&8[&6用戶系統&8] &c這個密碼太不安全了!'
+password_error_unsafe: '&8[&6用戶系統&8] &c這個密碼太不安全了!'
+invalid_session: '&8[&6用戶系統&8] &f登入階段資料已損壞,請等待登入階段結束。'
+reg_only: '&8[&6用戶系統&8] &f限已註冊會員,請先到本服網站進行註冊。'
+logged_in: '&8[&6用戶系統&8] &c你已經登入過了。'
+logout: '&8[&6用戶系統&8] &b你成功登出了。'
+same_nick: '&8[&6用戶系統&8] &f同名玩家已在遊玩。'
+registered: '&8[&6用戶系統&8] &b你成功註冊了。'
+pass_len: '&8[&6用戶系統&8] &f你的密碼並不符合規定長度。'
+reload: '&8[&6用戶系統&8] &b登入系統設定及資料庫重新載入完畢。'
+timeout: '&8[&6用戶系統&8] &f登入逾時。'
+usage_changepassword: '&8[&6用戶系統&8] &f用法: 《 /changepassword <舊密碼> <新密碼> 》'
+name_len: '&8[&6用戶系統&8] &c你的用戶名不符合規定長度。'
+regex: '&8[&6用戶系統&8] &c用戶名稱錯誤! 登入系統只接受以下字符: REG_EX'
+add_email: '&8[&6用戶系統&8] &b請為你的帳戶立即添加電郵地址: 《 /email add <電郵地址> <重覆電郵地址> 》'
+recovery_email: '&8[&6用戶系統&8] &b忘記密碼?請使用 /email recovery <電郵地址> 來更新密碼。'
+usage_captcha: '&8[&6用戶系統&8] &f用法: 《 /captcha 》'
+wrong_captcha: '&8[&6用戶系統&8] &c你所輸入的驗證碼無效,請使用 《 /captcha THE_CAPTCHA 》 再次輸入。'
+valid_captcha: '&8[&6用戶系統&8] &c你所輸入的驗證碼無效 !'
+kick_forvip: '&c喔!因為有VIP玩家登入了伺服器。'
+kick_fullserver: '&c抱歉! 因為伺服器滿人了,所以你目前未能登入伺服器。'
+usage_email_add: '&8[&6用戶系統&8] &f用法: 《 /email add <電郵> <重覆電郵> 》'
+usage_email_change: '&8[&6用戶系統&8] &f用法: 《 /email change <舊電郵> <新電郵> 》'
+usage_email_recovery: '&8[&6用戶系統&8] &f用法: 《 /email recovery <電郵> 》'
+new_email_invalid: '&8[&6用戶系統&8] &c你所填寫的新電郵地址並不正確。'
+old_email_invalid: '&8[&6用戶系統&8] &c你所填寫的舊電郵地址並不正確。'
+email_invalid: '&8[&6用戶系統&8] &c你所填寫的電郵地址並不正確。'
+email_added: '&8[&6用戶系統&8] &a已新增你的電郵地址。'
+email_confirm: '&8[&6用戶系統&8] &5請重覆輸入你的電郵地址。'
+email_changed: '&8[&6用戶系統&8] &a你的電郵地址已更改。'
+email_send: '&8[&6用戶系統&8] &a忘記密碼信件已寄出,請查收。'
+country_banned: '&8[&6用戶系統&8] &4本伺服器已停止對你的國家提供遊戲服務。'
+antibot_auto_enabled: '&8[&6用戶系統&8] &3防止機械人程序已因應現時大量不尋常連線而啟用。'
+antibot_auto_disabled: '&8[&6用戶系統&8] &3不正常連接數已減少,防止機械人程序將於 %m 分鐘後停止。'
+email_already_used: '&8[&6用戶系統&8] &4這個電郵地址已被使用。'
+email_exists: '&8[&6用戶系統&8] &c訊息已發送!如果你收不到該封電郵,可以使用以下指令進行重寄:'
+two_factor_create: '&8[&6用戶系統 - 兩步驗證碼&8] &b你的登入金鑰為&9「%c%code&9」&b,掃描連結為:&c %url'
+not_owner_error: '&8[&6用戶系統&8] &4警告!&c你並不是此帳戶持有人,請立即登出。'
+invalid_name_case: '&8[&6用戶系統&8] &4警告!&c你應該使用「%valid」而並非「%invalid」登入遊戲。'
\ No newline at end of file
diff --git a/src/main/resources/messages/messages_zhtw.yml b/src/main/resources/messages/messages_zhtw.yml
index d31431f4..9b0d536c 100644
--- a/src/main/resources/messages/messages_zhtw.yml
+++ b/src/main/resources/messages/messages_zhtw.yml
@@ -1,6 +1,7 @@
-# Translator: MineWolf50
-# Last Time Edit : 2015 / 7 / 14 , A.M.10:14
-# = = = = = = = = = = = = = = = = = = = = = = = #
+# Translator: MineWolf50, lifehome #
+# Last modif: 1459528742 UTC #
+# -------------------------------------------- #
+kick_antibot: '&b【AuthMe】&cAntiBotMod 正在啟用中,請稍後再嘗試登入吧!'
unknown_user: "&b【AuthMe】&6沒有在資料庫內找到該玩家。"
unsafe_spawn: '&b【AuthMe】&6你登出的地點不安全,已傳送你到安全的地點。'
not_logged_in: '&b【AuthMe】&6你還沒有登入!'
@@ -9,8 +10,6 @@ usage_log: '&b【AuthMe】&6用法: &c"/login <密碼>"'
wrong_pwd: '&b【AuthMe】&6密碼錯誤!'
unregistered: '&b【AuthMe】&6你已經成功取消註冊。'
reg_disabled: '&b【AuthMe】&6已關閉註冊功能'
-password_error_nick: '&b【AuthMe】&6你不可以用你的 ID ( 名稱 ) 來當作密碼 !'
-password_error_unsafe: '&b【AuthMe】&6你不可以使用這個不安全的密碼'
valid_session: '&b【AuthMe】&6你已經成功登入!'
login: '&b【AuthMe】&6密碼正確,你已成功登入!'
vb_nonActiv: '&b【AuthMe】&6你的帳號還沒有經過驗證! 檢查看看你的電子信箱 (Email) 吧!'
@@ -26,8 +25,10 @@ usage_unreg: '&b【AuthMe】&6用法: &c"/unregister <密碼>"'
pwd_changed: '&b【AuthMe】&6密碼變更成功!'
user_unknown: '&b【AuthMe】&6這個帳號還沒有註冊過'
password_error: '&b【AuthMe】&6兩次輸入的密碼不一致!'
+password_error_nick: '&b【AuthMe】&6你不可以用你的 ID ( 名稱 ) 來當作密碼 !'
+password_error_unsafe: '&b【AuthMe】&6你不可以使用這個不安全的密碼'
invalid_session: '&b【AuthMe】&6憑證日期不相符!'
-reg_only: '&b【AuthMe】&6請到下列網站 :「 http://example.com 」 進行註冊'
+reg_only: '&b【AuthMe】&6請到下列網站 :「 https://example.tw 」 進行註冊'
logged_in: '&b【AuthMe】&6你已經登入了!'
logout: '&b【AuthMe】&6你已成功登出'
same_nick: '&b【AuthMe】&6有同樣帳號的玩家在線上!'
@@ -37,13 +38,11 @@ reload: '&b【AuthMe】&6已重新讀取設定檔及資料庫'
timeout: '&b【AuthMe】&6超過登入時間,請稍後再試一次'
usage_changepassword: '&b【AuthMe】&6用法: &c"/changepassword <舊密碼> <新密碼>"'
name_len: '&b【AuthMe】&6你的暱稱 太長 / 太短 了!'
-# TODO regex: Missing tag REG_EX
-regex: '&b【AuthMe】&6暱稱裡包含不能使用的字符'
+regex: '&b【AuthMe】&6暱稱裡能使用的字符為: REG_EX'
add_email: '&b【AuthMe】&6請使用 &c"/email add <你的Email> <再次輸入你的Email>" &6來添加 Email'
recovery_email: '&b【AuthMe】&6忘記密碼了嗎? 使用 &c"/email recovery <你的Email>"'
usage_captcha: '&b【AuthMe】&6請用 &c"/captcha " &6來輸入你的驗證碼'
-# TODO wrong_captcha: Missing tag THE_CAPTCHA
-wrong_captcha: '&b【AuthMe】&6錯誤的驗證碼'
+wrong_captcha: '&b【AuthMe】&6錯誤的驗證碼,請使用 《 /captcha THE_CAPTCHA 》 再試一次吧。'
valid_captcha: '&b【AuthMe】&6驗證碼無效!'
kick_forvip: '&b【AuthMe】&6你已經被請出。&c原因 : 有 VIP 玩家登入伺服器'
kick_fullserver: '&b【AuthMe】&6伺服器已經滿了,請等等再試一次'
@@ -57,12 +56,11 @@ email_added: '&b【AuthMe】&6已添加Email!'
email_confirm: '&b【AuthMe】&6請驗證你的Email!'
email_changed: '&b【AuthMe】&6Email已變更!'
email_send: '&b【AuthMe】&6已經送出重設密碼要求至你的Email , 請查收。'
-email_exists: '&b【AuthMe】&6這個帳戶已經有設定電子郵件了'
country_banned: '&b【AuthMe】&6你所在的地區無法進入此伺服器'
antibot_auto_enabled: '&b【AuthMe】&6AntiBotMod已自動啟用!'
antibot_auto_disabled: '&b【AuthMe】&6AntiBotMod將會於 &c%m &6分鐘後自動關閉'
-# TODO email_already_used: '&4The email address is already being used'
-# TODO kick_antibot: 'AntiBot protection mode is enabled! You have to wait some minutes before joining the server.'
-# TODO invalid_name_case: 'You should join using username %valid, not %invalid.'
-# TODO two_factor_create: '&2Your secret code is %code. You can scan it from here %url'
-# TODO not_owner_error: 'You are not the owner of this account. Please try another name!'
\ No newline at end of file
+email_already_used: '&b【AuthMe】&4這個電郵地址已被使用。'
+email_exists: '&b【AuthMe】&6這個帳戶已經有設定電子郵件了'
+two_factor_create: '&b【AuthMe - 兩步驗證碼】&b你的登入金鑰為&9「%c%code&9」&b,掃描連結為:&c %url'
+not_owner_error: '&b【AuthMe】&4警告!&c你並不是此帳戶持有人,請立即登出。'
+invalid_name_case: '&b【AuthMe】&4警告!&c你應該使用「%valid」而並非「%invalid」登入遊戲。'
\ No newline at end of file
diff --git a/src/test/java/fr/xephi/authme/AntiBotTest.java b/src/test/java/fr/xephi/authme/AntiBotTest.java
index 4dace294..9950963a 100644
--- a/src/test/java/fr/xephi/authme/AntiBotTest.java
+++ b/src/test/java/fr/xephi/authme/AntiBotTest.java
@@ -167,6 +167,7 @@ public class AntiBotTest {
antiBot.checkAntiBot(player);
// then
+ @SuppressWarnings("unchecked")
List playerList = (List) ReflectionTestUtils
.getFieldValue(AntiBot.class, antiBot, "antibotPlayers");
assertThat(playerList, hasSize(1));
@@ -196,6 +197,7 @@ public class AntiBotTest {
antiBot.checkAntiBot(player);
// then
+ @SuppressWarnings("rawtypes")
List> playerList = (List) ReflectionTestUtils.getFieldValue(AntiBot.class, antiBot, "antibotPlayers");
assertThat(playerList, empty());
verify(bukkitService, never()).scheduleSyncDelayedTask(any(Runnable.class), anyLong());
diff --git a/src/test/java/fr/xephi/authme/ConsoleLoggerTestInitializer.java b/src/test/java/fr/xephi/authme/ConsoleLoggerTestInitializer.java
deleted file mode 100644
index cfa871e3..00000000
--- a/src/test/java/fr/xephi/authme/ConsoleLoggerTestInitializer.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package fr.xephi.authme;
-
-import org.mockito.Mockito;
-
-import java.util.logging.Logger;
-
-/**
- * Test initializer for {@link ConsoleLogger}.
- */
-public class ConsoleLoggerTestInitializer {
-
- private ConsoleLoggerTestInitializer() {
- }
-
- public static Logger setupLogger() {
- Logger logger = Mockito.mock(Logger.class);
- ConsoleLogger.setLogger(logger);
- return logger;
- }
-}
diff --git a/src/test/java/fr/xephi/authme/TestHelper.java b/src/test/java/fr/xephi/authme/TestHelper.java
index 5f1db10d..463b3870 100644
--- a/src/test/java/fr/xephi/authme/TestHelper.java
+++ b/src/test/java/fr/xephi/authme/TestHelper.java
@@ -3,11 +3,16 @@ package fr.xephi.authme;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.util.BukkitService;
import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.logging.Logger;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Mockito.verify;
@@ -68,20 +73,6 @@ public final class TestHelper {
runnable.run();
}
- /**
- * Execute a {@link Runnable} passed to a mock's {@link BukkitService#scheduleSyncDelayedTask(Runnable)} method.
- * Note that calling this method expects that there be a runnable sent to the method and will fail
- * otherwise.
- *
- * @param service The mock service
- */
- public static void runSyncDelayedTask(BukkitService service) {
- ArgumentCaptor captor = ArgumentCaptor.forClass(Runnable.class);
- verify(service).scheduleSyncDelayedTask(captor.capture());
- Runnable runnable = captor.getValue();
- runnable.run();
- }
-
/**
* Execute a {@link Runnable} passed to a mock's {@link BukkitService#scheduleSyncDelayedTask(Runnable, long)}
* method. Note that calling this method expects that there be a runnable sent to the method and will fail
@@ -96,4 +87,42 @@ public final class TestHelper {
runnable.run();
}
+ /**
+ * Assign the necessary fields on ConsoleLogger with mocks.
+ *
+ * @return The logger mock used
+ */
+ public static Logger setupLogger() {
+ Logger logger = Mockito.mock(Logger.class);
+ ConsoleLogger.setLogger(logger);
+ return logger;
+ }
+
+ /**
+ * Check that a class only has a hidden, zero-argument constructor, preventing the
+ * instantiation of such classes (utility classes). Invokes the hidden constructor
+ * as to register the code coverage.
+ *
+ * @param clazz The class to validate
+ */
+ public static void validateHasOnlyPrivateEmptyConstructor(Class> clazz) {
+ Constructor>[] constructors = clazz.getDeclaredConstructors();
+ if (constructors.length > 1) {
+ throw new IllegalStateException("Class " + clazz.getSimpleName() + " has more than one constructor");
+ } else if (constructors[0].getParameterTypes().length != 0) {
+ throw new IllegalStateException("Constructor of " + clazz + " does not have empty parameter list");
+ } else if (!Modifier.isPrivate(constructors[0].getModifiers())) {
+ throw new IllegalStateException("Constructor of " + clazz + " is not private");
+ }
+
+ // Ugly hack to get coverage on the private constructors
+ // http://stackoverflow.com/questions/14077842/how-to-test-a-private-constructor-in-java-application
+ try {
+ constructors[0].setAccessible(true);
+ constructors[0].newInstance();
+ } catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
+ throw new UnsupportedOperationException(e);
+ }
+ }
+
}
diff --git a/src/test/java/fr/xephi/authme/cache/IpAddressManagerTest.java b/src/test/java/fr/xephi/authme/cache/IpAddressManagerTest.java
deleted file mode 100644
index 50c73d30..00000000
--- a/src/test/java/fr/xephi/authme/cache/IpAddressManagerTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package fr.xephi.authme.cache;
-
-import fr.xephi.authme.settings.NewSetting;
-import fr.xephi.authme.settings.properties.HooksSettings;
-import org.bukkit.entity.Player;
-import org.junit.Test;
-
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-
-import static org.hamcrest.Matchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.Mockito.mock;
-
-/**
- * Test for {@link IpAddressManager}.
- */
-public class IpAddressManagerTest {
-
- @Test
- public void shouldRetrieveFromCache() {
- // given
- IpAddressManager ipAddressManager = new IpAddressManager(mockSettings(true));
- ipAddressManager.addCache("Test", "my test IP");
-
- // when
- String result = ipAddressManager.getPlayerIp(mockPlayer("test", "123.123.123.123"));
-
- // then
- assertThat(result, equalTo("my test IP"));
- }
-
- @Test
- public void shouldReturnPlainIp() {
- // given
- IpAddressManager ipAddressManager = new IpAddressManager(mockSettings(false));
-
- // when
- String result = ipAddressManager.getPlayerIp(mockPlayer("bobby", "8.8.8.8"));
-
- // then
- assertThat(result, equalTo("8.8.8.8"));
- }
-
-
-
- private static NewSetting mockSettings(boolean useVeryGames) {
- NewSetting settings = mock(NewSetting.class);
- given(settings.getProperty(HooksSettings.ENABLE_VERYGAMES_IP_CHECK)).willReturn(useVeryGames);
- return settings;
- }
-
- private static Player mockPlayer(String name, String ip) {
- Player player = mock(Player.class);
- given(player.getName()).willReturn(name);
- InetAddress inetAddress = mock(InetAddress.class);
- given(inetAddress.getHostAddress()).willReturn(ip);
- InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, 8093);
- given(player.getAddress()).willReturn(inetSocketAddress);
- return player;
- }
-
-}
diff --git a/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java b/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java
index 345082bc..e5e6b749 100644
--- a/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java
+++ b/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java
@@ -17,13 +17,14 @@ import static fr.xephi.authme.command.FoundResultStatus.NO_PERMISSION;
import static fr.xephi.authme.command.FoundResultStatus.SUCCESS;
import static fr.xephi.authme.command.FoundResultStatus.UNKNOWN_LABEL;
import static java.util.Arrays.asList;
-import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyListOf;
import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
@@ -95,11 +96,8 @@ public class CommandHandlerTest {
// then
verify(serviceMock).mapPartsToCommand(eq(sender), captor.capture());
assertThat(captor.getValue(), contains("unreg", "testPlayer"));
-
verify(command, never()).getExecutableCommand();
- ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
- verify(sender).sendMessage(captor.capture());
- assertThat(captor.getValue(), containsString("don't have permission"));
+ verify(sender).sendMessage(argThat(containsString("don't have permission")));
}
@Test
@@ -170,11 +168,8 @@ public class CommandHandlerTest {
// then
verify(serviceMock).mapPartsToCommand(eq(sender), captor.capture());
assertThat(captor.getValue(), contains("unreg", "testPlayer"));
-
verify(command, never()).getExecutableCommand();
- ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
- verify(sender).sendMessage(captor.capture());
- assertThat(captor.getValue(), containsString("Failed to parse"));
+ verify(sender).sendMessage(argThat(containsString("Failed to parse")));
}
@Test
diff --git a/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java b/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java
index 7e62023f..6e5418d5 100644
--- a/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java
+++ b/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java
@@ -3,7 +3,6 @@ package fr.xephi.authme.command;
import fr.xephi.authme.permission.AdminPermission;
import fr.xephi.authme.permission.PermissionNode;
import fr.xephi.authme.util.StringUtils;
-import fr.xephi.authme.util.WrapperMock;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -38,7 +37,6 @@ public class CommandInitializerTest {
@BeforeClass
public static void initializeCommandManager() {
- WrapperMock.createInstance();
commands = CommandInitializer.buildCommands();
}
diff --git a/src/test/java/fr/xephi/authme/command/CommandMapperTest.java b/src/test/java/fr/xephi/authme/command/CommandMapperTest.java
index 8da42043..77840e89 100644
--- a/src/test/java/fr/xephi/authme/command/CommandMapperTest.java
+++ b/src/test/java/fr/xephi/authme/command/CommandMapperTest.java
@@ -13,12 +13,12 @@ import java.util.Set;
import static fr.xephi.authme.command.TestCommandsUtil.getCommandWithLabel;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
-import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
@@ -31,7 +31,7 @@ public class CommandMapperTest {
private static Set commands;
private static CommandMapper mapper;
- private static PermissionsManager permissionsManagerMock;
+ private static PermissionsManager permissionsManager;
@BeforeClass
public static void setUpCommandHandler() {
@@ -40,8 +40,8 @@ public class CommandMapperTest {
@Before
public void setUpMocks() {
- permissionsManagerMock = mock(PermissionsManager.class);
- mapper = new CommandMapper(commands, permissionsManagerMock);
+ permissionsManager = mock(PermissionsManager.class);
+ mapper = new CommandMapper(commands, permissionsManager);
}
// -----------
@@ -52,7 +52,7 @@ public class CommandMapperTest {
// given
List parts = Arrays.asList("authme", "login", "test1");
CommandSender sender = mock(CommandSender.class);
- given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
+ given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@@ -71,7 +71,7 @@ public class CommandMapperTest {
// given
List parts = Arrays.asList("Authme", "REG", "arg1", "arg2");
CommandSender sender = mock(CommandSender.class);
- given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
+ given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@@ -89,7 +89,7 @@ public class CommandMapperTest {
// given
List parts = Arrays.asList("authme", "register", "pass123", "pass123", "pass123");
CommandSender sender = mock(CommandSender.class);
- given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
+ given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@@ -107,7 +107,7 @@ public class CommandMapperTest {
// given
List parts = Arrays.asList("authme", "Reg");
CommandSender sender = mock(CommandSender.class);
- given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
+ given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@@ -125,7 +125,7 @@ public class CommandMapperTest {
// given
List parts = Arrays.asList("authme", "reh", "pass123", "pass123");
CommandSender sender = mock(CommandSender.class);
- given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
+ given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@@ -144,7 +144,7 @@ public class CommandMapperTest {
// given
List parts = Arrays.asList("authme", "asdfawetawty4asdca");
CommandSender sender = mock(CommandSender.class);
- given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
+ given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@@ -162,7 +162,7 @@ public class CommandMapperTest {
// given
List parts = singletonList("unregister");
CommandSender sender = mock(CommandSender.class);
- given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
+ given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@@ -180,7 +180,7 @@ public class CommandMapperTest {
// given
List parts = asList("bogus", "label1", "arg1");
CommandSender sender = mock(CommandSender.class);
- given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
+ given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@@ -205,7 +205,7 @@ public class CommandMapperTest {
// given
List parts = asList("Unreg", "player1");
CommandSender sender = mock(CommandSender.class);
- given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
+ given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@@ -223,7 +223,7 @@ public class CommandMapperTest {
// given
List parts = asList("unregistER", "player1", "wrongArg");
CommandSender sender = mock(CommandSender.class);
- given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
+ given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@@ -241,7 +241,7 @@ public class CommandMapperTest {
// given
List parts = asList("email", "helptest", "arg1");
CommandSender sender = mock(CommandSender.class);
- given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
+ given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@@ -259,7 +259,7 @@ public class CommandMapperTest {
// given
List parts = Arrays.asList("authme", "login", "test1");
CommandSender sender = mock(CommandSender.class);
- given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(false);
+ given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(false);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
diff --git a/src/test/java/fr/xephi/authme/command/CommandServiceTest.java b/src/test/java/fr/xephi/authme/command/CommandServiceTest.java
index d34ee633..89a35571 100644
--- a/src/test/java/fr/xephi/authme/command/CommandServiceTest.java
+++ b/src/test/java/fr/xephi/authme/command/CommandServiceTest.java
@@ -2,7 +2,6 @@ package fr.xephi.authme.command;
import fr.xephi.authme.AntiBot;
import fr.xephi.authme.AuthMe;
-import fr.xephi.authme.cache.IpAddressManager;
import fr.xephi.authme.command.help.HelpProvider;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.hooks.PluginHooks;
@@ -15,6 +14,8 @@ import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.domain.Property;
import fr.xephi.authme.settings.properties.SecuritySettings;
+import fr.xephi.authme.util.BukkitService;
+import fr.xephi.authme.util.ValidationService;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.junit.Before;
@@ -27,8 +28,8 @@ import org.mockito.runners.MockitoJUnitRunner;
import java.util.Arrays;
import java.util.List;
-import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@@ -56,18 +57,20 @@ public class CommandServiceTest {
@Mock
private NewSetting settings;
@Mock
- private IpAddressManager ipAddressManager;
- @Mock
private PluginHooks pluginHooks;
@Mock
private SpawnLoader spawnLoader;
@Mock
private AntiBot antiBot;
+ @Mock
+ private ValidationService validationService;
+ @Mock
+ private BukkitService bukkitService;
@Before
public void setUpService() {
commandService = new CommandService(authMe, commandMapper, helpProvider, messages, passwordSecurity,
- permissionsManager, settings, ipAddressManager, pluginHooks, spawnLoader, antiBot);
+ permissionsManager, settings, pluginHooks, spawnLoader, antiBot, validationService, bukkitService);
}
@Test
@@ -221,11 +224,63 @@ public class CommandServiceTest {
}
@Test
- public void shouldReturnIpAddressManager() {
- // given/when
- IpAddressManager ipManager = commandService.getIpAddressManager();
+ public void shouldValidatePassword() {
+ // given
+ String user = "asdf";
+ String password = "mySecret55";
+ given(validationService.validatePassword(password, user)).willReturn(MessageKey.INVALID_PASSWORD_LENGTH);
+
+ // when
+ MessageKey result = commandService.validatePassword(password, user);
// then
- assertThat(ipManager, equalTo(ipAddressManager));
+ assertThat(result, equalTo(MessageKey.INVALID_PASSWORD_LENGTH));
+ verify(validationService).validatePassword(password, user);
}
+
+ @Test
+ public void shouldValidateEmail() {
+ // given
+ String email = "test@example.tld";
+ given(validationService.validateEmail(email)).willReturn(true);
+
+ // when
+ boolean result = commandService.validateEmail(email);
+
+ // then
+ assertThat(result, equalTo(true));
+ verify(validationService).validateEmail(email);
+ }
+
+ @Test
+ public void shouldCheckIfEmailCanBeUsed() {
+ // given
+ String email = "mail@example.com";
+ CommandSender sender = mock(CommandSender.class);
+ given(validationService.isEmailFreeForRegistration(email, sender))
+ .willReturn(true);
+
+ // when
+ boolean result = commandService.isEmailFreeForRegistration(email, sender);
+
+ // then
+ assertThat(result, equalTo(true));
+ verify(validationService).isEmailFreeForRegistration(email, sender);
+ }
+
+ @Test
+ public void shouldGetPlayer() {
+ // given
+ String playerName = "_tester";
+ Player player = mock(Player.class);
+ given(bukkitService.getPlayerExact(playerName)).willReturn(player);
+
+ // when
+ Player result = commandService.getPlayer(playerName);
+
+ // then
+ assertThat(result, equalTo(player));
+ verify(bukkitService).getPlayerExact(playerName);
+ }
+
}
diff --git a/src/test/java/fr/xephi/authme/command/PlayerCommandTest.java b/src/test/java/fr/xephi/authme/command/PlayerCommandTest.java
index 4afee564..a4c02b93 100644
--- a/src/test/java/fr/xephi/authme/command/PlayerCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/PlayerCommandTest.java
@@ -4,14 +4,13 @@ import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.junit.Test;
-import org.mockito.ArgumentCaptor;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
+import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -28,12 +27,10 @@ public class PlayerCommandTest {
PlayerCommandImpl command = new PlayerCommandImpl();
// when
- command.executeCommand(sender, Collections. emptyList(), mock(CommandService.class));
+ command.executeCommand(sender, Collections.emptyList(), mock(CommandService.class));
// then
- ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
- verify(sender, times(1)).sendMessage(captor.capture());
- assertThat(captor.getValue(), containsString("only for players"));
+ verify(sender).sendMessage(argThat(containsString("only for players")));
}
@Test
@@ -58,12 +55,10 @@ public class PlayerCommandTest {
PlayerCommandWithAlt command = new PlayerCommandWithAlt();
// when
- command.executeCommand(sender, Collections. emptyList(), mock(CommandService.class));
+ command.executeCommand(sender, Collections.emptyList(), mock(CommandService.class));
// then
- ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
- verify(sender, times(1)).sendMessage(captor.capture());
- assertThat(captor.getValue(), containsString("use /authme test instead"));
+ verify(sender, times(1)).sendMessage(argThat(containsString("use /authme test instead")));
}
diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/AccountsCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/AccountsCommandTest.java
index 82469635..5a837280 100644
--- a/src/test/java/fr/xephi/authme/command/executable/authme/AccountsCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/authme/AccountsCommandTest.java
@@ -14,8 +14,8 @@ import java.util.Collections;
import java.util.List;
import static fr.xephi.authme.TestHelper.runInnerRunnable;
-import static org.hamcrest.CoreMatchers.containsString;
-import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
@@ -81,7 +81,7 @@ public class AccountsCommandTest {
// given
List arguments = Collections.singletonList("SomeUser");
given(dataSource.getAuth("someuser")).willReturn(mock(PlayerAuth.class));
- given(dataSource.getAllAuthsByIp(anyString())).willReturn(Collections. emptyList());
+ given(dataSource.getAllAuthsByIp(anyString())).willReturn(Collections.emptyList());
// when
command.executeCommand(sender, arguments, service);
@@ -115,7 +115,7 @@ public class AccountsCommandTest {
public void shouldReturnIpUnknown() {
// given
List arguments = Collections.singletonList("123.45.67.89");
- given(dataSource.getAllAuthsByIp("123.45.67.89")).willReturn(Collections. emptyList());
+ given(dataSource.getAllAuthsByIp("123.45.67.89")).willReturn(Collections.emptyList());
// when
command.executeCommand(sender, arguments, service);
diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/AuthMeCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/AuthMeCommandTest.java
index 8be1185a..c1c0c6e3 100644
--- a/src/test/java/fr/xephi/authme/command/executable/authme/AuthMeCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/authme/AuthMeCommandTest.java
@@ -8,7 +8,7 @@ import org.mockito.ArgumentCaptor;
import java.util.Collections;
-import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommandTest.java
index 28a6a3f8..b4f42886 100644
--- a/src/test/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommandTest.java
@@ -1,7 +1,6 @@
package fr.xephi.authme.command.executable.authme;
-import com.google.common.base.Strings;
-import fr.xephi.authme.ConsoleLoggerTestInitializer;
+import fr.xephi.authme.TestHelper;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.command.CommandService;
@@ -10,12 +9,12 @@ import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.security.crypts.HashedPassword;
-import fr.xephi.authme.settings.properties.RestrictionSettings;
-import fr.xephi.authme.settings.properties.SecuritySettings;
import org.bukkit.command.CommandSender;
-import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
import java.util.Arrays;
@@ -29,97 +28,33 @@ import static org.mockito.Mockito.verify;
/**
* Test for {@link ChangePasswordAdminCommand}.
*/
+@RunWith(MockitoJUnitRunner.class)
public class ChangePasswordAdminCommandTest {
+ @Mock
private CommandService service;
@BeforeClass
public static void setUpLogger() {
- ConsoleLoggerTestInitializer.setupLogger();
- }
-
- @Before
- public void setUpServiceMock() {
- service = mock(CommandService.class);
- given(service.getProperty(RestrictionSettings.ALLOWED_PASSWORD_REGEX)).willReturn("[a-zA-Z]+");
- given(service.getProperty(SecuritySettings.MIN_PASSWORD_LENGTH)).willReturn(3);
- given(service.getProperty(SecuritySettings.MAX_PASSWORD_LENGTH)).willReturn(20);
- given(service.getProperty(SecuritySettings.UNSAFE_PASSWORDS))
- .willReturn(Arrays.asList("unsafe", "otherUnsafe"));
+ TestHelper.setupLogger();
}
@Test
- public void shouldRejectPasswordSameAsUsername() {
+ public void shouldRejectInvalidPassword() {
// given
ExecutableCommand command = new ChangePasswordAdminCommand();
CommandSender sender = mock(CommandSender.class);
+ given(service.validatePassword("Bobby", "bobby")).willReturn(MessageKey.PASSWORD_IS_USERNAME_ERROR);
// when
command.executeCommand(sender, Arrays.asList("bobby", "Bobby"), service);
// then
+ verify(service).validatePassword("Bobby", "bobby");
verify(service).send(sender, MessageKey.PASSWORD_IS_USERNAME_ERROR);
verify(service, never()).getDataSource();
}
- @Test
- public void shouldRejectPasswordNotMatchingPattern() {
- // given
- ExecutableCommand command = new ChangePasswordAdminCommand();
- CommandSender sender = mock(CommandSender.class);
- // service mock returns pattern a-zA-Z -> numbers should not be accepted
- String invalidPassword = "invalid1234";
-
- // when
- command.executeCommand(sender, Arrays.asList("myPlayer123", invalidPassword), service);
-
- // then
- verify(service).send(sender, MessageKey.PASSWORD_MATCH_ERROR);
- verify(service, never()).getDataSource();
- }
-
- @Test
- public void shouldRejectTooShortPassword() {
- // given
- ExecutableCommand command = new ChangePasswordAdminCommand();
- CommandSender sender = mock(CommandSender.class);
-
- // when
- command.executeCommand(sender, Arrays.asList("player", "ab"), service);
-
- // then
- verify(service).send(sender, MessageKey.INVALID_PASSWORD_LENGTH);
- verify(service, never()).getDataSource();
- }
-
- @Test
- public void shouldRejectTooLongPassword() {
- // given
- ExecutableCommand command = new ChangePasswordAdminCommand();
- CommandSender sender = mock(CommandSender.class);
-
- // when
- command.executeCommand(sender, Arrays.asList("player", Strings.repeat("a", 30)), service);
-
- // then
- verify(service).send(sender, MessageKey.INVALID_PASSWORD_LENGTH);
- verify(service, never()).getDataSource();
- }
-
- @Test
- public void shouldRejectUnsafePassword() {
- // given
- ExecutableCommand command = new ChangePasswordAdminCommand();
- CommandSender sender = mock(CommandSender.class);
-
- // when
- command.executeCommand(sender, Arrays.asList("player", "unsafe"), service);
-
- // then
- verify(service).send(sender, MessageKey.PASSWORD_UNSAFE_ERROR);
- verify(service, never()).getDataSource();
- }
-
@Test
public void shouldRejectCommandForUnknownUser() {
// given
@@ -173,6 +108,7 @@ public class ChangePasswordAdminCommandTest {
runInnerRunnable(service);
// then
+ verify(service).validatePassword(password, player);
verify(service).send(sender, MessageKey.PASSWORD_CHANGED_SUCCESS);
verify(passwordSecurity).computeHash(password, player);
verify(auth).setPassword(hashedPassword);
@@ -209,6 +145,7 @@ public class ChangePasswordAdminCommandTest {
runInnerRunnable(service);
// then
+ verify(service).validatePassword(password, player);
verify(service).send(sender, MessageKey.PASSWORD_CHANGED_SUCCESS);
verify(passwordSecurity).computeHash(password, player);
verify(auth).setPassword(hashedPassword);
@@ -244,6 +181,7 @@ public class ChangePasswordAdminCommandTest {
runInnerRunnable(service);
// then
+ verify(service).validatePassword(password, player);
verify(service).send(sender, MessageKey.ERROR);
verify(passwordSecurity).computeHash(password, player);
verify(auth).setPassword(hashedPassword);
diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommandTest.java
index aa4f7b74..0c70bd01 100644
--- a/src/test/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommandTest.java
@@ -6,14 +6,13 @@ import fr.xephi.authme.settings.SpawnLoader;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.junit.Test;
-import org.mockito.ArgumentCaptor;
import java.util.Collections;
import static org.hamcrest.Matchers.containsString;
-import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -36,7 +35,7 @@ public class FirstSpawnCommandTest {
ExecutableCommand command = new FirstSpawnCommand();
// when
- command.executeCommand(player, Collections. emptyList(), service);
+ command.executeCommand(player, Collections.emptyList(), service);
// then
verify(player).teleport(firstSpawn);
@@ -54,12 +53,10 @@ public class FirstSpawnCommandTest {
ExecutableCommand command = new FirstSpawnCommand();
// when
- command.executeCommand(player, Collections. emptyList(), service);
+ command.executeCommand(player, Collections.emptyList(), service);
// then
- ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
- verify(player).sendMessage(captor.capture());
- assertThat(captor.getValue(), containsString("spawn has failed"));
+ verify(player).sendMessage(argThat(containsString("spawn has failed")));
verify(player, never()).teleport(any(Location.class));
}
}
diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/ForceLoginCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/ForceLoginCommandTest.java
new file mode 100644
index 00000000..f6a01f2d
--- /dev/null
+++ b/src/test/java/fr/xephi/authme/command/executable/authme/ForceLoginCommandTest.java
@@ -0,0 +1,146 @@
+package fr.xephi.authme.command.executable.authme;
+
+import fr.xephi.authme.command.CommandService;
+import fr.xephi.authme.command.ExecutableCommand;
+import fr.xephi.authme.permission.PermissionsManager;
+import fr.xephi.authme.permission.PlayerPermission;
+import fr.xephi.authme.process.Management;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import java.util.Collections;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+/**
+ * Test for {@link ForceLoginCommand}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class ForceLoginCommandTest {
+
+ @Mock
+ private CommandService commandService;
+
+ @Test
+ public void shouldRejectOfflinePlayer() {
+ // given
+ String playerName = "Bobby";
+ Player player = mockPlayer(false, playerName);
+ given(commandService.getPlayer(playerName)).willReturn(player);
+ CommandSender sender = mock(CommandSender.class);
+ ExecutableCommand command = new ForceLoginCommand();
+
+ // when
+ command.executeCommand(sender, Collections.singletonList(playerName), commandService);
+
+ // then
+ verify(commandService).getPlayer(playerName);
+ verify(sender).sendMessage(argThat(equalTo("Player needs to be online!")));
+ verify(commandService, never()).getManagement();
+ }
+
+ @Test
+ public void shouldRejectInexistentPlayer() {
+ // given
+ String playerName = "us3rname01";
+ given(commandService.getPlayer(playerName)).willReturn(null);
+ CommandSender sender = mock(CommandSender.class);
+ ExecutableCommand command = new ForceLoginCommand();
+
+ // when
+ command.executeCommand(sender, Collections.singletonList(playerName), commandService);
+
+ // then
+ verify(commandService).getPlayer(playerName);
+ verify(sender).sendMessage(argThat(equalTo("Player needs to be online!")));
+ verify(commandService, never()).getManagement();
+ }
+
+ @Test
+ public void shouldRejectPlayerWithMissingPermission() {
+ // given
+ String playerName = "testTest";
+ Player player = mockPlayer(true, playerName);
+ given(commandService.getPlayer(playerName)).willReturn(player);
+ PermissionsManager permissionsManager = mock(PermissionsManager.class);
+ given(permissionsManager.hasPermission(player, PlayerPermission.CAN_LOGIN_BE_FORCED)).willReturn(false);
+ given(commandService.getPermissionsManager()).willReturn(permissionsManager);
+
+ CommandSender sender = mock(CommandSender.class);
+ ExecutableCommand command = new ForceLoginCommand();
+
+ // when
+ command.executeCommand(sender, Collections.singletonList(playerName), commandService);
+
+ // then
+ verify(commandService).getPlayer(playerName);
+ verify(sender).sendMessage(argThat(containsString("You cannot force login the player")));
+ verify(commandService, never()).getManagement();
+ }
+
+ @Test
+ public void shouldForceLoginPlayer() {
+ // given
+ String playerName = "tester23";
+ Player player = mockPlayer(true, playerName);
+ given(commandService.getPlayer(playerName)).willReturn(player);
+ PermissionsManager permissionsManager = mock(PermissionsManager.class);
+ given(permissionsManager.hasPermission(player, PlayerPermission.CAN_LOGIN_BE_FORCED)).willReturn(true);
+ given(commandService.getPermissionsManager()).willReturn(permissionsManager);
+ Management management = mock(Management.class);
+ given(commandService.getManagement()).willReturn(management);
+
+ CommandSender sender = mock(CommandSender.class);
+ ExecutableCommand command = new ForceLoginCommand();
+
+ // when
+ command.executeCommand(sender, Collections.singletonList(playerName), commandService);
+
+ // then
+ verify(commandService).getPlayer(playerName);
+ verify(management).performLogin(eq(player), anyString(), eq(true));
+ }
+
+ @Test
+ public void shouldForceLoginSenderSelf() {
+ // given
+ String senderName = "tester23";
+ Player player = mockPlayer(true, senderName);
+ given(commandService.getPlayer(senderName)).willReturn(player);
+ PermissionsManager permissionsManager = mock(PermissionsManager.class);
+ given(permissionsManager.hasPermission(player, PlayerPermission.CAN_LOGIN_BE_FORCED)).willReturn(true);
+ given(commandService.getPermissionsManager()).willReturn(permissionsManager);
+ Management management = mock(Management.class);
+ given(commandService.getManagement()).willReturn(management);
+
+ CommandSender sender = mock(CommandSender.class);
+ given(sender.getName()).willReturn(senderName);
+ ExecutableCommand command = new ForceLoginCommand();
+
+ // when
+ command.executeCommand(sender, Collections.emptyList(), commandService);
+
+ // then
+ verify(commandService).getPlayer(senderName);
+ verify(management).performLogin(eq(player), anyString(), eq(true));
+ }
+
+ private static Player mockPlayer(boolean isOnline, String name) {
+ Player player = mock(Player.class);
+ given(player.isOnline()).willReturn(isOnline);
+ given(player.getName()).willReturn(name);
+ return player;
+ }
+}
diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/GetEmailCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/GetEmailCommandTest.java
index 247c43ac..6d232037 100644
--- a/src/test/java/fr/xephi/authme/command/executable/authme/GetEmailCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/authme/GetEmailCommandTest.java
@@ -7,13 +7,12 @@ import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
import org.bukkit.command.CommandSender;
import org.junit.Test;
-import org.mockito.ArgumentCaptor;
import java.util.Collections;
import static org.hamcrest.Matchers.containsString;
-import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
+import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -61,8 +60,6 @@ public class GetEmailCommandTest {
command.executeCommand(sender, Collections.singletonList(user), service);
// then
- ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
- verify(sender).sendMessage(captor.capture());
- assertThat(captor.getValue(), containsString(email));
+ verify(sender).sendMessage(argThat(containsString(email)));
}
}
diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/GetIpCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/GetIpCommandTest.java
new file mode 100644
index 00000000..7e070af6
--- /dev/null
+++ b/src/test/java/fr/xephi/authme/command/executable/authme/GetIpCommandTest.java
@@ -0,0 +1,75 @@
+package fr.xephi.authme.command.executable.authme;
+
+import fr.xephi.authme.command.CommandService;
+import fr.xephi.authme.command.ExecutableCommand;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.util.Collections;
+
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.containsString;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+/**
+ * Test for {@link GetIpCommand}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class GetIpCommandTest {
+
+ @Mock
+ private CommandService commandService;
+ @Mock
+ private CommandSender sender;
+
+ @Test
+ public void shouldGetIpOfPlayer() {
+ // given
+ given(commandService.getPlayer(anyString())).willReturn(null);
+ ExecutableCommand command = new GetIpCommand();
+
+ // when
+ command.executeCommand(sender, Collections.singletonList("Testt"), commandService);
+
+ // then
+ verify(commandService).getPlayer("Testt");
+ verify(sender).sendMessage(argThat(containsString("not online")));
+ }
+
+ @Test
+ public void shouldReturnIpAddressOfPlayer() {
+ // given
+ String playerName = "charlie";
+ String ip = "123.34.56.88";
+ Player player = mockPlayer(playerName, ip);
+ given(commandService.getPlayer(playerName)).willReturn(player);
+ ExecutableCommand command = new GetIpCommand();
+
+ // when
+ command.executeCommand(sender, Collections.singletonList(playerName), commandService);
+
+ // then
+ verify(commandService).getPlayer(playerName);
+ verify(sender).sendMessage(argThat(allOf(containsString(playerName), containsString(ip))));
+ }
+
+ private static Player mockPlayer(String name, String ip) {
+ Player player = mock(Player.class);
+ given(player.getName()).willReturn(name);
+ InetAddress inetAddress = mock(InetAddress.class);
+ given(inetAddress.getHostAddress()).willReturn(ip);
+ InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, 8093);
+ given(player.getAddress()).willReturn(inetSocketAddress);
+ return player;
+ }
+}
diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/LastLoginCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/LastLoginCommandTest.java
index 96cf8844..d1e58e92 100644
--- a/src/test/java/fr/xephi/authme/command/executable/authme/LastLoginCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/authme/LastLoginCommandTest.java
@@ -103,7 +103,7 @@ public class LastLoginCommandTest {
ExecutableCommand command = new LastLoginCommand();
// when
- command.executeCommand(sender, Collections. emptyList(), service);
+ command.executeCommand(sender, Collections.emptyList(), service);
// then
verify(dataSource).getAuth(name);
diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommandTest.java
index 9f207866..bcce0342 100644
--- a/src/test/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommandTest.java
@@ -61,7 +61,7 @@ public class PurgeLastPositionCommandTest {
ExecutableCommand command = new PurgeLastPositionCommand();
// when
- command.executeCommand(sender, Collections. emptyList(), service);
+ command.executeCommand(sender, Collections.emptyList(), service);
// then
verify(dataSource).getAuth(player);
diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommandTest.java
new file mode 100644
index 00000000..d2c7fd1e
--- /dev/null
+++ b/src/test/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommandTest.java
@@ -0,0 +1,177 @@
+package fr.xephi.authme.command.executable.authme;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import java.util.Arrays;
+
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import fr.xephi.authme.TestHelper;
+import fr.xephi.authme.cache.auth.PlayerAuth;
+import fr.xephi.authme.command.CommandService;
+import fr.xephi.authme.command.ExecutableCommand;
+import fr.xephi.authme.datasource.DataSource;
+import fr.xephi.authme.output.MessageKey;
+import fr.xephi.authme.security.PasswordSecurity;
+import fr.xephi.authme.security.crypts.HashedPassword;
+
+/**
+ * Test for {@link RegisterAdminCommand}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class RegisterAdminCommandTest {
+
+ @Mock
+ private CommandSender sender;
+ @Mock
+ private CommandService commandService;
+
+ @BeforeClass
+ public static void setUpLogger() {
+ TestHelper.setupLogger();
+ }
+
+ @Test
+ public void shouldRejectInvalidPassword() {
+ // given
+ String user = "tester";
+ String password = "myPassword";
+ given(commandService.validatePassword(password, user)).willReturn(MessageKey.INVALID_PASSWORD_LENGTH);
+ ExecutableCommand command = new RegisterAdminCommand();
+
+ // when
+ command.executeCommand(sender, Arrays.asList(user, password), commandService);
+
+ // then
+ verify(commandService).validatePassword(password, user);
+ verify(commandService).send(sender, MessageKey.INVALID_PASSWORD_LENGTH);
+ verify(commandService, never()).runTaskAsynchronously(any(Runnable.class));
+ }
+
+ @Test
+ public void shouldRejectAlreadyRegisteredAccount() {
+ // given
+ String user = "my_name55";
+ String password = "@some-pass@";
+ given(commandService.validatePassword(password, user)).willReturn(null);
+ DataSource dataSource = mock(DataSource.class);
+ given(dataSource.isAuthAvailable(user)).willReturn(true);
+ given(commandService.getDataSource()).willReturn(dataSource);
+ ExecutableCommand command = new RegisterAdminCommand();
+
+ // when
+ command.executeCommand(sender, Arrays.asList(user, password), commandService);
+ TestHelper.runInnerRunnable(commandService);
+
+ // then
+ verify(commandService).validatePassword(password, user);
+ verify(commandService).send(sender, MessageKey.NAME_ALREADY_REGISTERED);
+ verify(dataSource, never()).saveAuth(any(PlayerAuth.class));
+ }
+
+ @Test
+ public void shouldHandleSavingError() {
+ // given
+ String user = "test-test";
+ String password = "afdjhfkt";
+ given(commandService.validatePassword(password, user)).willReturn(null);
+ DataSource dataSource = mock(DataSource.class);
+ given(dataSource.isAuthAvailable(user)).willReturn(false);
+ given(dataSource.saveAuth(any(PlayerAuth.class))).willReturn(false);
+ given(commandService.getDataSource()).willReturn(dataSource);
+ PasswordSecurity passwordSecurity = mock(PasswordSecurity.class);
+ HashedPassword hashedPassword = new HashedPassword("235sdf4w5udsgf");
+ given(passwordSecurity.computeHash(password, user)).willReturn(hashedPassword);
+ given(commandService.getPasswordSecurity()).willReturn(passwordSecurity);
+ ExecutableCommand command = new RegisterAdminCommand();
+
+ // when
+ command.executeCommand(sender, Arrays.asList(user, password), commandService);
+ TestHelper.runInnerRunnable(commandService);
+
+ // then
+ verify(commandService).validatePassword(password, user);
+ verify(commandService).send(sender, MessageKey.ERROR);
+ ArgumentCaptor captor = ArgumentCaptor.forClass(PlayerAuth.class);
+ verify(dataSource).saveAuth(captor.capture());
+ assertAuthHasInfo(captor.getValue(), user, hashedPassword);
+ }
+
+ @Test
+ public void shouldRegisterOfflinePlayer() {
+ // given
+ String user = "someone";
+ String password = "Al1O3P49S5%";
+ given(commandService.validatePassword(password, user)).willReturn(null);
+ DataSource dataSource = mock(DataSource.class);
+ given(dataSource.isAuthAvailable(user)).willReturn(false);
+ given(dataSource.saveAuth(any(PlayerAuth.class))).willReturn(true);
+ given(commandService.getDataSource()).willReturn(dataSource);
+ PasswordSecurity passwordSecurity = mock(PasswordSecurity.class);
+ HashedPassword hashedPassword = new HashedPassword("$aea2345EW235dfsa@#R%987048");
+ given(passwordSecurity.computeHash(password, user)).willReturn(hashedPassword);
+ given(commandService.getPasswordSecurity()).willReturn(passwordSecurity);
+ given(commandService.getPlayer(user)).willReturn(null);
+ ExecutableCommand command = new RegisterAdminCommand();
+
+ // when
+ command.executeCommand(sender, Arrays.asList(user, password), commandService);
+ TestHelper.runInnerRunnable(commandService);
+
+ // then
+ verify(commandService).validatePassword(password, user);
+ verify(commandService).send(sender, MessageKey.REGISTER_SUCCESS);
+ ArgumentCaptor captor = ArgumentCaptor.forClass(PlayerAuth.class);
+ verify(dataSource).saveAuth(captor.capture());
+ assertAuthHasInfo(captor.getValue(), user, hashedPassword);
+ verify(dataSource).setUnlogged(user);
+ }
+
+ @Test
+ public void shouldRegisterOnlinePlayer() {
+ // given
+ String user = "someone";
+ String password = "Al1O3P49S5%";
+ given(commandService.validatePassword(password, user)).willReturn(null);
+ DataSource dataSource = mock(DataSource.class);
+ given(dataSource.isAuthAvailable(user)).willReturn(false);
+ given(dataSource.saveAuth(any(PlayerAuth.class))).willReturn(true);
+ given(commandService.getDataSource()).willReturn(dataSource);
+ PasswordSecurity passwordSecurity = mock(PasswordSecurity.class);
+ HashedPassword hashedPassword = new HashedPassword("$aea2345EW235dfsa@#R%987048");
+ given(passwordSecurity.computeHash(password, user)).willReturn(hashedPassword);
+ given(commandService.getPasswordSecurity()).willReturn(passwordSecurity);
+ ExecutableCommand command = new RegisterAdminCommand();
+
+ // when
+ command.executeCommand(sender, Arrays.asList(user, password), commandService);
+ TestHelper.runInnerRunnable(commandService);
+
+ // then
+ verify(commandService).validatePassword(password, user);
+ verify(commandService).send(sender, MessageKey.REGISTER_SUCCESS);
+ ArgumentCaptor captor = ArgumentCaptor.forClass(PlayerAuth.class);
+ verify(dataSource).saveAuth(captor.capture());
+ assertAuthHasInfo(captor.getValue(), user, hashedPassword);
+ verify(dataSource).setUnlogged(user);
+ }
+
+ private void assertAuthHasInfo(PlayerAuth auth, String name, HashedPassword hashedPassword) {
+ assertThat(auth.getRealName(), equalTo(name));
+ assertThat(auth.getNickname(), equalTo(name.toLowerCase()));
+ assertThat(auth.getPassword(), equalTo(hashedPassword));
+ }
+}
diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/ReloadCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/ReloadCommandTest.java
index 873108ee..99600c89 100644
--- a/src/test/java/fr/xephi/authme/command/executable/authme/ReloadCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/authme/ReloadCommandTest.java
@@ -1,7 +1,7 @@
package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.AuthMe;
-import fr.xephi.authme.ConsoleLoggerTestInitializer;
+import fr.xephi.authme.TestHelper;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.output.MessageKey;
@@ -24,7 +24,7 @@ public class ReloadCommandTest {
@BeforeClass
public static void setUpLogger() {
- ConsoleLoggerTestInitializer.setupLogger();
+ TestHelper.setupLogger();
}
@Test
@@ -37,7 +37,7 @@ public class ReloadCommandTest {
ExecutableCommand command = new ReloadCommand();
// when
- command.executeCommand(sender, Collections. emptyList(), service);
+ command.executeCommand(sender, Collections.emptyList(), service);
// then
verify(authMe).reload();
@@ -55,7 +55,7 @@ public class ReloadCommandTest {
ExecutableCommand command = new ReloadCommand();
// when
- command.executeCommand(sender, Collections. emptyList(), service);
+ command.executeCommand(sender, Collections.emptyList(), service);
// then
verify(authMe).reload();
diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommandTest.java
index 307831ce..74964882 100644
--- a/src/test/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommandTest.java
@@ -35,7 +35,7 @@ public class SetFirstSpawnCommandTest {
ExecutableCommand command = new SetFirstSpawnCommand();
// when
- command.executeCommand(player, Collections. emptyList(), service);
+ command.executeCommand(player, Collections.emptyList(), service);
// then
verify(spawnLoader).setFirstSpawn(location);
@@ -57,7 +57,7 @@ public class SetFirstSpawnCommandTest {
ExecutableCommand command = new SetFirstSpawnCommand();
// when
- command.executeCommand(player, Collections. emptyList(), service);
+ command.executeCommand(player, Collections.emptyList(), service);
// then
verify(spawnLoader).setFirstSpawn(location);
diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/SetSpawnCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/SetSpawnCommandTest.java
index 11c28d32..e3e01f99 100644
--- a/src/test/java/fr/xephi/authme/command/executable/authme/SetSpawnCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/authme/SetSpawnCommandTest.java
@@ -35,7 +35,7 @@ public class SetSpawnCommandTest {
ExecutableCommand command = new SetSpawnCommand();
// when
- command.executeCommand(player, Collections. emptyList(), service);
+ command.executeCommand(player, Collections.emptyList(), service);
// then
verify(spawnLoader).setSpawn(location);
@@ -57,7 +57,7 @@ public class SetSpawnCommandTest {
ExecutableCommand command = new SetSpawnCommand();
// when
- command.executeCommand(player, Collections. emptyList(), service);
+ command.executeCommand(player, Collections.emptyList(), service);
// then
verify(spawnLoader).setSpawn(location);
diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/SpawnCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/SpawnCommandTest.java
index 7b76ad02..799d1ca4 100644
--- a/src/test/java/fr/xephi/authme/command/executable/authme/SpawnCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/authme/SpawnCommandTest.java
@@ -35,7 +35,7 @@ public class SpawnCommandTest {
ExecutableCommand command = new SpawnCommand();
// when
- command.executeCommand(player, Collections. emptyList(), service);
+ command.executeCommand(player, Collections.emptyList(), service);
// then
verify(player).teleport(spawn);
@@ -53,7 +53,7 @@ public class SpawnCommandTest {
ExecutableCommand command = new SpawnCommand();
// when
- command.executeCommand(player, Collections. emptyList(), service);
+ command.executeCommand(player, Collections.emptyList(), service);
// then
verify(player).sendMessage(argThat(containsString("Spawn has failed")));
diff --git a/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java
deleted file mode 100644
index b3b54a1c..00000000
--- a/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package fr.xephi.authme.command.executable.captcha;
-
-import fr.xephi.authme.AuthMe;
-import fr.xephi.authme.command.CommandService;
-import fr.xephi.authme.command.ExecutableCommand;
-import fr.xephi.authme.output.MessageKey;
-import fr.xephi.authme.output.Messages;
-import fr.xephi.authme.settings.properties.SecuritySettings;
-import fr.xephi.authme.util.WrapperMock;
-import org.bukkit.command.BlockCommandSender;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import java.util.ArrayList;
-import java.util.Collections;
-
-import static org.hamcrest.Matchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-/**
- * Test for {@link CaptchaCommand}.
- */
-public class CaptchaCommandTest {
-
- private WrapperMock wrapperMock;
- private CommandService commandService;
-
- @Before
- public void setUpWrapperMock() {
- wrapperMock = WrapperMock.createInstance();
- commandService = mock(CommandService.class);
- given(commandService.getProperty(SecuritySettings.USE_CAPTCHA)).willReturn(true);
- }
-
- @Test
- public void shouldRejectNonPlayerSender() {
- // given
- CommandSender sender = Mockito.mock(BlockCommandSender.class);
- ExecutableCommand command = new CaptchaCommand();
-
- // when
- command.executeCommand(sender, new ArrayList(), commandService);
-
- // then
- assertThat(wrapperMock.wasMockCalled(AuthMe.class), equalTo(false));
- assertThat(wrapperMock.wasMockCalled(Messages.class), equalTo(false));
- }
-
- @Test
- public void shouldRejectIfCaptchaIsNotUsed() {
- // given
- Player player = mockPlayerWithName("testplayer");
- ExecutableCommand command = new CaptchaCommand();
- given(commandService.getProperty(SecuritySettings.USE_CAPTCHA)).willReturn(false);
-
- // when
- command.executeCommand(player, Collections.singletonList("1234"), commandService);
-
- // then
- verify(commandService).send(player, MessageKey.USAGE_LOGIN);
- }
-
- private static Player mockPlayerWithName(String name) {
- Player player = Mockito.mock(Player.class);
- when(player.getName()).thenReturn(name);
- return player;
- }
-}
diff --git a/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java
index 213dba4c..bc8e0876 100644
--- a/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java
@@ -18,10 +18,11 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
+import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
@@ -57,9 +58,7 @@ public class ChangePasswordCommandTest {
command.executeCommand(sender, new ArrayList(), commandService);
// then
- ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
- verify(sender).sendMessage(captor.capture());
- assertThat(captor.getValue(), containsString("only for players"));
+ verify(sender).sendMessage(argThat(containsString("only for players")));
}
@Test
@@ -76,75 +75,21 @@ public class ChangePasswordCommandTest {
}
@Test
- public void shouldDenyInvalidPassword() {
- // given
- CommandSender sender = initPlayerWithName("name", true);
- ChangePasswordCommand command = new ChangePasswordCommand();
-
- // when
- command.executeCommand(sender, Arrays.asList("old123", "!pass"), commandService);
-
- // then
- verify(commandService).send(sender, MessageKey.PASSWORD_MATCH_ERROR);
- }
-
-
- @Test
- public void shouldRejectPasswordEqualToNick() {
- // given
- CommandSender sender = initPlayerWithName("tester", true);
- ChangePasswordCommand command = new ChangePasswordCommand();
-
- // when
- command.executeCommand(sender, Arrays.asList("old_", "Tester"), commandService);
-
- // then
- verify(commandService).send(sender, MessageKey.PASSWORD_IS_USERNAME_ERROR);
- }
-
- @Test
- public void shouldRejectTooLongPassword() {
+ public void shouldRejectInvalidPassword() {
// given
CommandSender sender = initPlayerWithName("abc12", true);
ChangePasswordCommand command = new ChangePasswordCommand();
- given(commandService.getProperty(SecuritySettings.MAX_PASSWORD_LENGTH)).willReturn(3);
+ String password = "newPW";
+ given(commandService.validatePassword(password, "abc12")).willReturn(MessageKey.INVALID_PASSWORD_LENGTH);
// when
- command.executeCommand(sender, Arrays.asList("12", "test"), commandService);
+ command.executeCommand(sender, Arrays.asList("tester", password), commandService);
// then
+ verify(commandService).validatePassword(password, "abc12");
verify(commandService).send(sender, MessageKey.INVALID_PASSWORD_LENGTH);
}
- @Test
- public void shouldRejectTooShortPassword() {
- // given
- CommandSender sender = initPlayerWithName("abc12", true);
- ChangePasswordCommand command = new ChangePasswordCommand();
- given(commandService.getProperty(SecuritySettings.MIN_PASSWORD_LENGTH)).willReturn(7);
-
- // when
- command.executeCommand(sender, Arrays.asList("oldverylongpassword", "tester"), commandService);
-
- // then
- verify(commandService).send(sender, MessageKey.INVALID_PASSWORD_LENGTH);
- }
-
- @Test
- public void shouldRejectUnsafeCustomPassword() {
- // given
- CommandSender sender = initPlayerWithName("player", true);
- ChangePasswordCommand command = new ChangePasswordCommand();
- given(commandService.getProperty(SecuritySettings.UNSAFE_PASSWORDS))
- .willReturn(Arrays.asList("test", "abc123"));
-
- // when
- command.executeCommand(sender, Arrays.asList("oldpw", "abc123"), commandService);
-
- // then
- verify(commandService).send(sender, MessageKey.PASSWORD_UNSAFE_ERROR);
- }
-
@Test
public void shouldForwardTheDataForValidPassword() {
// given
@@ -155,6 +100,7 @@ public class ChangePasswordCommandTest {
command.executeCommand(sender, Arrays.asList("abc123", "abc123"), commandService);
// then
+ verify(commandService).validatePassword("abc123", "parker");
verify(commandService, never()).send(eq(sender), any(MessageKey.class));
ArgumentCaptor taskCaptor = ArgumentCaptor.forClass(ChangePasswordTask.class);
verify(commandService).runTaskAsynchronously(taskCaptor.capture());
diff --git a/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java
index f1e55787..1ea41355 100644
--- a/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java
@@ -1,15 +1,15 @@
package fr.xephi.authme.command.executable.email;
import fr.xephi.authme.command.CommandService;
+import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.process.Management;
-import fr.xephi.authme.settings.NewSetting;
-import fr.xephi.authme.util.WrapperMock;
import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
-import org.junit.Before;
import org.junit.Test;
-import org.mockito.Mockito;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
import java.util.ArrayList;
import java.util.Arrays;
@@ -22,20 +22,16 @@ import static org.mockito.Mockito.verify;
/**
* Test for {@link AddEmailCommand}.
*/
+@RunWith(MockitoJUnitRunner.class)
public class AddEmailCommandTest {
+ @Mock
private CommandService commandService;
- @Before
- public void setUpMocks() {
- commandService = mock(CommandService.class);
- WrapperMock.createInstance();
- }
-
@Test
public void shouldRejectNonPlayerSender() {
// given
- CommandSender sender = Mockito.mock(BlockCommandSender.class);
+ CommandSender sender = mock(BlockCommandSender.class);
AddEmailCommand command = new AddEmailCommand();
// when
@@ -48,18 +44,34 @@ public class AddEmailCommandTest {
@Test
public void shouldForwardData() {
// given
- Player sender = Mockito.mock(Player.class);
- AddEmailCommand command = new AddEmailCommand();
+ Player sender = mock(Player.class);
+ String email = "mail@example";
+ given(commandService.validateEmail(email)).willReturn(true);
Management management = mock(Management.class);
given(commandService.getManagement()).willReturn(management);
- NewSetting settings = mock(NewSetting.class);
- given(commandService.getSettings()).willReturn(settings);
+ AddEmailCommand command = new AddEmailCommand();
// when
- command.executeCommand(sender, Arrays.asList("mail@example", "mail@example"), commandService);
+ command.executeCommand(sender, Arrays.asList(email, email), commandService);
// then
- verify(management).performAddEmail(sender, "mail@example");
+ verify(management).performAddEmail(sender, email);
+ }
+
+ @Test
+ public void shouldFailForConfirmationMismatch() {
+ // given
+ Player sender = mock(Player.class);
+ String email = "asdfasdf@example.com";
+ given(commandService.validateEmail(email)).willReturn(true);
+ AddEmailCommand command = new AddEmailCommand();
+
+ // when
+ command.executeCommand(sender, Arrays.asList(email, "wrongConf"), commandService);
+
+ // then
+ verify(commandService, never()).getManagement();
+ verify(commandService).send(sender, MessageKey.CONFIRM_EMAIL_MESSAGE);
}
}
diff --git a/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java
deleted file mode 100644
index 94c1c8dc..00000000
--- a/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package fr.xephi.authme.command.executable.email;
-
-import fr.xephi.authme.command.CommandService;
-import fr.xephi.authme.util.WrapperMock;
-import org.bukkit.command.BlockCommandSender;
-import org.bukkit.command.CommandSender;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import java.util.ArrayList;
-
-import static org.mockito.Mockito.mock;
-
-/**
- * Test for {@link RecoverEmailCommand}.
- */
-public class RecoverEmailCommandTest {
-
- @Before
- public void setUpMocks() {
- WrapperMock wrapper = WrapperMock.createInstance();
- }
-
- @Test
- @Ignore
- public void shouldRejectNonPlayerSender() {
- // given
- CommandSender sender = Mockito.mock(BlockCommandSender.class);
- RecoverEmailCommand command = new RecoverEmailCommand();
-
- // when
- command.executeCommand(sender, new ArrayList(), mock(CommandService.class));
-
- // then
- }
-
- // TODO ljacqu 20151121: Expand tests. This command doesn't use a scheduler and has all of its
- // logic inside here.
-}
diff --git a/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java
index 5e62866c..9a23bc17 100644
--- a/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java
@@ -2,22 +2,20 @@ package fr.xephi.authme.command.executable.login;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.process.Management;
-import fr.xephi.authme.settings.Settings;
-import fr.xephi.authme.util.WrapperMock;
import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
-import org.junit.Before;
import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mockito;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
import java.util.ArrayList;
import java.util.Collections;
-import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.mockito.BDDMockito.given;
+import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -26,17 +24,12 @@ import static org.mockito.Mockito.verify;
/**
* Test for {@link LoginCommand}.
*/
+@RunWith(MockitoJUnitRunner.class)
public class LoginCommandTest {
+ @Mock
private CommandService commandService;
- @Before
- public void initializeAuthMeMock() {
- WrapperMock.createInstance();
- Settings.captchaLength = 10;
- commandService = mock(CommandService.class);
- }
-
@Test
public void shouldStopIfSenderIsNotAPlayer() {
// given
@@ -47,10 +40,8 @@ public class LoginCommandTest {
command.executeCommand(sender, new ArrayList(), commandService);
// then
- Mockito.verify(commandService, never()).getManagement();
- ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(String.class);
- verify(sender).sendMessage(messageCaptor.capture());
- assertThat(messageCaptor.getValue(), containsString("only for players"));
+ verify(commandService, never()).getManagement();
+ verify(sender).sendMessage(argThat(containsString("only for players")));
}
@Test
@@ -65,7 +56,7 @@ public class LoginCommandTest {
command.executeCommand(sender, Collections.singletonList("password"), commandService);
// then
- Mockito.verify(management).performLogin(eq(sender), eq("password"), eq(false));
+ verify(management).performLogin(eq(sender), eq("password"), eq(false));
}
}
diff --git a/src/test/java/fr/xephi/authme/command/executable/logout/LogoutCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/logout/LogoutCommandTest.java
index 6e83e801..7ac3ede6 100644
--- a/src/test/java/fr/xephi/authme/command/executable/logout/LogoutCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/logout/LogoutCommandTest.java
@@ -2,21 +2,18 @@ package fr.xephi.authme.command.executable.logout;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.process.Management;
-import fr.xephi.authme.settings.Settings;
-import fr.xephi.authme.util.WrapperMock;
import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.junit.Before;
import org.junit.Test;
-import org.mockito.ArgumentCaptor;
import java.util.ArrayList;
import java.util.Collections;
-import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.mockito.BDDMockito.given;
+import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -30,8 +27,6 @@ public class LogoutCommandTest {
@Before
public void initializeAuthMeMock() {
- WrapperMock.createInstance();
- Settings.captchaLength = 10;
commandService = mock(CommandService.class);
}
@@ -46,9 +41,7 @@ public class LogoutCommandTest {
// then
verify(commandService, never()).getManagement();
- ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(String.class);
- verify(sender).sendMessage(messageCaptor.capture());
- assertThat(messageCaptor.getValue(), containsString("only for players"));
+ verify(sender).sendMessage(argThat(containsString("only for players")));
}
@Test
diff --git a/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java
index e4ff5ac0..6f86a5f6 100644
--- a/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java
@@ -1,39 +1,63 @@
package fr.xephi.authme.command.executable.register;
+import fr.xephi.authme.TestHelper;
import fr.xephi.authme.command.CommandService;
+import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.process.Management;
-import fr.xephi.authme.settings.Settings;
-import fr.xephi.authme.util.WrapperMock;
+import fr.xephi.authme.security.HashAlgorithm;
+import fr.xephi.authme.settings.properties.EmailSettings;
+import fr.xephi.authme.settings.properties.RegistrationSettings;
+import fr.xephi.authme.settings.properties.RestrictionSettings;
+import fr.xephi.authme.settings.properties.SecuritySettings;
import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Test;
-import org.mockito.ArgumentCaptor;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import static org.hamcrest.Matchers.containsString;
-import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
/**
* Test for {@link RegisterCommand}.
*/
+@RunWith(MockitoJUnitRunner.class)
public class RegisterCommandTest {
+ @Mock
private CommandService commandService;
+ @Mock
+ private Management management;
+ @Mock
+ private Player sender;
+
+ @BeforeClass
+ public static void setup() {
+ TestHelper.setupLogger();
+ }
@Before
- public void initializeAuthMeMock() {
- WrapperMock.createInstance();
- Settings.captchaLength = 10;
- commandService = mock(CommandService.class);
+ public void linkMocksAndProvideSettingDefaults() {
+ given(commandService.getManagement()).willReturn(management);
+ given(commandService.getProperty(SecuritySettings.PASSWORD_HASH)).willReturn(HashAlgorithm.BCRYPT);
+ given(commandService.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)).willReturn(false);
+ given(commandService.getProperty(RestrictionSettings.ENABLE_PASSWORD_CONFIRMATION)).willReturn(false);
}
@Test
@@ -46,39 +70,181 @@ public class RegisterCommandTest {
command.executeCommand(sender, new ArrayList(), commandService);
// then
- verify(commandService, never()).getManagement();
- ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(String.class);
- verify(sender).sendMessage(messageCaptor.capture());
- assertThat(messageCaptor.getValue(), containsString("Player only!"));
+ verify(sender).sendMessage(argThat(containsString("Player only!")));
+ verifyZeroInteractions(management);
}
@Test
- public void shouldFailForEmptyArguments() {
+ public void shouldForwardToManagementForTwoFactor() {
// given
- CommandSender sender = mock(Player.class);
- RegisterCommand command = new RegisterCommand();
+ given(commandService.getProperty(SecuritySettings.PASSWORD_HASH)).willReturn(HashAlgorithm.TWO_FACTOR);
+ ExecutableCommand command = new RegisterCommand();
// when
- command.executeCommand(sender, new ArrayList(), commandService);
+ command.executeCommand(sender, Collections.emptyList(), commandService);
+
+ // then
+ verify(management).performRegister(sender, "", "");
+ }
+
+ @Test
+ public void shouldReturnErrorForEmptyArguments() {
+ // given
+ ExecutableCommand command = new RegisterCommand();
+
+ // when
+ command.executeCommand(sender, Collections.emptyList(), commandService);
// then
verify(commandService).send(sender, MessageKey.USAGE_REGISTER);
- verify(commandService, never()).getManagement();
+ verifyZeroInteractions(management);
}
@Test
- public void shouldForwardRegister() {
+ public void shouldReturnErrorForMissingConfirmation() {
// given
- Player sender = mock(Player.class);
- RegisterCommand command = new RegisterCommand();
- Management management = mock(Management.class);
- given(commandService.getManagement()).willReturn(management);
+ given(commandService.getProperty(RestrictionSettings.ENABLE_PASSWORD_CONFIRMATION)).willReturn(true);
+ ExecutableCommand command = new RegisterCommand();
// when
- command.executeCommand(sender, Collections.singletonList("password"), commandService);
+ command.executeCommand(sender, Collections.singletonList("arrrr"), commandService);
// then
- verify(management).performRegister(sender, "password", "");
+ verify(commandService).send(sender, MessageKey.USAGE_REGISTER);
+ verifyZeroInteractions(management);
}
+ @Test
+ public void shouldReturnErrorForMissingEmailConfirmation() {
+ // given
+ given(commandService.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)).willReturn(true);
+ given(commandService.getProperty(RegistrationSettings.ENABLE_CONFIRM_EMAIL)).willReturn(true);
+ ExecutableCommand command = new RegisterCommand();
+
+ // when
+ command.executeCommand(sender, Collections.singletonList("test@example.org"), commandService);
+
+ // then
+ verify(commandService).send(sender, MessageKey.USAGE_REGISTER);
+ verifyZeroInteractions(management);
+ }
+
+ @Test
+ public void shouldThrowErrorForMissingEmailConfiguration() {
+ // given
+ given(commandService.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)).willReturn(true);
+ given(commandService.getProperty(RegistrationSettings.ENABLE_CONFIRM_EMAIL)).willReturn(false);
+ given(commandService.getProperty(EmailSettings.MAIL_ACCOUNT)).willReturn("");
+ ExecutableCommand command = new RegisterCommand();
+
+ // when
+ command.executeCommand(sender, Collections.singletonList("myMail@example.tld"), commandService);
+
+ // then
+ verify(sender).sendMessage(argThat(containsString("no email address")));
+ verifyZeroInteractions(management);
+ }
+
+ @Test
+ public void shouldRejectInvalidEmail() {
+ // given
+ String playerMail = "player@example.org";
+ given(commandService.validateEmail(playerMail)).willReturn(false);
+
+ given(commandService.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)).willReturn(true);
+ given(commandService.getProperty(RegistrationSettings.ENABLE_CONFIRM_EMAIL)).willReturn(true);
+ given(commandService.getProperty(EmailSettings.MAIL_ACCOUNT)).willReturn("server@example.com");
+
+ ExecutableCommand command = new RegisterCommand();
+
+ // when
+ command.executeCommand(sender, Arrays.asList(playerMail, playerMail), commandService);
+
+ // then
+ verify(commandService).validateEmail(playerMail);
+ verify(commandService).send(sender, MessageKey.INVALID_EMAIL);
+ verifyZeroInteractions(management);
+ }
+
+ @Test
+ public void shouldRejectInvalidEmailConfirmation() {
+ // given
+ String playerMail = "bobber@bobby.org";
+ given(commandService.validateEmail(playerMail)).willReturn(true);
+
+ given(commandService.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)).willReturn(true);
+ given(commandService.getProperty(RegistrationSettings.ENABLE_CONFIRM_EMAIL)).willReturn(true);
+ given(commandService.getProperty(EmailSettings.MAIL_ACCOUNT)).willReturn("server@example.com");
+
+ ExecutableCommand command = new RegisterCommand();
+
+ // when
+ command.executeCommand(sender, Arrays.asList(playerMail, "invalid"), commandService);
+
+ // then
+ verify(commandService).send(sender, MessageKey.USAGE_REGISTER);
+ verifyZeroInteractions(management);
+ }
+
+ @Test
+ public void shouldPerformEmailRegistration() {
+ // given
+ String playerMail = "asfd@lakjgre.lds";
+ given(commandService.validateEmail(playerMail)).willReturn(true);
+ int passLength = 7;
+ given(commandService.getProperty(EmailSettings.RECOVERY_PASSWORD_LENGTH)).willReturn(passLength);
+
+ given(commandService.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)).willReturn(true);
+ given(commandService.getProperty(RegistrationSettings.ENABLE_CONFIRM_EMAIL)).willReturn(true);
+ given(commandService.getProperty(EmailSettings.MAIL_ACCOUNT)).willReturn("server@example.com");
+ ExecutableCommand command = new RegisterCommand();
+
+ // when
+ command.executeCommand(sender, Arrays.asList(playerMail, playerMail), commandService);
+
+ // then
+ verify(commandService).validateEmail(playerMail);
+ verify(management).performRegister(eq(sender), argThat(stringWithLength(passLength)), eq(playerMail));
+ }
+
+ @Test
+ public void shouldRejectInvalidPasswordConfirmation() {
+ // given
+ given(commandService.getProperty(RestrictionSettings.ENABLE_PASSWORD_CONFIRMATION)).willReturn(true);
+ ExecutableCommand command = new RegisterCommand();
+
+ // when
+ command.executeCommand(sender, Arrays.asList("myPass", "mypass"), commandService);
+
+ // then
+ verify(commandService).send(sender, MessageKey.PASSWORD_MATCH_ERROR);
+ verifyZeroInteractions(management);
+ }
+
+ @Test
+ public void shouldPerformPasswordValidation() {
+ // given
+ ExecutableCommand command = new RegisterCommand();
+
+ // when
+ command.executeCommand(sender, Collections.singletonList("myPass"), commandService);
+
+ // then
+ verify(management).performRegister(sender, "myPass", "");
+ }
+
+
+ private static TypeSafeMatcher stringWithLength(final int length) {
+ return new TypeSafeMatcher() {
+ @Override
+ protected boolean matchesSafely(String item) {
+ return item != null && item.length() == length;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("String with length " + length);
+ }
+ };
+ }
}
diff --git a/src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java b/src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java
index 6568a773..3ec47a4f 100644
--- a/src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java
+++ b/src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java
@@ -6,7 +6,6 @@ import fr.xephi.authme.command.FoundResultStatus;
import fr.xephi.authme.command.TestCommandsUtil;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.permission.PlayerPermission;
-import fr.xephi.authme.util.WrapperMock;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.junit.Before;
@@ -47,7 +46,6 @@ public class HelpProviderTest {
@BeforeClass
public static void setUpCommands() {
- WrapperMock.createInstance();
commands = TestCommandsUtil.generateCommands();
}
diff --git a/src/test/java/fr/xephi/authme/converter/ForceFlatToSqliteTest.java b/src/test/java/fr/xephi/authme/converter/ForceFlatToSqliteTest.java
index 17d4fb06..6f6082ce 100644
--- a/src/test/java/fr/xephi/authme/converter/ForceFlatToSqliteTest.java
+++ b/src/test/java/fr/xephi/authme/converter/ForceFlatToSqliteTest.java
@@ -1,7 +1,6 @@
package fr.xephi.authme.converter;
import com.google.common.io.Files;
-import fr.xephi.authme.ConsoleLoggerTestInitializer;
import fr.xephi.authme.TestHelper;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource;
@@ -37,7 +36,7 @@ public class ForceFlatToSqliteTest {
@BeforeClass
public static void setup() {
- ConsoleLoggerTestInitializer.setupLogger();
+ TestHelper.setupLogger();
}
@Before
diff --git a/src/test/java/fr/xephi/authme/datasource/AbstractDataSourceIntegrationTest.java b/src/test/java/fr/xephi/authme/datasource/AbstractDataSourceIntegrationTest.java
index 077209f4..30f3484e 100644
--- a/src/test/java/fr/xephi/authme/datasource/AbstractDataSourceIntegrationTest.java
+++ b/src/test/java/fr/xephi/authme/datasource/AbstractDataSourceIntegrationTest.java
@@ -22,7 +22,11 @@ import static org.junit.Assume.assumeThat;
*/
public abstract class AbstractDataSourceIntegrationTest {
- protected abstract DataSource getDataSource();
+ protected DataSource getDataSource() {
+ return getDataSource("salt");
+ }
+
+ protected abstract DataSource getDataSource(String saltColumn);
@Test
public void shouldReturnIfAuthIsAvailableOrNot() {
@@ -56,6 +60,22 @@ public abstract class AbstractDataSourceIntegrationTest {
assertThat(userPassword, equalToHash("b28c32f624a4eb161d6adc9acb5bfc5b", "f750ba32"));
}
+ @Test
+ public void shouldReturnPasswordWithEmptySaltColumn() {
+ // given
+ DataSource dataSource = getDataSource("");
+
+ // when
+ HashedPassword bobbyPassword = dataSource.getPassword("bobby");
+ HashedPassword invalidPassword = dataSource.getPassword("doesNotExist");
+ HashedPassword userPassword = dataSource.getPassword("user");
+
+ // then
+ assertThat(bobbyPassword, equalToHash("$SHA$11aa0706173d7272$dbba966"));
+ assertThat(invalidPassword, nullValue());
+ assertThat(userPassword, equalToHash("b28c32f624a4eb161d6adc9acb5bfc5b"));
+ }
+
@Test
public void shouldGetAuth() {
// given
@@ -80,22 +100,6 @@ public abstract class AbstractDataSourceIntegrationTest {
assertThat(userAuth.getPassword(), equalToHash("b28c32f624a4eb161d6adc9acb5bfc5b", "f750ba32"));
}
- @Test
- public void shouldFindIfEmailExists() {
- // given
- DataSource dataSource = getDataSource();
-
- // when
- boolean isUserMailPresent = dataSource.isEmailStored("user@example.org");
- boolean isUserMailPresentCaseInsensitive = dataSource.isEmailStored("user@example.ORG");
- boolean isInvalidMailPresent = dataSource.isEmailStored("not-in-database@example.com");
-
- // then
- assertThat(isUserMailPresent, equalTo(true));
- assertThat(isUserMailPresentCaseInsensitive, equalTo(true));
- assertThat(isInvalidMailPresent, equalTo(false));
- }
-
@Test
public void shouldCountAuthsByEmail() {
// given
@@ -149,6 +153,21 @@ public abstract class AbstractDataSourceIntegrationTest {
assertThat(dataSource.getPassword("user"), equalToHash(newHash));
}
+ @Test
+ public void shouldUpdatePasswordWithNoSalt() {
+ // given
+ DataSource dataSource = getDataSource("");
+ HashedPassword newHash = new HashedPassword("new_hash", "1241");
+
+ // when
+ boolean response1 = dataSource.updatePassword("user", newHash);
+ boolean response2 = dataSource.updatePassword("non-existent-name", new HashedPassword("asdfasdf", "a1f34ec"));
+
+ // then
+ assertThat(response1 && response2, equalTo(true));
+ assertThat(dataSource.getPassword("user"), equalToHash("new_hash"));
+ }
+
@Test
public void shouldRemovePlayerAuth() {
// given
diff --git a/src/test/java/fr/xephi/authme/datasource/AbstractResourceClosingTest.java b/src/test/java/fr/xephi/authme/datasource/AbstractResourceClosingTest.java
index 69bb0512..75908e3e 100644
--- a/src/test/java/fr/xephi/authme/datasource/AbstractResourceClosingTest.java
+++ b/src/test/java/fr/xephi/authme/datasource/AbstractResourceClosingTest.java
@@ -4,7 +4,7 @@ import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
-import fr.xephi.authme.ConsoleLoggerTestInitializer;
+import fr.xephi.authme.TestHelper;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.security.crypts.HashedPassword;
@@ -107,7 +107,7 @@ public abstract class AbstractResourceClosingTest {
return ((Property) invocation.getArguments()[0]).getDefaultValue();
}
});
- ConsoleLoggerTestInitializer.setupLogger();
+ TestHelper.setupLogger();
}
/** Initialize the dataSource implementation to test based on a mock connection. */
diff --git a/src/test/java/fr/xephi/authme/datasource/FlatFileIntegrationTest.java b/src/test/java/fr/xephi/authme/datasource/FlatFileIntegrationTest.java
index 154511c2..0c0ab8e1 100644
--- a/src/test/java/fr/xephi/authme/datasource/FlatFileIntegrationTest.java
+++ b/src/test/java/fr/xephi/authme/datasource/FlatFileIntegrationTest.java
@@ -16,8 +16,8 @@ import java.util.List;
import static fr.xephi.authme.AuthMeMatchers.equalToHash;
import static fr.xephi.authme.AuthMeMatchers.hasAuthBasicData;
import static fr.xephi.authme.AuthMeMatchers.hasAuthLocation;
-import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.assertThat;
diff --git a/src/test/java/fr/xephi/authme/datasource/MySqlIntegrationTest.java b/src/test/java/fr/xephi/authme/datasource/MySqlIntegrationTest.java
index 81e2e122..ec90dab0 100644
--- a/src/test/java/fr/xephi/authme/datasource/MySqlIntegrationTest.java
+++ b/src/test/java/fr/xephi/authme/datasource/MySqlIntegrationTest.java
@@ -2,7 +2,6 @@ package fr.xephi.authme.datasource;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
-import fr.xephi.authme.ConsoleLoggerTestInitializer;
import fr.xephi.authme.TestHelper;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.domain.Property;
@@ -53,8 +52,7 @@ public class MySqlIntegrationTest extends AbstractDataSourceIntegrationTest {
});
set(DatabaseSettings.MYSQL_DATABASE, "h2_test");
set(DatabaseSettings.MYSQL_TABLE, "authme");
- set(DatabaseSettings.MYSQL_COL_SALT, "salt");
- ConsoleLoggerTestInitializer.setupLogger();
+ TestHelper.setupLogger();
Path sqlInitFile = TestHelper.getJarPath("/datasource-integration/sql-initialize.sql");
sqlInitialize = new String(Files.readAllBytes(sqlInitFile));
@@ -80,7 +78,8 @@ public class MySqlIntegrationTest extends AbstractDataSourceIntegrationTest {
}
@Override
- protected DataSource getDataSource() {
+ protected DataSource getDataSource(String saltColumn) {
+ when(settings.getProperty(DatabaseSettings.MYSQL_COL_SALT)).thenReturn(saltColumn);
return new MySQL(settings, hikariSource);
}
diff --git a/src/test/java/fr/xephi/authme/datasource/SQLiteIntegrationTest.java b/src/test/java/fr/xephi/authme/datasource/SQLiteIntegrationTest.java
index 2ef4e15a..3cfe9eb2 100644
--- a/src/test/java/fr/xephi/authme/datasource/SQLiteIntegrationTest.java
+++ b/src/test/java/fr/xephi/authme/datasource/SQLiteIntegrationTest.java
@@ -1,6 +1,5 @@
package fr.xephi.authme.datasource;
-import fr.xephi.authme.ConsoleLoggerTestInitializer;
import fr.xephi.authme.TestHelper;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.domain.Property;
@@ -52,8 +51,7 @@ public class SQLiteIntegrationTest extends AbstractDataSourceIntegrationTest {
});
set(DatabaseSettings.MYSQL_DATABASE, "sqlite-test");
set(DatabaseSettings.MYSQL_TABLE, "authme");
- set(DatabaseSettings.MYSQL_COL_SALT, "salt");
- ConsoleLoggerTestInitializer.setupLogger();
+ TestHelper.setupLogger();
Path sqlInitFile = TestHelper.getJarPath("/datasource-integration/sql-initialize.sql");
// Note ljacqu 20160221: It appears that we can only run one statement per Statement.execute() so we split
@@ -75,7 +73,8 @@ public class SQLiteIntegrationTest extends AbstractDataSourceIntegrationTest {
}
@Override
- protected DataSource getDataSource() {
+ protected DataSource getDataSource(String saltColumn) {
+ when(settings.getProperty(DatabaseSettings.MYSQL_COL_SALT)).thenReturn(saltColumn);
return new SQLite(settings, con);
}
diff --git a/src/test/java/fr/xephi/authme/events/EventsConsistencyTest.java b/src/test/java/fr/xephi/authme/events/EventsConsistencyTest.java
new file mode 100644
index 00000000..d7ba5f74
--- /dev/null
+++ b/src/test/java/fr/xephi/authme/events/EventsConsistencyTest.java
@@ -0,0 +1,94 @@
+package fr.xephi.authme.events;
+
+import org.apache.commons.lang.reflect.MethodUtils;
+import org.bukkit.event.Event;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Checks the consistency of the AuthMe event classes.
+ */
+public class EventsConsistencyTest {
+
+ private static final String SRC_FOLDER = "src/main/java/";
+ private static final String EVENTS_FOLDER = SRC_FOLDER + "/fr/xephi/authme/events/";
+ private static List> classes;
+
+ @BeforeClass
+ public static void scanEventClasses() {
+ File eventsFolder = new File(EVENTS_FOLDER);
+ File[] filesInFolder = eventsFolder.listFiles();
+ if (filesInFolder == null || filesInFolder.length == 0) {
+ throw new IllegalStateException("Could not read folder '" + EVENTS_FOLDER + "'. Is it correct?");
+ }
+
+ classes = new ArrayList<>();
+ for (File file : filesInFolder) {
+ Class extends Event> clazz = getEventClassFromFile(file);
+ if (clazz != null) {
+ classes.add(clazz);
+ }
+ }
+ if (classes.isEmpty()) {
+ throw new IllegalStateException("Did not find any AuthMe event classes. Is the folder correct?");
+ }
+ }
+
+ @Test
+ public void shouldExtendFromCustomEvent() {
+ for (Class> clazz : classes) {
+ assertThat("Class " + clazz.getSimpleName() + " is subtype of CustomEvent",
+ CustomEvent.class.isAssignableFrom(clazz), equalTo(true));
+ }
+ }
+
+ /**
+ * Bukkit requires a static getHandlerList() method on all event classes, see {@link Event}.
+ * This test checks that such a method is present, and that it is absent if the class
+ * is not instantiable (abstract class).
+ */
+ @Test
+ public void shouldHaveStaticEventHandlerMethod() {
+ for (Class> clazz : classes) {
+ Method handlerListMethod = MethodUtils.getAccessibleMethod(clazz, "getHandlerList", new Class>[]{});
+ if (canBeInstantiated(clazz)) {
+ assertThat("Class " + clazz.getSimpleName() + " has static method getHandlerList()",
+ handlerListMethod != null && Modifier.isStatic(handlerListMethod.getModifiers()), equalTo(true));
+ } else {
+ assertThat("Non-instantiable class " + clazz.getSimpleName() + " does not have static getHandlerList()",
+ handlerListMethod, nullValue());
+ }
+ }
+ }
+
+ private static boolean canBeInstantiated(Class> clazz) {
+ return !clazz.isInterface() && !clazz.isEnum() && !Modifier.isAbstract(clazz.getModifiers());
+ }
+
+ private static Class extends Event> getEventClassFromFile(File file) {
+ String fileName = file.getPath();
+ String className = fileName
+ .substring(SRC_FOLDER.length(), fileName.length() - ".java".length())
+ .replace(File.separator, ".");
+ try {
+ Class> clazz = EventsConsistencyTest.class.getClassLoader().loadClass(className);
+ if (Event.class.isAssignableFrom(clazz)) {
+ return (Class extends Event>) clazz;
+ }
+ return null;
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException("Could not load class '" + className + "'", e);
+ }
+ }
+
+}
diff --git a/src/test/java/fr/xephi/authme/hooks/PluginHooksTest.java b/src/test/java/fr/xephi/authme/hooks/PluginHooksTest.java
index be12afce..e8475d9c 100644
--- a/src/test/java/fr/xephi/authme/hooks/PluginHooksTest.java
+++ b/src/test/java/fr/xephi/authme/hooks/PluginHooksTest.java
@@ -2,8 +2,8 @@ package fr.xephi.authme.hooks;
import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.User;
-import fr.xephi.authme.ConsoleLoggerTestInitializer;
import fr.xephi.authme.ReflectionTestUtils;
+import fr.xephi.authme.TestHelper;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
@@ -29,7 +29,7 @@ public class PluginHooksTest {
@BeforeClass
public static void setLogger() {
- ConsoleLoggerTestInitializer.setupLogger();
+ TestHelper.setupLogger();
}
@Test
diff --git a/src/test/java/fr/xephi/authme/output/MessagesIntegrationTest.java b/src/test/java/fr/xephi/authme/output/MessagesIntegrationTest.java
index 39955365..cd858ad8 100644
--- a/src/test/java/fr/xephi/authme/output/MessagesIntegrationTest.java
+++ b/src/test/java/fr/xephi/authme/output/MessagesIntegrationTest.java
@@ -1,9 +1,7 @@
package fr.xephi.authme.output;
import fr.xephi.authme.ConsoleLogger;
-import fr.xephi.authme.ConsoleLoggerTestInitializer;
import fr.xephi.authme.TestHelper;
-import fr.xephi.authme.util.WrapperMock;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.junit.Before;
@@ -16,11 +14,15 @@ import java.io.File;
import java.util.logging.Logger;
import static org.hamcrest.Matchers.arrayWithSize;
+import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assume.assumeThat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -35,8 +37,7 @@ public class MessagesIntegrationTest {
@BeforeClass
public static void setup() {
- WrapperMock.createInstance();
- ConsoleLoggerTestInitializer.setupLogger();
+ TestHelper.setupLogger();
}
/**
@@ -62,7 +63,7 @@ public class MessagesIntegrationTest {
String[] message = messages.retrieve(key);
// then
- String[] lines = new String[]{"This test message", "includes", "some new lines"};
+ String[] lines = new String[]{"We've got", "new lines", "and ' apostrophes"};
assertThat(message, equalTo(lines));
}
@@ -75,7 +76,7 @@ public class MessagesIntegrationTest {
String message = messages.retrieveSingle(key);
// then
- assertThat(message, equalTo("This test message\nincludes\nsome new lines"));
+ assertThat(message, equalTo("We've got\nnew lines\nand ' apostrophes"));
}
@Test
@@ -92,16 +93,16 @@ public class MessagesIntegrationTest {
}
@Test
- public void shouldRetainApostrophes() {
+ public void shouldNotSendEmptyMessage() {
// given
- MessageKey key = MessageKey.NOT_LOGGED_IN;
+ MessageKey key = MessageKey.EMAIL_ALREADY_USED_ERROR;
+ CommandSender sender = mock(CommandSender.class);
// when
- String[] message = messages.retrieve(key);
+ messages.send(sender, key);
// then
- assertThat(message, arrayWithSize(1));
- assertThat(message[0], equalTo("Apostrophes ' should be loaded correctly, don't you think?"));
+ verify(sender, never()).sendMessage(anyString());
}
@Test
@@ -127,10 +128,10 @@ public class MessagesIntegrationTest {
messages.send(player, key);
// then
- String[] lines = new String[]{"This test message", "includes", "some new lines"};
- for (String line : lines) {
- verify(player).sendMessage(line);
- }
+ String[] lines = new String[]{"We've got", "new lines", "and ' apostrophes"};
+ ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
+ verify(player, times(3)).sendMessage(captor.capture());
+ assertThat(captor.getAllValues(), contains(lines));
}
@Test
@@ -143,14 +144,11 @@ public class MessagesIntegrationTest {
messages.send(sender, key, "1234");
// then
- ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
- verify(sender, times(1)).sendMessage(captor.capture());
- String message = captor.getValue();
- assertThat(message, equalTo("Use /captcha 1234 to solve the captcha"));
+ verify(sender, times(1)).sendMessage("Use /captcha 1234 to solve the captcha");
}
@Test
- public void shouldNotThrowForKeyWithNoTagReplacements() {
+ public void shouldNotLogErrorForKeyWithNoTagReplacements() {
// given
MessageKey key = MessageKey.CAPTCHA_WRONG_ERROR;
CommandSender sender = mock(CommandSender.class);
@@ -159,10 +157,7 @@ public class MessagesIntegrationTest {
messages.send(sender, key);
// then
- ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
- verify(sender, times(1)).sendMessage(captor.capture());
- String message = captor.getValue();
- assertThat(message, equalTo("Use /captcha THE_CAPTCHA to solve the captcha"));
+ verify(sender).sendMessage(argThat(equalTo("Use /captcha THE_CAPTCHA to solve the captcha")));
}
@Test
@@ -176,13 +171,11 @@ public class MessagesIntegrationTest {
messages.send(mock(CommandSender.class), key, "rep", "rep2");
// then
- ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
- verify(logger).warning(captor.capture());
- assertThat(captor.getValue(), containsString("Invalid number of replacements"));
+ verify(logger).warning(argThat(containsString("Invalid number of replacements")));
}
@Test
- public void shouldThrowForReplacementsOnKeyWithNoTags() {
+ public void shouldSendErrorForReplacementsOnKeyWithNoTags() {
// given
Logger logger = mock(Logger.class);
ConsoleLogger.setLogger(logger);
@@ -192,9 +185,7 @@ public class MessagesIntegrationTest {
messages.send(mock(CommandSender.class), key, "Replacement");
// then
- ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
- verify(logger).warning(captor.capture());
- assertThat(captor.getValue(), containsString("Invalid number of replacements"));
+ verify(logger).warning(argThat(containsString("Invalid number of replacements")));
}
@Test
diff --git a/src/test/java/fr/xephi/authme/process/ProcessServiceTest.java b/src/test/java/fr/xephi/authme/process/ProcessServiceTest.java
index da3c2f8d..ab935d02 100644
--- a/src/test/java/fr/xephi/authme/process/ProcessServiceTest.java
+++ b/src/test/java/fr/xephi/authme/process/ProcessServiceTest.java
@@ -1,7 +1,6 @@
package fr.xephi.authme.process;
import fr.xephi.authme.AuthMe;
-import fr.xephi.authme.cache.IpAddressManager;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.hooks.PluginHooks;
import fr.xephi.authme.output.MessageKey;
@@ -11,12 +10,14 @@ import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.properties.SecuritySettings;
+import fr.xephi.authme.util.BukkitService;
+import fr.xephi.authme.util.ValidationService;
import org.bukkit.command.CommandSender;
import org.junit.Before;
import org.junit.Test;
-
-import java.util.HashMap;
-import java.util.Map;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
@@ -27,23 +28,38 @@ import static org.mockito.Mockito.verify;
/**
* Test for {@link ProcessService}.
*/
+@RunWith(MockitoJUnitRunner.class)
public class ProcessServiceTest {
private ProcessService processService;
- private Map, Object> mocks;
+ @Mock
+ private ValidationService validationService;
+ @Mock
+ private NewSetting settings;
+ @Mock
+ private Messages messages;
+ @Mock
+ private PasswordSecurity passwordSecurity;
+ @Mock
+ private AuthMe authMe;
+ @Mock
+ private DataSource dataSource;
+ @Mock
+ private SpawnLoader spawnLoader;
+ @Mock
+ private PluginHooks pluginHooks;
+ @Mock
+ private BukkitService bukkitService;
@Before
public void setUpService() {
- mocks = new HashMap<>();
- processService = new ProcessService(newMock(NewSetting.class), newMock(Messages.class), newMock(AuthMe.class),
- newMock(DataSource.class), newMock(IpAddressManager.class), newMock(PasswordSecurity.class),
- newMock(PluginHooks.class), newMock(SpawnLoader.class));
+ processService = new ProcessService(settings, messages, authMe, dataSource, passwordSecurity,
+ pluginHooks, spawnLoader, validationService, bukkitService);
}
@Test
public void shouldGetProperty() {
// given
- NewSetting settings = getMock(NewSetting.class);
given(settings.getProperty(SecuritySettings.CAPTCHA_LENGTH)).willReturn(8);
// when
@@ -57,16 +73,15 @@ public class ProcessServiceTest {
@Test
public void shouldReturnSettings() {
// given/when
- NewSetting settings = processService.getSettings();
+ NewSetting result = processService.getSettings();
// then
- assertThat(settings, equalTo(getMock(NewSetting.class)));
+ assertThat(result, equalTo(settings));
}
@Test
public void shouldSendMessageToPlayer() {
// given
- Messages messages = getMock(Messages.class);
CommandSender sender = mock(CommandSender.class);
MessageKey key = MessageKey.ACCOUNT_NOT_ACTIVATED;
@@ -80,7 +95,6 @@ public class ProcessServiceTest {
@Test
public void shouldSendMessageWithReplacements() {
// given
- Messages messages = getMock(Messages.class);
CommandSender sender = mock(CommandSender.class);
MessageKey key = MessageKey.ACCOUNT_NOT_ACTIVATED;
String[] replacements = new String[]{"test", "toast"};
@@ -95,7 +109,6 @@ public class ProcessServiceTest {
@Test
public void shouldRetrieveMessage() {
// given
- Messages messages = getMock(Messages.class);
MessageKey key = MessageKey.ACCOUNT_NOT_ACTIVATED;
String[] lines = new String[]{"First message line", "second line"};
given(messages.retrieve(key)).willReturn(lines);
@@ -111,7 +124,6 @@ public class ProcessServiceTest {
@Test
public void shouldRetrieveSingleMessage() {
// given
- Messages messages = getMock(Messages.class);
MessageKey key = MessageKey.ACCOUNT_NOT_ACTIVATED;
String text = "Test text";
given(messages.retrieveSingle(key)).willReturn(text);
@@ -127,52 +139,42 @@ public class ProcessServiceTest {
@Test
public void shouldReturnAuthMeInstance() {
// given / when
- AuthMe authMe = processService.getAuthMe();
+ AuthMe result = processService.getAuthMe();
// then
- assertThat(authMe, equalTo(getMock(AuthMe.class)));
+ assertThat(result, equalTo(authMe));
}
@Test
public void shouldReturnPluginHooks() {
// given / when
- PluginHooks pluginHooks = processService.getPluginHooks();
+ PluginHooks result = processService.getPluginHooks();
// then
- assertThat(pluginHooks, equalTo(getMock(PluginHooks.class)));
- }
-
- @Test
- public void shouldReturnIpAddressManager() {
- // given / when
- IpAddressManager ipAddressManager = processService.getIpAddressManager();
-
- // then
- assertThat(ipAddressManager, equalTo(getMock(IpAddressManager.class)));
+ assertThat(result, equalTo(pluginHooks));
}
@Test
public void shouldReturnSpawnLoader() {
// given / when
- SpawnLoader spawnLoader = processService.getSpawnLoader();
+ SpawnLoader result = processService.getSpawnLoader();
// then
- assertThat(spawnLoader, equalTo(getMock(SpawnLoader.class)));
+ assertThat(result, equalTo(spawnLoader));
}
@Test
public void shouldReturnDatasource() {
// given / when
- DataSource dataSource = processService.getDataSource();
+ DataSource result = processService.getDataSource();
// then
- assertThat(dataSource, equalTo(getMock(DataSource.class)));
+ assertThat(result, equalTo(dataSource));
}
@Test
public void shouldComputeHash() {
// given
- PasswordSecurity passwordSecurity = getMock(PasswordSecurity.class);
String password = "test123";
String username = "Username";
HashedPassword hashedPassword = new HashedPassword("hashedResult", "salt12342");
@@ -186,17 +188,48 @@ public class ProcessServiceTest {
verify(passwordSecurity).computeHash(password, username);
}
- private T newMock(Class clazz) {
- T mock = mock(clazz);
- mocks.put(clazz, mock);
- return mock;
+ @Test
+ public void shouldValidatePassword() {
+ // given
+ String user = "test-user";
+ String password = "passw0rd";
+ given(validationService.validatePassword(password, user)).willReturn(MessageKey.PASSWORD_MATCH_ERROR);
+
+ // when
+ MessageKey result = processService.validatePassword(password, user);
+
+ // then
+ assertThat(result, equalTo(MessageKey.PASSWORD_MATCH_ERROR));
+ verify(validationService).validatePassword(password, user);
}
- private