From 45f604534de6b121d16650816523bdfa7b496d7e Mon Sep 17 00:00:00 2001 From: DNx5 Date: Sat, 12 Dec 2015 19:16:52 +0700 Subject: [PATCH 01/17] Use Guava cache for caching PlayerAuth object. --- src/main/java/fr/xephi/authme/AuthMe.java | 2 +- .../xephi/authme/cache/auth/PlayerAuth.java | 8 +- .../xephi/authme/cache/auth/PlayerCache.java | 5 +- .../executable/authme/AccountsCommand.java | 45 +-- .../executable/authme/ResetNameCommand.java | 3 +- .../executable/authme/SetEmailCommand.java | 52 +-- .../authme/datasource/CacheDataSource.java | 361 +++++++----------- .../xephi/authme/datasource/DataSource.java | 4 +- .../fr/xephi/authme/datasource/FlatFile.java | 14 +- .../fr/xephi/authme/datasource/MySQL.java | 9 +- .../xephi/authme/hooks/BungeeCordMessage.java | 43 ++- 11 files changed, 229 insertions(+), 317 deletions(-) diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java index 2f6bf18f..d49abed8 100644 --- a/src/main/java/fr/xephi/authme/AuthMe.java +++ b/src/main/java/fr/xephi/authme/AuthMe.java @@ -603,7 +603,7 @@ public class AuthMe extends JavaPlugin { } if (Settings.isCachingEnabled) { - database = new CacheDataSource(this, database); + database = new CacheDataSource(database); } if (Settings.getDataSource == DataSource.DataSourceType.FILE) { diff --git a/src/main/java/fr/xephi/authme/cache/auth/PlayerAuth.java b/src/main/java/fr/xephi/authme/cache/auth/PlayerAuth.java index 32c4f7fd..c501e8eb 100644 --- a/src/main/java/fr/xephi/authme/cache/auth/PlayerAuth.java +++ b/src/main/java/fr/xephi/authme/cache/auth/PlayerAuth.java @@ -194,7 +194,7 @@ public class PlayerAuth { this.setHash(auth.getHash()); this.setIp(auth.getIp()); this.setLastLogin(auth.getLastLogin()); - this.setName(auth.getNickname()); + this.setNickname(auth.getNickname()); this.setQuitLocX(auth.getQuitLocX()); this.setQuitLocY(auth.getQuitLocY()); this.setQuitLocZ(auth.getQuitLocZ()); @@ -204,11 +204,11 @@ public class PlayerAuth { } /** - * Method setName. + * Method setNickname. * * @param nickname String */ - public void setName(String nickname) { + public void setNickname(String nickname) { this.nickname = nickname.toLowerCase(); } @@ -522,7 +522,7 @@ public class PlayerAuth { public PlayerAuth build() { return new PlayerAuth( - checkNotNull(name).toLowerCase(), + checkNotNull(name), nullToEmpty(hash), nullToEmpty(salt), groupId, diff --git a/src/main/java/fr/xephi/authme/cache/auth/PlayerCache.java b/src/main/java/fr/xephi/authme/cache/auth/PlayerCache.java index 4f9d2187..17cdca55 100644 --- a/src/main/java/fr/xephi/authme/cache/auth/PlayerCache.java +++ b/src/main/java/fr/xephi/authme/cache/auth/PlayerCache.java @@ -40,8 +40,7 @@ public class PlayerCache { * @param auth PlayerAuth */ public void updatePlayer(PlayerAuth auth) { - cache.remove(auth.getNickname().toLowerCase()); - cache.put(auth.getNickname().toLowerCase(), auth); + cache.put(auth.getNickname(), auth); } /** @@ -87,7 +86,7 @@ public class PlayerCache { /** * Method getCache. * - * @return ConcurrentHashMap + * @return ConcurrentHashMap */ public ConcurrentHashMap getCache() { return this.cache; diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java index ba34491a..2c629ca2 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java @@ -1,13 +1,11 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; -import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import java.util.List; @@ -26,30 +24,24 @@ public class AccountsCommand extends ExecutableCommand { // Get the player query String playerQuery = sender.getName(); - if (commandArguments.getCount() >= 1) + if (commandArguments.getCount() >= 1) { playerQuery = commandArguments.get(0); + } final String playerQueryFinal = playerQuery; // Command logic - if (!playerQuery.contains(".")) { - Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { - + if (!playerQueryFinal.contains(".")) { + plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() { @Override public void run() { - PlayerAuth auth; - StringBuilder message = new StringBuilder("[AuthMe] "); - try { - auth = plugin.database.getAuth(playerQueryFinal.toLowerCase()); - } catch (NullPointerException npe) { - m.send(sender, MessageKey.UNKNOWN_USER); - return; - } + PlayerAuth auth = plugin.database.getAuth(playerQueryFinal.toLowerCase()); if (auth == null) { m.send(sender, MessageKey.UNKNOWN_USER); return; } + StringBuilder message = new StringBuilder("[AuthMe] "); List accountList = plugin.database.getAllAuthsByName(auth); - if (accountList == null || accountList.isEmpty()) { + if (accountList.isEmpty()) { m.send(sender, MessageKey.USER_NOT_REGISTERED); return; } @@ -67,28 +59,20 @@ public class AccountsCommand extends ExecutableCommand { message.append('.'); } } - sender.sendMessage("[AuthMe] " + playerQueryFinal + " has " + String.valueOf(accountList.size()) + " accounts"); + sender.sendMessage("[AuthMe] " + playerQueryFinal + " has " + + String.valueOf(accountList.size()) + " accounts."); sender.sendMessage(message.toString()); } }); return true; } else { - Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() { + plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() { @Override public void run() { - List accountList; - try { - accountList = plugin.database.getAllAuthsByIp(playerQueryFinal); - } catch (Exception e) { - ConsoleLogger.showError(e.getMessage()); - ConsoleLogger.writeStackTrace(e); - m.send(sender, MessageKey.ERROR); - return; - } - + List accountList = plugin.database.getAllAuthsByIp(playerQueryFinal); StringBuilder message = new StringBuilder("[AuthMe] "); - if (accountList == null || accountList.isEmpty()) { - sender.sendMessage("[AuthMe] This IP does not exist in the database"); + if (accountList.isEmpty()) { + sender.sendMessage("[AuthMe] This IP does not exist in the database."); return; } if (accountList.size() == 1) { @@ -105,7 +89,8 @@ public class AccountsCommand extends ExecutableCommand { message.append('.'); } } - sender.sendMessage("[AuthMe] " + playerQueryFinal + " has " + String.valueOf(accountList.size()) + " accounts"); + sender.sendMessage("[AuthMe] " + playerQueryFinal + " has " + + String.valueOf(accountList.size()) + " accounts."); sender.sendMessage(message.toString()); } }); diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ResetNameCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ResetNameCommand.java index ae1f3840..0029104f 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/ResetNameCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/ResetNameCommand.java @@ -11,6 +11,7 @@ import java.util.List; /** */ +// TODO: remove if not used public class ResetNameCommand extends ExecutableCommand { /** @@ -28,7 +29,7 @@ public class ResetNameCommand extends ExecutableCommand { final AuthMe plugin = AuthMe.getInstance(); // Command logic - Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() { + plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() { @Override public void run() { List authentications = plugin.database.getAllAuths(); diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java index 278bf13c..813443f4 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java @@ -24,16 +24,16 @@ public class SetEmailCommand extends ExecutableCommand { * @return True if the command was executed successfully, false otherwise. */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public boolean executeCommand(final CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { // AuthMe plugin instance - AuthMe plugin = AuthMe.getInstance(); + final AuthMe plugin = AuthMe.getInstance(); // Messages instance - Messages m = plugin.getMessages(); + final Messages m = plugin.getMessages(); // Get the player name and email address - String playerName = commandArguments.get(0); - String playerEmail = commandArguments.get(1); + final String playerName = commandArguments.get(0); + final String playerEmail = commandArguments.get(1); // Validate the email address if (!Settings.isEmailCorrect(playerEmail)) { @@ -41,26 +41,34 @@ public class SetEmailCommand extends ExecutableCommand { return true; } - // Validate the user - PlayerAuth auth = plugin.database.getAuth(playerName.toLowerCase()); - if (auth == null) { - m.send(sender, MessageKey.UNKNOWN_USER); - return true; - } + plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() { + @Override + public void run() { + // Validate the user + PlayerAuth auth = plugin.database.getAuth(playerName); + if (auth == null) { + m.send(sender, MessageKey.UNKNOWN_USER); + return; + } - // Set the email address - auth.setEmail(playerEmail); - if (!plugin.database.updateEmail(auth)) { - m.send(sender, MessageKey.ERROR); - return true; - } + // Set the email address - // Update the player cache - if (PlayerCache.getInstance().getAuth(playerName.toLowerCase()) != null) - PlayerCache.getInstance().updatePlayer(auth); + auth.setEmail(playerEmail); + if (!plugin.database.updateEmail(auth)) { + m.send(sender, MessageKey.ERROR); + return; + } - // Show a status message - m.send(sender, MessageKey.EMAIL_CHANGED_SUCCESS); + // Update the player cache + if (PlayerCache.getInstance().getAuth(playerName) != null) { + PlayerCache.getInstance().updatePlayer(auth); + } + + // Show a status message + m.send(sender, MessageKey.EMAIL_CHANGED_SUCCESS); + + } + }); return true; } } diff --git a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java index 55e00246..a1f74dd3 100644 --- a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java +++ b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java @@ -1,18 +1,16 @@ package fr.xephi.authme.datasource; -import fr.xephi.authme.AuthMe; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.util.Utils; -import org.bukkit.entity.Player; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; /** */ @@ -20,37 +18,24 @@ public class CacheDataSource implements DataSource { private final DataSource source; private final ExecutorService exec; - private final ConcurrentHashMap cache = new ConcurrentHashMap<>(); + private final LoadingCache cachedAuths; /** * Constructor for CacheDataSource. * - * @param pl AuthMe * @param src DataSource */ - public CacheDataSource(final AuthMe pl, DataSource src) { + public CacheDataSource(DataSource src) { this.source = src; this.exec = Executors.newCachedThreadPool(); - pl.setCanConnect(false); - - /* - * We need to load all players in cache ... It will took more time to - * load the server, but it will be much easier to check for an - * isAuthAvailable ! - */ - exec.execute(new Runnable() { - @Override - public void run() { - for (PlayerAuth auth : source.getAllAuths()) { - cache.put(auth.getNickname().toLowerCase(), auth); - } - pl.setCanConnect(true); - } - }); - } - - public void addAuthToCache(PlayerAuth auth) { - cache.put(auth.getNickname().toLowerCase(), auth); + cachedAuths = CacheBuilder.newBuilder() + .expireAfterWrite(5, TimeUnit.MINUTES) + .build( + new CacheLoader() { + public PlayerAuth load(String key) { + return source.getAuth(key); + } + }); } /** @@ -58,11 +43,13 @@ public class CacheDataSource implements DataSource { * * @param user String * - * @return boolean * @see fr.xephi.authme.datasource.DataSource#isAuthAvailable(String) + * @return boolean + * + * @see fr.xephi.authme.datasource.DataSource#isAuthAvailable(String) */ @Override public synchronized boolean isAuthAvailable(String user) { - return cache.containsKey(user.toLowerCase()); + return getAuth(user) != null; } /** @@ -70,15 +57,14 @@ public class CacheDataSource implements DataSource { * * @param user String * - * @return PlayerAuth * @see fr.xephi.authme.datasource.DataSource#getAuth(String) + * @return PlayerAuth + * + * @see fr.xephi.authme.datasource.DataSource#getAuth(String) */ @Override public synchronized PlayerAuth getAuth(String user) { user = user.toLowerCase(); - if (cache.containsKey(user)) { - return cache.get(user); - } - return null; + return cachedAuths.getUnchecked(user); } /** @@ -86,20 +72,17 @@ public class CacheDataSource implements DataSource { * * @param auth PlayerAuth * - * @return boolean * @see fr.xephi.authme.datasource.DataSource#saveAuth(PlayerAuth) + * @return boolean + * + * @see fr.xephi.authme.datasource.DataSource#saveAuth(PlayerAuth) */ @Override - public synchronized boolean saveAuth(final PlayerAuth auth) { - cache.put(auth.getNickname(), auth); - exec.execute(new Runnable() { - @Override - public void run() { - if (!source.saveAuth(auth)) { - cache.remove(auth.getNickname()); - } - } - }); - return true; + public synchronized boolean saveAuth(PlayerAuth auth) { + boolean result = source.saveAuth(auth); + if (result) { + cachedAuths.refresh(auth.getNickname()); + } + return result; } /** @@ -107,26 +90,17 @@ public class CacheDataSource implements DataSource { * * @param auth PlayerAuth * - * @return boolean * @see fr.xephi.authme.datasource.DataSource#updatePassword(PlayerAuth) + * @return boolean + * + * @see fr.xephi.authme.datasource.DataSource#updatePassword(PlayerAuth) */ @Override - public synchronized boolean updatePassword(final PlayerAuth auth) { - if (!cache.containsKey(auth.getNickname())) { - return false; + public synchronized boolean updatePassword(PlayerAuth auth) { + boolean result = source.updatePassword(auth); + if (result) { + cachedAuths.refresh(auth.getNickname()); } - final String oldHash = cache.get(auth.getNickname()).getHash(); - cache.get(auth.getNickname()).setHash(auth.getHash()); - exec.execute(new Runnable() { - @Override - public void run() { - if (!source.updatePassword(auth)) { - if (cache.containsKey(auth.getNickname())) { - cache.get(auth.getNickname()).setHash(oldHash); - } - } - } - }); - return true; + return result; } /** @@ -134,35 +108,17 @@ public class CacheDataSource implements DataSource { * * @param auth PlayerAuth * - * @return boolean * @see fr.xephi.authme.datasource.DataSource#updateSession(PlayerAuth) + * @return boolean + * + * @see fr.xephi.authme.datasource.DataSource#updateSession(PlayerAuth) */ @Override - public boolean updateSession(final PlayerAuth auth) { - if (!cache.containsKey(auth.getNickname())) { - return false; + public boolean updateSession(PlayerAuth auth) { + boolean result = source.updateSession(auth); + if (result) { + cachedAuths.refresh(auth.getNickname()); } - PlayerAuth cachedAuth = cache.get(auth.getNickname()); - final String oldIp = cachedAuth.getIp(); - final long oldLastLogin = cachedAuth.getLastLogin(); - final String oldRealName = cachedAuth.getRealName(); - - cachedAuth.setIp(auth.getIp()); - cachedAuth.setLastLogin(auth.getLastLogin()); - cachedAuth.setRealName(auth.getRealName()); - exec.execute(new Runnable() { - @Override - public void run() { - if (!source.updateSession(auth)) { - if (cache.containsKey(auth.getNickname())) { - PlayerAuth cachedAuth = cache.get(auth.getNickname()); - cachedAuth.setIp(oldIp); - cachedAuth.setLastLogin(oldLastLogin); - cachedAuth.setRealName(oldRealName); - } - } - } - }); - return true; + return result; } /** @@ -170,38 +126,17 @@ public class CacheDataSource implements DataSource { * * @param auth PlayerAuth * - * @return boolean * @see fr.xephi.authme.datasource.DataSource#updateQuitLoc(PlayerAuth) + * @return boolean + * + * @see fr.xephi.authme.datasource.DataSource#updateQuitLoc(PlayerAuth) */ @Override public boolean updateQuitLoc(final PlayerAuth auth) { - if (!cache.containsKey(auth.getNickname())) { - return false; + boolean result = source.updateSession(auth); + if (result) { + cachedAuths.refresh(auth.getNickname()); } - final PlayerAuth cachedAuth = cache.get(auth.getNickname()); - final double oldX = cachedAuth.getQuitLocX(); - final double oldY = cachedAuth.getQuitLocY(); - final double oldZ = cachedAuth.getQuitLocZ(); - final String oldWorld = cachedAuth.getWorld(); - - cachedAuth.setQuitLocX(auth.getQuitLocX()); - cachedAuth.setQuitLocY(auth.getQuitLocY()); - cachedAuth.setQuitLocZ(auth.getQuitLocZ()); - cachedAuth.setWorld(auth.getWorld()); - exec.execute(new Runnable() { - @Override - public void run() { - if (!source.updateQuitLoc(auth)) { - if (cache.containsKey(auth.getNickname())) { - PlayerAuth cachedAuth = cache.get(auth.getNickname()); - cachedAuth.setQuitLocX(oldX); - cachedAuth.setQuitLocY(oldY); - cachedAuth.setQuitLocZ(oldZ); - cachedAuth.setWorld(oldWorld); - } - } - } - }); - return true; + return result; } /** @@ -209,17 +144,13 @@ public class CacheDataSource implements DataSource { * * @param ip String * - * @return int * @see fr.xephi.authme.datasource.DataSource#getIps(String) + * @return int + * + * @see fr.xephi.authme.datasource.DataSource#getIps(String) */ @Override public int getIps(String ip) { - int count = 0; - for (Map.Entry p : cache.entrySet()) { - if (p.getValue().getIp().equals(ip)) { - count++; - } - } - return count; + return source.getIps(ip); } /** @@ -227,15 +158,17 @@ public class CacheDataSource implements DataSource { * * @param until long * - * @return int * @see fr.xephi.authme.datasource.DataSource#purgeDatabase(long) + * @return int + * + * @see fr.xephi.authme.datasource.DataSource#purgeDatabase(long) */ @Override public int purgeDatabase(long until) { int cleared = source.purgeDatabase(until); if (cleared > 0) { - for (PlayerAuth auth : cache.values()) { - if (auth.getLastLogin() < until) { - cache.remove(auth.getNickname()); + for (PlayerAuth auth : cachedAuths.asMap().values()) { + if (auth != null && auth.getLastLogin() < until) { + cachedAuths.invalidate(auth.getNickname()); } } } @@ -247,17 +180,15 @@ public class CacheDataSource implements DataSource { * * @param until long * - * @return List * @see fr.xephi.authme.datasource.DataSource#autoPurgeDatabase(long) + * @return List + * + * @see fr.xephi.authme.datasource.DataSource#autoPurgeDatabase(long) */ @Override public List autoPurgeDatabase(long until) { List cleared = source.autoPurgeDatabase(until); - if (cleared.size() > 0) { - for (PlayerAuth auth : cache.values()) { - if (auth.getLastLogin() < until) { - cache.remove(auth.getNickname()); - } - } + for (String name : cleared) { + cachedAuths.invalidate(name); } return cleared; } @@ -265,24 +196,20 @@ public class CacheDataSource implements DataSource { /** * Method removeAuth. * - * @param username String + * @param name String * - * @return boolean * @see fr.xephi.authme.datasource.DataSource#removeAuth(String) + * @return boolean + * + * @see fr.xephi.authme.datasource.DataSource#removeAuth(String) */ @Override - public synchronized boolean removeAuth(String username) { - final String user = username.toLowerCase(); - final PlayerAuth auth = cache.get(user); - cache.remove(user); - exec.execute(new Runnable() { - @Override - public void run() { - if (!source.removeAuth(user)) { - cache.put(user, auth); - } - } - }); - return true; + public synchronized boolean removeAuth(String name) { + name = name.toLowerCase(); + boolean result = source.removeAuth(name); + if (result) { + cachedAuths.invalidate(name); + } + return result; } /** @@ -302,19 +229,12 @@ public class CacheDataSource implements DataSource { * @see fr.xephi.authme.datasource.DataSource#reload() */ @Override - public void reload() { + public void reload() { // unused method exec.execute(new Runnable() { @Override public void run() { - cache.clear(); source.reload(); - for (Player player : Utils.getOnlinePlayers()) { - String user = player.getName().toLowerCase(); - if (PlayerCache.getInstance().isAuthenticated(user)) { - PlayerAuth auth = source.getAuth(user); - cache.put(user, auth); - } - } + cachedAuths.invalidateAll(); } }); } @@ -324,19 +244,17 @@ public class CacheDataSource implements DataSource { * * @param auth PlayerAuth * - * @return boolean * @see fr.xephi.authme.datasource.DataSource#updateEmail(PlayerAuth) + * @return boolean + * + * @see fr.xephi.authme.datasource.DataSource#updateEmail(PlayerAuth) */ @Override public synchronized boolean updateEmail(final PlayerAuth auth) { - try { - return exec.submit(new Callable() { - public Boolean call() { - return source.updateEmail(auth); - } - }).get(); - } catch (Exception e) { - return false; + boolean result = source.updateEmail(auth); + if (result) { + cachedAuths.refresh(auth.getNickname()); } + return result; } /** @@ -344,27 +262,17 @@ public class CacheDataSource implements DataSource { * * @param auth PlayerAuth * - * @return boolean * @see fr.xephi.authme.datasource.DataSource#updateSalt(PlayerAuth) + * @return boolean + * + * @see fr.xephi.authme.datasource.DataSource#updateSalt(PlayerAuth) */ @Override public synchronized boolean updateSalt(final PlayerAuth auth) { - if (!cache.containsKey(auth.getNickname())) { - return false; + boolean result = source.updateSalt(auth); + if (result) { + cachedAuths.refresh(auth.getNickname()); } - PlayerAuth cachedAuth = cache.get(auth.getNickname()); - final String oldSalt = cachedAuth.getSalt(); - cachedAuth.setSalt(auth.getSalt()); - exec.execute(new Runnable() { - @Override - public void run() { - if (!source.updateSalt(auth)) { - if (cache.containsKey(auth.getNickname())) { - cache.get(auth.getNickname()).setSalt(oldSalt); - } - } - } - }); - return true; + return result; } /** @@ -372,17 +280,13 @@ public class CacheDataSource implements DataSource { * * @param auth PlayerAuth * - * @return List * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByName(PlayerAuth) + * @return List + * + * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByName(PlayerAuth) */ @Override public synchronized List getAllAuthsByName(PlayerAuth auth) { - List result = new ArrayList<>(); - for (Map.Entry stringPlayerAuthEntry : cache.entrySet()) { - PlayerAuth p = stringPlayerAuthEntry.getValue(); - if (p.getIp().equals(auth.getIp())) - result.add(p.getNickname()); - } - return result; + return source.getAllAuthsByName(auth); } /** @@ -390,15 +294,13 @@ public class CacheDataSource implements DataSource { * * @param ip String * - * @return List * @throws Exception * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByIp(String) + * @return List + * + * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByIp(String) */ @Override - public synchronized List getAllAuthsByIp(final String ip) throws Exception { - return exec.submit(new Callable>() { - public List call() throws Exception { - return source.getAllAuthsByIp(ip); - } - }).get(); + public synchronized List getAllAuthsByIp(final String ip) { + return source.getAllAuthsByIp(ip); } /** @@ -406,15 +308,13 @@ public class CacheDataSource implements DataSource { * * @param email String * - * @return List * @throws Exception * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByEmail(String) + * @return List + * + * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByEmail(String) */ @Override - public synchronized List getAllAuthsByEmail(final String email) throws Exception { - return exec.submit(new Callable>() { - public List call() throws Exception { - return source.getAllAuthsByEmail(email); - } - }).get(); + public synchronized List getAllAuthsByEmail(final String email) { + return source.getAllAuthsByEmail(email); } /** @@ -422,7 +322,7 @@ public class CacheDataSource implements DataSource { * * @param banned List * - * @see fr.xephi.authme.datasource.DataSource#purgeBanned(List) + * @see fr.xephi.authme.datasource.DataSource#purgeBanned(List) */ @Override public synchronized void purgeBanned(final List banned) { @@ -430,11 +330,7 @@ public class CacheDataSource implements DataSource { @Override public void run() { source.purgeBanned(banned); - for (PlayerAuth auth : cache.values()) { - if (banned.contains(auth.getNickname())) { - cache.remove(auth.getNickname()); - } - } + cachedAuths.invalidateAll(banned); } }); } @@ -442,7 +338,9 @@ public class CacheDataSource implements DataSource { /** * Method getType. * - * @return DataSourceType * @see fr.xephi.authme.datasource.DataSource#getType() + * @return DataSourceType + * + * @see fr.xephi.authme.datasource.DataSource#getType() */ @Override public DataSourceType getType() { @@ -454,12 +352,13 @@ public class CacheDataSource implements DataSource { * * @param user String * - * @return boolean * @see fr.xephi.authme.datasource.DataSource#isLogged(String) + * @return boolean + * + * @see fr.xephi.authme.datasource.DataSource#isLogged(String) */ @Override public boolean isLogged(String user) { - user = user.toLowerCase(); - return PlayerCache.getInstance().getCache().containsKey(user); + return PlayerCache.getInstance().isAuthenticated(user); } /** @@ -507,6 +406,7 @@ public class CacheDataSource implements DataSource { @Override public void run() { source.purgeLogged(); + cachedAuths.invalidateAll(); } }); } @@ -514,11 +414,13 @@ public class CacheDataSource implements DataSource { /** * Method getAccountsRegistered. * - * @return int * @see fr.xephi.authme.datasource.DataSource#getAccountsRegistered() + * @return int + * + * @see fr.xephi.authme.datasource.DataSource#getAccountsRegistered() */ @Override public int getAccountsRegistered() { - return cache.size(); + return source.getAccountsRegistered(); } /** @@ -531,14 +433,11 @@ public class CacheDataSource implements DataSource { */ @Override public void updateName(final String oldOne, final String newOne) { - if (cache.containsKey(oldOne)) { - cache.put(newOne, cache.get(oldOne)); - cache.remove(oldOne); - } exec.execute(new Runnable() { @Override public void run() { source.updateName(oldOne, newOne); + cachedAuths.invalidate(oldOne); } }); } @@ -546,17 +445,21 @@ public class CacheDataSource implements DataSource { /** * Method getAllAuths. * - * @return List * @see fr.xephi.authme.datasource.DataSource#getAllAuths() + * @return List + * + * @see fr.xephi.authme.datasource.DataSource#getAllAuths() */ @Override public List getAllAuths() { - return new ArrayList<>(cache.values()); + return source.getAllAuths(); } /** * Method getLoggedPlayers. * - * @return List * @see fr.xephi.authme.datasource.DataSource#getLoggedPlayers() + * @return List + * + * @see fr.xephi.authme.datasource.DataSource#getLoggedPlayers() */ @Override public List getLoggedPlayers() { diff --git a/src/main/java/fr/xephi/authme/datasource/DataSource.java b/src/main/java/fr/xephi/authme/datasource/DataSource.java index 39251b0a..e43dffa8 100644 --- a/src/main/java/fr/xephi/authme/datasource/DataSource.java +++ b/src/main/java/fr/xephi/authme/datasource/DataSource.java @@ -114,7 +114,7 @@ public interface DataSource { * * @return List * @throws Exception */ - List getAllAuthsByIp(String ip) throws Exception; + List getAllAuthsByIp(String ip); /** * Method getAllAuthsByEmail. @@ -123,7 +123,7 @@ public interface DataSource { * * @return List * @throws Exception */ - List getAllAuthsByEmail(String email) throws Exception; + List getAllAuthsByEmail(String email); /** * Method updateEmail. diff --git a/src/main/java/fr/xephi/authme/datasource/FlatFile.java b/src/main/java/fr/xephi/authme/datasource/FlatFile.java index 19c93ea3..40047979 100644 --- a/src/main/java/fr/xephi/authme/datasource/FlatFile.java +++ b/src/main/java/fr/xephi/authme/datasource/FlatFile.java @@ -6,7 +6,13 @@ import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.settings.Settings; -import java.io.*; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -564,7 +570,7 @@ public class FlatFile implements DataSource { BufferedReader br = null; try { br = new BufferedReader(new FileReader(source)); - String line = ""; + String line; while ((line = br.readLine()) != null) { String[] args = line.split(":"); if (args[0].equals(auth.getNickname())) { @@ -721,7 +727,7 @@ public class FlatFile implements DataSource { * * @param banned List * - * @see fr.xephi.authme.datasource.DataSource#purgeBanned(List) + * @see fr.xephi.authme.datasource.DataSource#purgeBanned(List) */ @Override public void purgeBanned(List banned) { @@ -856,7 +862,7 @@ public class FlatFile implements DataSource { @Override public void updateName(String oldOne, String newOne) { PlayerAuth auth = this.getAuth(oldOne); - auth.setName(newOne); + auth.setNickname(newOne); this.saveAuth(auth); this.removeAuth(oldOne); } diff --git a/src/main/java/fr/xephi/authme/datasource/MySQL.java b/src/main/java/fr/xephi/authme/datasource/MySQL.java index 93a2d345..e779afff 100644 --- a/src/main/java/fr/xephi/authme/datasource/MySQL.java +++ b/src/main/java/fr/xephi/authme/datasource/MySQL.java @@ -655,6 +655,7 @@ public class MySQL implements DataSource { while (rs.next()) { list.add(rs.getString(columnName)); } + rs.close(); sql = "DELETE FROM " + tableName + " WHERE " + columnLastLogin + "<" + until; st.executeUpdate(sql); st.close(); @@ -915,11 +916,10 @@ public class MySQL implements DataSource { * * @return List * - * @throws SQLException * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByEmail(String) */ @Override - public synchronized List getAllAuthsByEmail(String email) throws SQLException { + public synchronized List getAllAuthsByEmail(String email){ List countEmail = new ArrayList<>(); try (Connection con = getConnection()) { String sql = "SELECT " + columnName + " FROM " + tableName + " WHERE " + columnEmail + "=?;"; @@ -931,8 +931,11 @@ public class MySQL implements DataSource { } rs.close(); pst.close(); - return countEmail; + } catch (SQLException ex) { + ConsoleLogger.showError(ex.getMessage()); + ConsoleLogger.writeStackTrace(ex); } + return countEmail; } /** diff --git a/src/main/java/fr/xephi/authme/hooks/BungeeCordMessage.java b/src/main/java/fr/xephi/authme/hooks/BungeeCordMessage.java index d6e25117..f8a1b8d5 100644 --- a/src/main/java/fr/xephi/authme/hooks/BungeeCordMessage.java +++ b/src/main/java/fr/xephi/authme/hooks/BungeeCordMessage.java @@ -49,25 +49,32 @@ public class BungeeCordMessage implements PluginMessageListener { if (subChannel.equalsIgnoreCase("AuthMe")) { String str = in.readUTF(); String[] args = str.split(";"); - String name = args[1]; - PlayerAuth auth = plugin.database.getAuth(name); - if (auth == null) { - return; - } - if ("login".equals(args[0])) { - PlayerCache.getInstance().updatePlayer(auth); - plugin.database.setLogged(name); - ConsoleLogger.info("Player " + auth.getNickname() + " has logged in from one of your server!"); - } else if ("logout".equals(args[0])) { - PlayerCache.getInstance().removePlayer(name); - plugin.database.setUnlogged(name); - ConsoleLogger.info("Player " + auth.getNickname() + " has logged out from one of your server!"); - } else if ("register".equals(args[0])) { - if (plugin.database instanceof CacheDataSource) { - ((CacheDataSource)plugin.database).addAuthToCache(auth); + final String act = args[0]; + final String name = args[1]; + plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() { + @Override + public void run() { + PlayerAuth auth = plugin.database.getAuth(name); + if (auth == null) { + return; + } + if ("login".equals(act)) { + PlayerCache.getInstance().updatePlayer(auth); + plugin.database.setLogged(name); + ConsoleLogger.info("Player " + auth.getNickname() + + " has logged in from one of your server!"); + } else if ("logout".equals(act)) { + PlayerCache.getInstance().removePlayer(name); + plugin.database.setUnlogged(name); + ConsoleLogger.info("Player " + auth.getNickname() + + " has logged out from one of your server!"); + } else if ("register".equals(act)) { + ConsoleLogger.info("Player " + auth.getNickname() + + " has registered out from one of your server!"); + } + } - ConsoleLogger.info("Player " + auth.getNickname() + " has registered out from one of your server!"); - } + }); } } From 57446426cea9d26bcdfd1e35b2fdab501c09c293 Mon Sep 17 00:00:00 2001 From: DNx5 Date: Sat, 12 Dec 2015 19:48:01 +0700 Subject: [PATCH 02/17] Added cache removal listener. * Re-add auth object if player is still authenticated --- .../fr/xephi/authme/datasource/CacheDataSource.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java index a1f74dd3..2d12a720 100644 --- a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java +++ b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java @@ -3,6 +3,9 @@ package fr.xephi.authme.datasource; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; +import com.google.common.cache.RemovalListener; +import com.google.common.cache.RemovalListeners; +import com.google.common.cache.RemovalNotification; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerCache; @@ -30,6 +33,15 @@ public class CacheDataSource implements DataSource { this.exec = Executors.newCachedThreadPool(); cachedAuths = CacheBuilder.newBuilder() .expireAfterWrite(5, TimeUnit.MINUTES) + .removalListener(RemovalListeners.asynchronous(new RemovalListener() { + @Override + public void onRemoval(RemovalNotification removalNotification) { + String name = removalNotification.getKey(); + if (PlayerCache.getInstance().isAuthenticated(name)) { + cachedAuths.getUnchecked(name); + } + } + }, exec)) .build( new CacheLoader() { public PlayerAuth load(String key) { From 9f3b24db6feb1e0b4e8e1ab389dd4c958dd9bab7 Mon Sep 17 00:00:00 2001 From: DNx5 Date: Sat, 12 Dec 2015 20:12:52 +0700 Subject: [PATCH 03/17] Added player's real name check. Prevent login with other name case. --- .../authme/listener/AuthMePlayerListener.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java b/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java index 492ebe51..e49215b3 100644 --- a/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java +++ b/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java @@ -17,6 +17,7 @@ import fr.xephi.authme.settings.Settings; import fr.xephi.authme.util.GeoLiteAPI; import fr.xephi.authme.util.Utils; import org.bukkit.Bukkit; +import org.bukkit.ChatColor; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.entity.Entity; @@ -224,7 +225,20 @@ public class AuthMePlayerListener implements Listener { return; } - if (Settings.enableProtection) { + PlayerAuth auth = plugin.database.getAuth(event.getName()); + if (auth != null && !auth.getRealName().equals("Player") && !auth.getRealName().equals(event.getName())) { + event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER); + event.setKickMessage("You should join using username: " + ChatColor.AQUA + auth.getRealName() + + ChatColor.RESET + "\nnot :" + ChatColor.RED + event.getName()); // TODO: write a better message + return; + } + + if (auth != null && auth.getRealName().equals("Player")) { + auth.setRealName(event.getName()); + plugin.database.saveAuth(auth); + } + + if (auth == null && Settings.enableProtection) { String countryCode = GeoLiteAPI.getCountryCode(event.getAddress().getHostAddress()); if (!Settings.countriesBlacklist.isEmpty() && Settings.countriesBlacklist.contains(countryCode)) { event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER); @@ -240,13 +254,9 @@ public class AuthMePlayerListener implements Listener { final String name = event.getName().toLowerCase(); final Player player = Utils.getPlayer(name); - if (player == null) { - return; - } - // Check if forceSingleSession is set to true, so kick player that has // joined with same nick of online player - if (Settings.isForceSingleSessionEnabled) { + if (player != null && Settings.isForceSingleSessionEnabled) { event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER); event.setKickMessage(m.retrieveSingle(MessageKey.USERNAME_ALREADY_ONLINE_ERROR)); LimboPlayer limbo = LimboCache.getInstance().getLimboPlayer(name); @@ -435,7 +445,7 @@ public class AuthMePlayerListener implements Listener { } @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) - public void playerHitPlayerEvent(EntityDamageByEntityEvent event) { + public void onPlayerHitPlayerEvent(EntityDamageByEntityEvent event) { Entity damager = event.getDamager(); if (!(damager instanceof Player)) { return; From 7b3b7766e6252986722fe1fe50cf61afdf8ee398 Mon Sep 17 00:00:00 2001 From: DNx5 Date: Sat, 12 Dec 2015 20:56:45 +0700 Subject: [PATCH 04/17] CacheLoader doesn't accept null values. So, use Optional instead. --- .../authme/datasource/CacheDataSource.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java index 2d12a720..8b26b08c 100644 --- a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java +++ b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java @@ -1,5 +1,6 @@ package fr.xephi.authme.datasource; +import com.google.common.base.Optional; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; @@ -21,7 +22,7 @@ public class CacheDataSource implements DataSource { private final DataSource source; private final ExecutorService exec; - private final LoadingCache cachedAuths; + private final LoadingCache> cachedAuths; /** * Constructor for CacheDataSource. @@ -33,9 +34,9 @@ public class CacheDataSource implements DataSource { this.exec = Executors.newCachedThreadPool(); cachedAuths = CacheBuilder.newBuilder() .expireAfterWrite(5, TimeUnit.MINUTES) - .removalListener(RemovalListeners.asynchronous(new RemovalListener() { + .removalListener(RemovalListeners.asynchronous(new RemovalListener>() { @Override - public void onRemoval(RemovalNotification removalNotification) { + public void onRemoval(RemovalNotification> removalNotification) { String name = removalNotification.getKey(); if (PlayerCache.getInstance().isAuthenticated(name)) { cachedAuths.getUnchecked(name); @@ -43,9 +44,9 @@ public class CacheDataSource implements DataSource { } }, exec)) .build( - new CacheLoader() { - public PlayerAuth load(String key) { - return source.getAuth(key); + new CacheLoader>() { + public Optional load(String key) { + return Optional.fromNullable(source.getAuth(key)); } }); } @@ -76,7 +77,7 @@ public class CacheDataSource implements DataSource { @Override public synchronized PlayerAuth getAuth(String user) { user = user.toLowerCase(); - return cachedAuths.getUnchecked(user); + return cachedAuths.getUnchecked(user).orNull(); } /** @@ -178,9 +179,9 @@ public class CacheDataSource implements DataSource { public int purgeDatabase(long until) { int cleared = source.purgeDatabase(until); if (cleared > 0) { - for (PlayerAuth auth : cachedAuths.asMap().values()) { - if (auth != null && auth.getLastLogin() < until) { - cachedAuths.invalidate(auth.getNickname()); + for (Optional auth : cachedAuths.asMap().values()) { + if (auth.isPresent() && auth.get().getLastLogin() < until) { + cachedAuths.invalidate(auth.get().getNickname()); } } } From 21c136fbdf62f7e3f62a4b17c32623c1c852ad04 Mon Sep 17 00:00:00 2001 From: DNx5 Date: Sat, 12 Dec 2015 21:04:57 +0700 Subject: [PATCH 05/17] Lost my changes. --- .../authme/datasource/CacheDataSource.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java index 2d12a720..8b26b08c 100644 --- a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java +++ b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java @@ -1,5 +1,6 @@ package fr.xephi.authme.datasource; +import com.google.common.base.Optional; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; @@ -21,7 +22,7 @@ public class CacheDataSource implements DataSource { private final DataSource source; private final ExecutorService exec; - private final LoadingCache cachedAuths; + private final LoadingCache> cachedAuths; /** * Constructor for CacheDataSource. @@ -33,9 +34,9 @@ public class CacheDataSource implements DataSource { this.exec = Executors.newCachedThreadPool(); cachedAuths = CacheBuilder.newBuilder() .expireAfterWrite(5, TimeUnit.MINUTES) - .removalListener(RemovalListeners.asynchronous(new RemovalListener() { + .removalListener(RemovalListeners.asynchronous(new RemovalListener>() { @Override - public void onRemoval(RemovalNotification removalNotification) { + public void onRemoval(RemovalNotification> removalNotification) { String name = removalNotification.getKey(); if (PlayerCache.getInstance().isAuthenticated(name)) { cachedAuths.getUnchecked(name); @@ -43,9 +44,9 @@ public class CacheDataSource implements DataSource { } }, exec)) .build( - new CacheLoader() { - public PlayerAuth load(String key) { - return source.getAuth(key); + new CacheLoader>() { + public Optional load(String key) { + return Optional.fromNullable(source.getAuth(key)); } }); } @@ -76,7 +77,7 @@ public class CacheDataSource implements DataSource { @Override public synchronized PlayerAuth getAuth(String user) { user = user.toLowerCase(); - return cachedAuths.getUnchecked(user); + return cachedAuths.getUnchecked(user).orNull(); } /** @@ -178,9 +179,9 @@ public class CacheDataSource implements DataSource { public int purgeDatabase(long until) { int cleared = source.purgeDatabase(until); if (cleared > 0) { - for (PlayerAuth auth : cachedAuths.asMap().values()) { - if (auth != null && auth.getLastLogin() < until) { - cachedAuths.invalidate(auth.getNickname()); + for (Optional auth : cachedAuths.asMap().values()) { + if (auth.isPresent() && auth.get().getLastLogin() < until) { + cachedAuths.invalidate(auth.get().getNickname()); } } } From 7383242599fe0221ca3f8b86a815ce6b755d6a62 Mon Sep 17 00:00:00 2001 From: DNx5 Date: Sun, 13 Dec 2015 23:07:58 +0700 Subject: [PATCH 06/17] Attempt to fix #339 --- .../executable/authme/UnregisterAdminCommand.java | 10 ++++------ .../authme/process/join/AsynchronousJoin.java | 15 +++++---------- .../login/ProcessSyncronousPlayerLogin.java | 5 ----- .../logout/ProcessSyncronousPlayerLogout.java | 4 ---- .../register/ProcessSyncPasswordRegister.java | 5 ----- .../unregister/AsynchronousUnregister.java | 4 ---- 6 files changed, 9 insertions(+), 34 deletions(-) diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java index 8d2b1e11..46625aa1 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java @@ -59,7 +59,7 @@ public class UnregisterAdminCommand extends ExecutableCommand { } // Unregister the player - Player target = Bukkit.getPlayer(playerNameLowerCase); + Player target = Utils.getPlayer(playerNameLowerCase); PlayerCache.getInstance().removePlayer(playerNameLowerCase); Utils.setGroup(target, Utils.GroupType.UNREGISTERED); if (target != null && target.isOnline()) { @@ -75,11 +75,9 @@ public class UnregisterAdminCommand extends ExecutableCommand { LimboCache.getInstance().getLimboPlayer(playerNameLowerCase).setMessageTaskId( scheduler.runTaskAsynchronously(plugin, new MessageTask(plugin, playerNameLowerCase, m.retrieve(MessageKey.REGISTER_MESSAGE), interval))); - if (Settings.applyBlindEffect) - target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, Settings.getRegistrationTimeout * 20, 2)); - if (!Settings.isMovementAllowed && Settings.isRemoveSpeedEnabled) { - target.setWalkSpeed(0.0f); - target.setFlySpeed(0.0f); + if (Settings.applyBlindEffect) { + target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, + Settings.getRegistrationTimeout * 20, 2)); } m.send(target, MessageKey.UNREGISTERED_SUCCESS); 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 8a4bd654..dd1eb4b2 100644 --- a/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java +++ b/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java @@ -10,9 +10,9 @@ import fr.xephi.authme.events.FirstSpawnTeleportEvent; import fr.xephi.authme.events.ProtectInventoryEvent; import fr.xephi.authme.events.SpawnTeleportEvent; import fr.xephi.authme.listener.AuthMePlayerListener; -import fr.xephi.authme.permission.PlayerPermission; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; +import fr.xephi.authme.permission.PlayerPermission; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Spawn; import fr.xephi.authme.task.MessageTask; @@ -78,9 +78,9 @@ public class AsynchronousJoin { return; } if (Settings.getMaxJoinPerIp > 0 - && !plugin.getPermissionsManager().hasPermission(player, PlayerPermission.ALLOW_MULTIPLE_ACCOUNTS) - && !ip.equalsIgnoreCase("127.0.0.1") - && !ip.equalsIgnoreCase("localhost")) { + && !plugin.getPermissionsManager().hasPermission(player, PlayerPermission.ALLOW_MULTIPLE_ACCOUNTS) + && !ip.equalsIgnoreCase("127.0.0.1") + && !ip.equalsIgnoreCase("localhost")) { if (plugin.hasJoinedIp(player.getName(), ip)) { sched.scheduleSyncDelayedTask(plugin, new Runnable() { @@ -203,10 +203,6 @@ public class AsynchronousJoin { if (Settings.applyBlindEffect) { player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeOut, 2)); } - if (!Settings.isMovementAllowed && Settings.isRemoveSpeedEnabled) { - player.setWalkSpeed(0.0f); - player.setFlySpeed(0.0f); - } } }); @@ -236,8 +232,7 @@ public class AsynchronousJoin { ? m.retrieve(MessageKey.REGISTER_EMAIL_MESSAGE) : m.retrieve(MessageKey.REGISTER_MESSAGE); } - if (LimboCache.getInstance().getLimboPlayer(name) != null) - { + if (LimboCache.getInstance().getLimboPlayer(name) != null) { BukkitTask msgTask = sched.runTaskAsynchronously(plugin, new MessageTask(plugin, name, msg, msgInterval)); LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgTask); } diff --git a/src/main/java/fr/xephi/authme/process/login/ProcessSyncronousPlayerLogin.java b/src/main/java/fr/xephi/authme/process/login/ProcessSyncronousPlayerLogin.java index f64b2274..8c828074 100644 --- a/src/main/java/fr/xephi/authme/process/login/ProcessSyncronousPlayerLogin.java +++ b/src/main/java/fr/xephi/authme/process/login/ProcessSyncronousPlayerLogin.java @@ -189,11 +189,6 @@ public class ProcessSyncronousPlayerLogin implements Runnable { player.removePotionEffect(PotionEffectType.BLINDNESS); } - if (!Settings.isMovementAllowed && Settings.isRemoveSpeedEnabled) { - player.setWalkSpeed(0.2f); - player.setFlySpeed(0.1f); - } - // The Login event now fires (as intended) after everything is processed Bukkit.getServer().getPluginManager().callEvent(new LoginEvent(player, true)); player.saveData(); diff --git a/src/main/java/fr/xephi/authme/process/logout/ProcessSyncronousPlayerLogout.java b/src/main/java/fr/xephi/authme/process/logout/ProcessSyncronousPlayerLogout.java index 8f34c363..4fd6a9ca 100644 --- a/src/main/java/fr/xephi/authme/process/logout/ProcessSyncronousPlayerLogout.java +++ b/src/main/java/fr/xephi/authme/process/logout/ProcessSyncronousPlayerLogout.java @@ -80,10 +80,6 @@ public class ProcessSyncronousPlayerLogout implements Runnable { if (!Settings.isMovementAllowed) { player.setAllowFlight(true); player.setFlying(true); - if (!Settings.isMovementAllowed && Settings.isRemoveSpeedEnabled) { - player.setFlySpeed(0.0f); - player.setWalkSpeed(0.0f); - } } // Player is now logout... Time to fire event ! Bukkit.getServer().getPluginManager().callEvent(new LogoutEvent(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 4c9136de..17916167 100644 --- a/src/main/java/fr/xephi/authme/process/register/ProcessSyncPasswordRegister.java +++ b/src/main/java/fr/xephi/authme/process/register/ProcessSyncPasswordRegister.java @@ -128,11 +128,6 @@ public class ProcessSyncPasswordRegister implements Runnable { player.removePotionEffect(PotionEffectType.BLINDNESS); } - if (!Settings.isMovementAllowed && Settings.isRemoveSpeedEnabled) { - player.setWalkSpeed(0.0f); - player.setFlySpeed(0.0f); - } - // The LoginEvent now fires (as intended) after everything is processed plugin.getServer().getPluginManager().callEvent(new LoginEvent(player, true)); player.saveData(); 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 da5d19f9..53c54b3e 100644 --- a/src/main/java/fr/xephi/authme/process/unregister/AsynchronousUnregister.java +++ b/src/main/java/fr/xephi/authme/process/unregister/AsynchronousUnregister.java @@ -104,10 +104,6 @@ public class AsynchronousUnregister { if (Settings.applyBlindEffect) { player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeOut, 2)); } - if (!Settings.isMovementAllowed && Settings.isRemoveSpeedEnabled) { - player.setWalkSpeed(0.0f); - player.setFlySpeed(0.0f); - } m.send(player, MessageKey.UNREGISTERED_SUCCESS); ConsoleLogger.info(player.getDisplayName() + " unregistered himself"); Utils.teleportToSpawn(player); From 1c68f596bdc1002c7bc5decd903724b74b64ea65 Mon Sep 17 00:00:00 2001 From: Alexandre Vanhecke Date: Mon, 14 Dec 2015 12:06:31 +0100 Subject: [PATCH 07/17] Update messages_hu.yml --- src/main/resources/messages/messages_hu.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/messages/messages_hu.yml b/src/main/resources/messages/messages_hu.yml index 3245ce1a..f52e4f2b 100644 --- a/src/main/resources/messages/messages_hu.yml +++ b/src/main/resources/messages/messages_hu.yml @@ -1,4 +1,4 @@ -reg_only: Csak regisztrált játékosoknak! Jelentkezni a yndicraft@freemail.hu e-mail címen lehet +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' From 0fdc8d2810f5a247f20ae9404e765c267a3a85d0 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Mon, 14 Dec 2015 16:24:09 +0100 Subject: [PATCH 08/17] Fix #338 Create test to verify consistent argument count --- .../command/CommandInitializerTest.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java b/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java index e364fb9e..821e2c83 100644 --- a/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java +++ b/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java @@ -5,6 +5,7 @@ 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.Ignore; import org.junit.Test; import java.util.ArrayList; @@ -269,6 +270,42 @@ public class CommandInitializerTest { walkThroughCommands(commands, adminPermissionChecker); } + /** + * Tests that multiple CommandDescription instances pointing to the same ExecutableCommand use the same + * count of arguments. + */ + @Test + @Ignore // TODO #306 ljacqu 20151214: Un-ignore this test and fix the offending command + public void shouldPointToSameExecutableCommandWithConsistentArgumentCount() { + // given + final Map, Integer> mandatoryArguments = new HashMap<>(); + final Map, Integer> totalArguments = new HashMap<>(); + + BiConsumer argChecker = new BiConsumer() { + @Override + public void accept(CommandDescription command, int depth) { + testCollectionForCommand(command, CommandUtils.getMinNumberOfArguments(command), mandatoryArguments); + testCollectionForCommand(command, CommandUtils.getMaxNumberOfArguments(command), totalArguments); + } + private void testCollectionForCommand(CommandDescription command, int argCount, + Map, Integer> collection) { + final Class clazz = command.getExecutableCommand().getClass(); + Integer existingCount = collection.get(clazz); + if (existingCount != null) { + String commandDescription = "Command with label '" + command.getLabels().get(0) + "' and parent '" + + (command.getParent() != null ? command.getLabels().get(0) : "null") + "' "; + assertThat(commandDescription + "should point to " + clazz + " with arguments consistent to others", + argCount, equalTo(existingCount)); + } else { + collection.put(clazz, argCount); + } + } + }; + + // when / then + walkThroughCommands(commands, argChecker); + } + // ------------ // Helper methods From 282f777311ebfcc1fdb423b2658e64456c4707b4 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Mon, 14 Dec 2015 21:07:03 +0100 Subject: [PATCH 09/17] #336 Create command list generator in tools - Add new conditional template tags [...] blabla [/...] - Create logic for generating a list of commands --- .../java/fr/xephi/authme/DataManager.java | 2 +- .../fr/xephi/authme/command/CommandUtils.java | 16 ++++- .../authme/command/CommandUtilsTest.java | 52 ++++++++++++++ src/tools/commands/CommandPageCreater.java | 70 +++++++++++++++++++ src/tools/commands/command_entry.tpl.md | 2 + src/tools/commands/commands.tpl.md | 4 ++ .../permissions/PermissionsListWriter.java | 6 +- src/tools/utils/FileUtils.java | 3 +- src/tools/utils/TagReplacer.java | 13 +++- 9 files changed, 157 insertions(+), 11 deletions(-) create mode 100644 src/test/java/fr/xephi/authme/command/CommandUtilsTest.java create mode 100644 src/tools/commands/CommandPageCreater.java create mode 100644 src/tools/commands/command_entry.tpl.md create mode 100644 src/tools/commands/commands.tpl.md diff --git a/src/main/java/fr/xephi/authme/DataManager.java b/src/main/java/fr/xephi/authme/DataManager.java index c3847f3b..451667ad 100644 --- a/src/main/java/fr/xephi/authme/DataManager.java +++ b/src/main/java/fr/xephi/authme/DataManager.java @@ -203,7 +203,7 @@ public class DataManager { } catch (Exception ignored) { } } - ConsoleLogger.info("AutoPurgeDatabase : Removed " + i + " permissions"); + ConsoleLogger.info("AutoPurgeDatabase : Removed " + i + "permissions"); /*int i = 0; for (String name : cleared) { diff --git a/src/main/java/fr/xephi/authme/command/CommandUtils.java b/src/main/java/fr/xephi/authme/command/CommandUtils.java index 6025a5d9..11445999 100644 --- a/src/main/java/fr/xephi/authme/command/CommandUtils.java +++ b/src/main/java/fr/xephi/authme/command/CommandUtils.java @@ -1,10 +1,12 @@ package fr.xephi.authme.command; -import java.util.List; - +import com.google.common.collect.Lists; import fr.xephi.authme.util.CollectionUtils; import fr.xephi.authme.util.StringUtils; +import java.util.ArrayList; +import java.util.List; + public final class CommandUtils { public static int getMinNumberOfArguments(CommandDescription command) { @@ -32,6 +34,16 @@ public final class CommandUtils { return StringUtils.join(" ", labels); } + public static String constructCommandPath(CommandDescription command) { + List labels = new ArrayList<>(); + CommandDescription currentCommand = command; + while (currentCommand != null) { + labels.add(currentCommand.getLabels().get(0)); + currentCommand = currentCommand.getParent(); + } + return "/" + labelsToString(Lists.reverse(labels)); + } + public static double getDifference(List labels1, List labels2, boolean fullCompare) { // Make sure the other reference is correct if (labels1 == null || labels2 == null) { diff --git a/src/test/java/fr/xephi/authme/command/CommandUtilsTest.java b/src/test/java/fr/xephi/authme/command/CommandUtilsTest.java new file mode 100644 index 00000000..d808f8b4 --- /dev/null +++ b/src/test/java/fr/xephi/authme/command/CommandUtilsTest.java @@ -0,0 +1,52 @@ +package fr.xephi.authme.command; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; + +/** + * Test for {@link CommandUtils}. + */ +public class CommandUtilsTest { + + @Test + public void shouldPrintLabels() { + // given + List labels = Arrays.asList("authme", "help", "reload"); + + // when + String result = CommandUtils.labelsToString(labels); + + // then + assertThat(result, equalTo("authme help reload")); + } + + @Test + public void shouldReturnCommandPath() { + // given + CommandDescription base = CommandDescription.builder() + .labels("authme", "auth") + .description("Base") + .detailedDescription("Test base command.") + .executableCommand(mock(ExecutableCommand.class)) + .build(); + CommandDescription command = CommandDescription.builder() + .parent(base) + .labels("help", "h", "?") + .description("Child") + .detailedDescription("Test child command.") + .executableCommand(mock(ExecutableCommand.class)) + .build(); + + // when + String commandPath = CommandUtils.constructCommandPath(command); + + // then + assertThat(commandPath, equalTo("/authme help")); + } +} diff --git a/src/tools/commands/CommandPageCreater.java b/src/tools/commands/CommandPageCreater.java new file mode 100644 index 00000000..4d74dfba --- /dev/null +++ b/src/tools/commands/CommandPageCreater.java @@ -0,0 +1,70 @@ +package commands; + +import fr.xephi.authme.command.CommandArgumentDescription; +import fr.xephi.authme.command.CommandDescription; +import fr.xephi.authme.command.CommandInitializer; +import fr.xephi.authme.command.CommandPermissions; +import fr.xephi.authme.command.CommandUtils; +import fr.xephi.authme.permission.PermissionNode; +import utils.ANewMap; +import utils.FileUtils; +import utils.TagReplacer; +import utils.ToolTask; +import utils.ToolsConstants; + +import java.util.Map; +import java.util.Scanner; +import java.util.Set; + +public class CommandPageCreater implements ToolTask { + + @Override + public String getTaskName() { + return "createCommandPage"; + } + + @Override + public void execute(Scanner scanner) { + final Set baseCommands = CommandInitializer.getBaseCommands(); + final String template = FileUtils.readFromFile(ToolsConstants.TOOLS_SOURCE_ROOT + + "commands/command_entry.tpl.md"); + + StringBuilder commandsResult = new StringBuilder(); + for (CommandDescription command : baseCommands) { + Map tags = ANewMap + .with("command", CommandUtils.constructCommandPath(command)) + .and("description", command.getDetailedDescription()) + .and("arguments", formatArguments(command.getArguments())) + .and("permissions", formatPermissions(command.getCommandPermissions())) + .build(); + commandsResult.append(TagReplacer.applyReplacements(template, tags)); + } + + FileUtils.generateFileFromTemplate( + ToolsConstants.TOOLS_SOURCE_ROOT + "commands/commands.tpl.md", + ToolsConstants.DOCS_FOLDER + "commands.md", + ANewMap.with("commands", commandsResult.toString()).build()); + } + + private static String formatPermissions(CommandPermissions permissions) { + if (permissions == null) { + return ""; + } + String result = ""; + for (PermissionNode node : permissions.getPermissionNodes()) { + result += node.getNode() + " "; + } + return result; + } + + private static String formatArguments(Iterable arguments) { + StringBuilder result = new StringBuilder(); + for (CommandArgumentDescription argument : arguments) { + String argumentName = argument.isOptional() + ? "[" + argument.getDescription() + "]" + : "<" + argument.getDescription() + ">"; + result.append(argumentName).append(" "); + } + return result.toString(); + } +} diff --git a/src/tools/commands/command_entry.tpl.md b/src/tools/commands/command_entry.tpl.md new file mode 100644 index 00000000..c39b1deb --- /dev/null +++ b/src/tools/commands/command_entry.tpl.md @@ -0,0 +1,2 @@ +{command}: {description} _{arguments}_ +[permissions]Permission: {permissions}[/permissions] diff --git a/src/tools/commands/commands.tpl.md b/src/tools/commands/commands.tpl.md new file mode 100644 index 00000000..f2334c1b --- /dev/null +++ b/src/tools/commands/commands.tpl.md @@ -0,0 +1,4 @@ +## AuthMe commands +You can use the following commands to use the functions of AuthMe: + +{commands} diff --git a/src/tools/permissions/PermissionsListWriter.java b/src/tools/permissions/PermissionsListWriter.java index 1d06b8ce..5958e077 100644 --- a/src/tools/permissions/PermissionsListWriter.java +++ b/src/tools/permissions/PermissionsListWriter.java @@ -47,7 +47,7 @@ public class PermissionsListWriter implements ToolTask { private static void generateAndWriteFile() { final String permissionsTagValue = generatePermissionsList(); - Map tags = ANewMap.with("permissions", permissionsTagValue).build(); + Map tags = ANewMap.with("permissions", permissionsTagValue).build(); FileUtils.generateFileFromTemplate( ToolsConstants.TOOLS_SOURCE_ROOT + "permissions/permission_nodes.tpl.md", PERMISSIONS_OUTPUT_FILE, tags); System.out.println("Wrote to '" + PERMISSIONS_OUTPUT_FILE + "'"); @@ -62,8 +62,8 @@ public class PermissionsListWriter implements ToolTask { StringBuilder sb = new StringBuilder(); for (Map.Entry entry : permissions.entrySet()) { - Map tags = ANewMap. - with("node", entry.getKey()) + Map tags = ANewMap + .with("node", entry.getKey()) .and("description", entry.getValue()) .build(); sb.append(TagReplacer.applyReplacements(template, tags)); diff --git a/src/tools/utils/FileUtils.java b/src/tools/utils/FileUtils.java index 5ad5ab25..49bcab9f 100644 --- a/src/tools/utils/FileUtils.java +++ b/src/tools/utils/FileUtils.java @@ -18,10 +18,9 @@ public final class FileUtils { private FileUtils() { } - public static void generateFileFromTemplate(String templateFile, String destinationFile, Map tags) { + public static void generateFileFromTemplate(String templateFile, String destinationFile, Map tags) { String template = readFromFile(templateFile); String result = TagReplacer.applyReplacements(template, tags); - writeToFile(destinationFile, result); } diff --git a/src/tools/utils/TagReplacer.java b/src/tools/utils/TagReplacer.java index 404857b7..29a9b91c 100644 --- a/src/tools/utils/TagReplacer.java +++ b/src/tools/utils/TagReplacer.java @@ -1,5 +1,7 @@ package utils; +import fr.xephi.authme.util.StringUtils; + import java.util.Date; import java.util.Map; @@ -21,10 +23,15 @@ public class TagReplacer { * any occurrences of "{foo}" to "bar". * @return The filled template */ - public static String applyReplacements(String template, Map tags) { + public static String applyReplacements(String template, Map tags) { String result = template; - for (Map.Entry tagRule : tags.entrySet()) { - result = result.replace("{" + tagRule.getKey() + "}", tagRule.getValue().toString()); + for (Map.Entry tagRule : tags.entrySet()) { + final String name = tagRule.getKey(); + final String value = tagRule.getValue(); + + String replacement = StringUtils.isEmpty(value) ? "" : "\\1"; + result = result.replaceAll("\\[" + name + "\\](.*?)\\[/" + name + "\\]", replacement); + result = result.replace("{" + tagRule.getKey() + "}", tagRule.getValue()); } return applyReplacements(result); From bfebf6dc44760595129a090d5a79b0911845a805 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Mon, 14 Dec 2015 21:37:20 +0100 Subject: [PATCH 10/17] Add tests for CommandUtils, move purgeDirectory to its only use --- .../xephi/authme/cache/backup/JsonCache.java | 24 ++++++++- src/main/java/fr/xephi/authme/util/Utils.java | 22 -------- .../authme/command/CommandUtilsTest.java | 52 +++++++++++++++++++ 3 files changed, 74 insertions(+), 24 deletions(-) diff --git a/src/main/java/fr/xephi/authme/cache/backup/JsonCache.java b/src/main/java/fr/xephi/authme/cache/backup/JsonCache.java index b07c74d9..38784b16 100644 --- a/src/main/java/fr/xephi/authme/cache/backup/JsonCache.java +++ b/src/main/java/fr/xephi/authme/cache/backup/JsonCache.java @@ -5,7 +5,6 @@ import com.google.common.io.Files; import com.google.gson.*; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.settings.Settings; -import fr.xephi.authme.util.Utils; import org.bukkit.entity.Player; import java.io.File; @@ -109,7 +108,7 @@ public class JsonCache { } File file = new File(cacheDir, path); if (file.exists()) { - Utils.purgeDirectory(file); + purgeDirectory(file); if (!file.delete()) { ConsoleLogger.showError("Failed to remove" + player.getName() + "cache."); } @@ -194,4 +193,25 @@ public class JsonCache { } } + /** + * Delete a given directory and all its content. + * + * @param directory The directory to remove + */ + private static void purgeDirectory(File directory) { + if (!directory.isDirectory()) { + return; + } + File[] files = directory.listFiles(); + if (files == null) { + return; + } + for (File target : files) { + if (target.isDirectory()) { + purgeDirectory(target); + } + target.delete(); + } + } + } diff --git a/src/main/java/fr/xephi/authme/util/Utils.java b/src/main/java/fr/xephi/authme/util/Utils.java index e45b04a8..c96f47c6 100644 --- a/src/main/java/fr/xephi/authme/util/Utils.java +++ b/src/main/java/fr/xephi/authme/util/Utils.java @@ -15,7 +15,6 @@ import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; -import java.io.File; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; @@ -207,27 +206,6 @@ public final class Utils { } } - /** - * Delete a given directory and all his content. - * - * @param directory File - */ - public static void purgeDirectory(File directory) { - if (!directory.isDirectory()) { - return; - } - File[] files = directory.listFiles(); - if (files == null) { - return; - } - for (File target : files) { - if (target.isDirectory()) { - purgeDirectory(target); - } - target.delete(); - } - } - /** * 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, diff --git a/src/test/java/fr/xephi/authme/command/CommandUtilsTest.java b/src/test/java/fr/xephi/authme/command/CommandUtilsTest.java index d808f8b4..14dc8f7f 100644 --- a/src/test/java/fr/xephi/authme/command/CommandUtilsTest.java +++ b/src/test/java/fr/xephi/authme/command/CommandUtilsTest.java @@ -49,4 +49,56 @@ public class CommandUtilsTest { // then assertThat(commandPath, equalTo("/authme help")); } + + + // ------ + // min / max arguments + // ------ + @Test + public void shouldComputeMinAndMaxOnEmptyCommand() { + // given + CommandDescription command = getBuilderForArgsTest().build(); + + // when / then + checkArgumentCount(command, 0, 0); + } + + @Test + public void shouldComputeMinAndMaxOnCommandWithMandatoryArgs() { + // given + CommandDescription command = getBuilderForArgsTest() + .withArgument("Test", "Arg description", false) + .withArgument("Test22", "Arg description 2", false) + .build(); + + // when / then + checkArgumentCount(command, 2, 2); + } + + @Test + public void shouldComputeMinAndMaxOnCommandIncludingOptionalArgs() { + // given + CommandDescription command = getBuilderForArgsTest() + .withArgument("arg1", "Arg description", false) + .withArgument("arg2", "Arg description 2", true) + .withArgument("arg3", "Arg description 3", true) + .build(); + + // when / then + checkArgumentCount(command, 1, 3); + } + + + private static void checkArgumentCount(CommandDescription command, int expectedMin, int expectedMax) { + assertThat(CommandUtils.getMinNumberOfArguments(command), equalTo(expectedMin)); + assertThat(CommandUtils.getMaxNumberOfArguments(command), equalTo(expectedMax)); + } + + private static CommandDescription.CommandBuilder getBuilderForArgsTest() { + return CommandDescription.builder() + .labels("authme", "auth") + .description("Base") + .detailedDescription("Test base command.") + .executableCommand(mock(ExecutableCommand.class)); + } } From 3de7a7584e921484c7e1a3c24d2edbbdc8851eee Mon Sep 17 00:00:00 2001 From: ljacqu Date: Tue, 15 Dec 2015 09:00:41 +0100 Subject: [PATCH 11/17] Merge prefix tests for AdminPermission and PlayerPermission --- .../permission/AdminPermissionTest.java | 18 ++----------- .../permission/PlayerPermissionTest.java | 25 +++---------------- 2 files changed, 5 insertions(+), 38 deletions(-) diff --git a/src/test/java/fr/xephi/authme/permission/AdminPermissionTest.java b/src/test/java/fr/xephi/authme/permission/AdminPermissionTest.java index 9a8625ac..0c2c2b16 100644 --- a/src/test/java/fr/xephi/authme/permission/AdminPermissionTest.java +++ b/src/test/java/fr/xephi/authme/permission/AdminPermissionTest.java @@ -13,9 +13,9 @@ import static org.junit.Assert.fail; public class AdminPermissionTest { @Test - public void shouldStartWithAuthMePrefix() { + public void shouldStartWithAuthMeAdminPrefix() { // given - String requiredPrefix = "authme."; + String requiredPrefix = "authme.admin."; // when/then for (AdminPermission permission : AdminPermission.values()) { @@ -26,20 +26,6 @@ public class AdminPermissionTest { } } - @Test - public void shouldContainAdminBranch() { - // given - String requiredBranch = ".admin."; - - // when/then - for (AdminPermission permission : AdminPermission.values()) { - if (!permission.getNode().contains(requiredBranch)) { - fail("The permission '" + permission + "' does not contain with the required branch '" - + requiredBranch + "'"); - } - } - } - @Test public void shouldHaveUniqueNodes() { // given diff --git a/src/test/java/fr/xephi/authme/permission/PlayerPermissionTest.java b/src/test/java/fr/xephi/authme/permission/PlayerPermissionTest.java index 6afc0ac0..632a2cf3 100644 --- a/src/test/java/fr/xephi/authme/permission/PlayerPermissionTest.java +++ b/src/test/java/fr/xephi/authme/permission/PlayerPermissionTest.java @@ -13,32 +13,13 @@ import static org.junit.Assert.fail; public class PlayerPermissionTest { @Test - public void shouldStartWithAuthMePrefix() { + public void shouldStartWithPlayerPrefix() { // given - String requiredPrefix = "authme."; + String playerBranch = "authme.player."; // when/then for (PlayerPermission permission : PlayerPermission.values()) { - if (!permission.getNode().startsWith(requiredPrefix)) { - fail("The permission '" + permission + "' does not start with the required prefix '" + requiredPrefix - + "'"); - } - } - } - - @Test - public void shouldContainPlayerBranch() { - // given - String playerBranch = ".player."; - String adminBranch = ".admin."; - - // when/then - for (PlayerPermission permission : PlayerPermission.values()) { - if (permission.getNode().contains(adminBranch)) { - fail("The permission '" + permission + "' should not use a node with the admin-specific branch '" - + adminBranch + "'"); - - } else if (!permission.getNode().contains(playerBranch)) { + if (!permission.getNode().startsWith(playerBranch)) { fail("The permission '" + permission + "' should use a node with the player-specific branch '" + playerBranch + "'"); } From 94356bb23f0fba469b06001d77cf03e6d68acb5c Mon Sep 17 00:00:00 2001 From: ljacqu Date: Tue, 15 Dec 2015 13:21:53 +0100 Subject: [PATCH 12/17] #349 Add tags field to MessageKey, add test to verify presence in files --- .../fr/xephi/authme/output/MessageKey.java | 24 ++++++-- src/main/resources/messages/messages_en.yml | 14 ++--- src/tools/messages/MessageFileVerifier.java | 56 ++++++++++++++----- src/tools/messages/VerifyMessagesTask.java | 11 ++++ 4 files changed, 79 insertions(+), 26 deletions(-) diff --git a/src/main/java/fr/xephi/authme/output/MessageKey.java b/src/main/java/fr/xephi/authme/output/MessageKey.java index bc024abf..b93f956b 100644 --- a/src/main/java/fr/xephi/authme/output/MessageKey.java +++ b/src/main/java/fr/xephi/authme/output/MessageKey.java @@ -79,7 +79,7 @@ public enum MessageKey { INVALID_NAME_LENGTH("name_len"), - INVALID_NAME_CHARACTERS("regex"), + INVALID_NAME_CHARACTERS("regex", "REG_EX"), ADD_EMAIL_MESSAGE("add_email"), @@ -87,7 +87,7 @@ public enum MessageKey { USAGE_CAPTCHA("usage_captcha"), - CAPTCHA_WRONG_ERROR("wrong_captcha"), + CAPTCHA_WRONG_ERROR("wrong_captcha", "THE_CAPTCHA"), CAPTCHA_SUCCESS("valid_captcha"), @@ -119,16 +119,32 @@ public enum MessageKey { ANTIBOT_AUTO_ENABLED_MESSAGE("antibot_auto_enabled"), - ANTIBOT_AUTO_DISABLED_MESSAGE("antibot_auto_disabled"); + ANTIBOT_AUTO_DISABLED_MESSAGE("antibot_auto_disabled", "%m"); private String key; + private String[] tags; - MessageKey(String key) { + MessageKey(String key, String... tags) { this.key = key; + this.tags = tags; } + /** + * Return the key used in the messages file. + * + * @return The key + */ public String getKey() { return key; } + + /** + * Return a list of tags (texts) that are replaced with actual content in AuthMe. + * + * @return List of tags + */ + public String[] getTags() { + return tags; + } } diff --git a/src/main/resources/messages/messages_en.yml b/src/main/resources/messages/messages_en.yml index fdb361a3..2d26cb1f 100644 --- a/src/main/resources/messages/messages_en.yml +++ b/src/main/resources/messages/messages_en.yml @@ -14,7 +14,7 @@ user_regged: '&cYou already have registered this username!' usage_reg: '&cUsage: /register ' max_reg: '&cYou have exceeded the maximum number of registrations for your connection!' no_perm: '&4You don''t have the permission to perform this action!' -error: '&4An unexpected error occurred, please contact an Administrator!' +error: '&4An unexpected error occurred, please contact an administrator!' login_msg: '&cPlease, login with the command "/login "' reg_msg: '&3Please, register to the server with the command "/register "' reg_email_msg: '&3Please, register to the server with the command "/register "' @@ -39,20 +39,20 @@ regex: '&4Your username contains illegal characters. Allowed chars: REG_EX' add_email: '&3Please add your email to your account with the command "/email add "' recovery_email: '&3Forgot your password? Please use the command "/email recovery "' usage_captcha: '&3To login you have to solve a captcha code, please use the command "/captcha "' -wrong_captcha: '&cWrong Captcha, please type "/captcha THE_CAPTCHA" into the chat!' +wrong_captcha: '&cWrong captcha, please type "/captcha THE_CAPTCHA" into the chat!' valid_captcha: '&2Captcha code solved correctly!' -kick_forvip: '&3A VIP Player has joined the server when it was full!' +kick_forvip: '&3A VIP player has joined the server when it was full!' kick_fullserver: '&4The server is full, try again later!' usage_email_add: '&cUsage: /email add ' usage_email_change: '&cUsage: /email change ' usage_email_recovery: '&cUsage: /email recovery ' -new_email_invalid: '&cInvalid New Email, try again!' -old_email_invalid: '&cInvalid Old Email, try again!' -email_invalid: '&cInvalid Email address, try again!' +new_email_invalid: '&cInvalid new email, try again!' +old_email_invalid: '&cInvalid old email, try again!' +email_invalid: '&cInvalid email address, try again!' email_added: '&2Email address successfully added to your account!' email_confirm: '&cPlease confirm your email address!' email_changed: '&2Email address changed correctly!' -email_send: '&2Recovery email sent correctly! Check your email inbox!' +email_send: '&2Recovery email sent successfully! Please check your email inbox!' email_exists: '&cA recovery email was already sent! You can discard it and send a new one using the command below:' country_banned: '&4Your country is banned from this server!' antibot_auto_enabled: '&4[AntiBotService] AntiBot enabled due to the huge number of connections!' diff --git a/src/tools/messages/MessageFileVerifier.java b/src/tools/messages/MessageFileVerifier.java index 75e9927e..904ea1af 100644 --- a/src/tools/messages/MessageFileVerifier.java +++ b/src/tools/messages/MessageFileVerifier.java @@ -1,11 +1,15 @@ package messages; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; import fr.xephi.authme.output.MessageKey; import utils.FileUtils; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -22,6 +26,7 @@ public class MessageFileVerifier { private final Set unknownKeys = new HashSet<>(); // Map with the missing key and a boolean indicating whether or not it was added to the file by this object private final Map missingKeys = new HashMap<>(); + private final Multimap missingTags = HashMultimap.create(); /** * Create a verifier that verifies the given messages file. @@ -53,8 +58,17 @@ public class MessageFileVerifier { return missingKeys; } + /** + * Return the collection of tags the message key defines that aren't present in the read line. + * + * @return Collection of missing tags per message key. Key = message key, value = missing tag. + */ + public Multimap getMissingTags() { + return missingTags; + } + private void verifyKeys() { - Set messageKeys = getAllMessageKeys(); + List messageKeys = getAllMessageKeys(); List fileLines = FileUtils.readLinesFromFile(messagesFile); for (String line : fileLines) { // Skip comments and empty lines @@ -64,22 +78,38 @@ public class MessageFileVerifier { } // All keys that remain are keys that are absent in the file - for (String missingKey : messageKeys) { - missingKeys.put(missingKey, false); + for (MessageKey missingKey : messageKeys) { + missingKeys.put(missingKey.getKey(), false); } } - private void processKeyInFile(String line, Set messageKeys) { + private void processKeyInFile(String line, List messageKeys) { if (line.indexOf(':') == -1) { System.out.println("Skipping line in unknown format: '" + line + "'"); return; } - final String key = line.substring(0, line.indexOf(':')); - if (messageKeys.contains(key)) { - messageKeys.remove(key); - } else { - unknownKeys.add(key); + final String readKey = line.substring(0, line.indexOf(':')); + boolean foundKey = false; + for (Iterator it = messageKeys.iterator(); it.hasNext(); ) { + MessageKey messageKey = it.next(); + if (messageKey.getKey().equals(readKey)) { + checkTagsInMessage(readKey, line.substring(line.indexOf(':')), messageKey.getTags()); + it.remove(); + foundKey = true; + break; + } + } + if (!foundKey) { + unknownKeys.add(readKey); + } + } + + private void checkTagsInMessage(String key, String message, String[] tags) { + for (String tag : tags) { + if (!message.contains(tag)) { + missingTags.put(key, tag); + } } } @@ -105,11 +135,7 @@ public class MessageFileVerifier { FileUtils.appendToFile(messagesFile, sb.toString()); } - private static Set getAllMessageKeys() { - Set messageKeys = new HashSet<>(MessageKey.values().length); - for (MessageKey key : MessageKey.values()) { - messageKeys.add(key.getKey()); - } - return messageKeys; + private static List getAllMessageKeys() { + return new ArrayList<>(Arrays.asList(MessageKey.values())); } } diff --git a/src/tools/messages/VerifyMessagesTask.java b/src/tools/messages/VerifyMessagesTask.java index 2a371216..19eacf24 100644 --- a/src/tools/messages/VerifyMessagesTask.java +++ b/src/tools/messages/VerifyMessagesTask.java @@ -1,5 +1,6 @@ package messages; +import com.google.common.collect.Multimap; import fr.xephi.authme.util.StringUtils; import utils.FileUtils; import utils.ToolTask; @@ -84,6 +85,11 @@ public final class VerifyMessagesTask implements ToolTask { if (!unknownKeys.isEmpty()) { System.out.println(" Unknown keys: " + unknownKeys); } + + Multimap missingTags = verifier.getMissingTags(); + for (Map.Entry entry : missingTags.entries()) { + System.out.println(" Missing tag '" + entry.getValue() + "' in entry with key '" + entry.getKey() + "'"); + } } private static void verifyFileAndAddKeys(MessageFileVerifier verifier, Map defaultMessages) { @@ -106,6 +112,11 @@ public final class VerifyMessagesTask implements ToolTask { if (!unknownKeys.isEmpty()) { System.out.println(" Unknown keys: " + unknownKeys); } + + Multimap missingTags = verifier.getMissingTags(); + for (Map.Entry entry : missingTags.entries()) { + System.out.println(" Missing tag '" + entry.getValue() + "' in entry with key '" + entry.getKey() + "'"); + } } private static Map constructDefaultMessages() { From 558a1240a6ea246d169cf4ea0ad9de283616fa82 Mon Sep 17 00:00:00 2001 From: Gabriele C Date: Wed, 16 Dec 2015 13:30:34 +0100 Subject: [PATCH 13/17] whoops --- .../xephi/authme/listener/AuthMeEntityListener.java | 11 +---------- .../xephi/authme/listener/AuthMePlayerListener16.java | 2 +- .../xephi/authme/listener/AuthMePlayerListener18.java | 2 +- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/main/java/fr/xephi/authme/listener/AuthMeEntityListener.java b/src/main/java/fr/xephi/authme/listener/AuthMeEntityListener.java index 30b4af72..1d407a3b 100644 --- a/src/main/java/fr/xephi/authme/listener/AuthMeEntityListener.java +++ b/src/main/java/fr/xephi/authme/listener/AuthMeEntityListener.java @@ -36,6 +36,7 @@ public class AuthMeEntityListener implements Listener { } } + // TODO: npc status can be used to bypass security!!! /** * Method onEntityDamage. * @@ -53,7 +54,6 @@ public class AuthMeEntityListener implements Listener { return; } - // TODO: npc status can be used to bypass security!!! if (Utils.isNPC(player)) { return; } @@ -78,7 +78,6 @@ public class AuthMeEntityListener implements Listener { return; } - // TODO: npc status can be used to bypass security!!! if (Utils.isNPC((Player) entity)) { return; } @@ -104,7 +103,6 @@ public class AuthMeEntityListener implements Listener { return; } - // TODO: npc status can be used to bypass security!!! if (Utils.isNPC(player)) { return; } @@ -128,7 +126,6 @@ public class AuthMeEntityListener implements Listener { return; } - // TODO: npc status can be used to bypass security!!! if (Utils.isNPC((Player) entity)) { return; } @@ -152,7 +149,6 @@ public class AuthMeEntityListener implements Listener { return; } - // TODO: npc status can be used to bypass security!!! if (Utils.isNPC((Player) entity)) { return; } @@ -177,7 +173,6 @@ public class AuthMeEntityListener implements Listener { return; } - // TODO: npc status can be used to bypass security!!! if (Utils.isNPC((Player) entity)) { return; } @@ -201,7 +196,6 @@ public class AuthMeEntityListener implements Listener { return; } - // TODO: npc status can be used to bypass security!!! if (Utils.isNPC((Player) entity)) { return; } @@ -210,7 +204,6 @@ public class AuthMeEntityListener implements Listener { } // TODO: Need to check this, player can't throw snowball but the item is taken. - /** * Method onProjectileLaunch. * @@ -245,7 +238,6 @@ public class AuthMeEntityListener implements Listener { return; } - // TODO: npc status can be used to bypass security!!! if (Utils.isNPC(player)) { return; } @@ -270,7 +262,6 @@ public class AuthMeEntityListener implements Listener { return; } - // TODO: npc status can be used to bypass security!!! if (Utils.isNPC(player)) { return; } diff --git a/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener16.java b/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener16.java index 0975b18a..2c3c5d3c 100644 --- a/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener16.java +++ b/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener16.java @@ -22,6 +22,7 @@ public class AuthMePlayerListener16 implements Listener { this.plugin = plugin; } + // TODO: npc status can be used to bypass security!!! /** * Method onPlayerEditBook. * @@ -33,7 +34,6 @@ public class AuthMePlayerListener16 implements Listener { return; } - // TODO: npc status can be used to bypass security!!! if (Utils.isNPC(event.getPlayer())) { return; } diff --git a/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener18.java b/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener18.java index dbcb1c71..f3d01028 100644 --- a/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener18.java +++ b/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener18.java @@ -22,6 +22,7 @@ public class AuthMePlayerListener18 implements Listener { this.plugin = plugin; } + // TODO: npc status can be used to bypass security!!! /** * Method onPlayerInteractAtEntity. * @@ -33,7 +34,6 @@ public class AuthMePlayerListener18 implements Listener { return; } - // TODO: npc status can be used to bypass security!!! if (Utils.isNPC(event.getPlayer())) { return; } From dcc365c22f6b339a0ad3ee1fa1920b6f06906297 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Wed, 16 Dec 2015 20:46:40 +0100 Subject: [PATCH 14/17] Fix #349 Create method on Messages to pass tag replacements - Add tests - Fix placeholder in some files --- .../executable/captcha/CaptchaCommand.java | 4 +- .../java/fr/xephi/authme/output/Messages.java | 25 ++++++++ .../process/login/AsynchronousLogin.java | 20 +------ src/main/resources/messages/messages_cz.yml | 2 +- src/main/resources/messages/messages_es.yml | 2 +- .../output/MessagesIntegrationTest.java | 58 +++++++++++++++++++ src/test/resources/messages_test.yml | 1 + 7 files changed, 88 insertions(+), 24 deletions(-) diff --git a/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java b/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java index 69677353..be07e33a 100644 --- a/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java @@ -58,9 +58,7 @@ public class CaptchaCommand extends ExecutableCommand { plugin.cap.remove(playerNameLowerCase); String randStr = new RandomString(Settings.captchaLength).nextString(); plugin.cap.put(playerNameLowerCase, randStr); - for (String s : m.retrieve(MessageKey.CAPTCHA_WRONG_ERROR)) { - player.sendMessage(s.replace("THE_CAPTCHA", plugin.cap.get(playerNameLowerCase))); - } + m.send(player, MessageKey.CAPTCHA_WRONG_ERROR, plugin.cap.get(playerNameLowerCase)); return true; } diff --git a/src/main/java/fr/xephi/authme/output/Messages.java b/src/main/java/fr/xephi/authme/output/Messages.java index ad586fd1..e27e9061 100644 --- a/src/main/java/fr/xephi/authme/output/Messages.java +++ b/src/main/java/fr/xephi/authme/output/Messages.java @@ -47,6 +47,31 @@ public class Messages { } } + /** + * Send the given message code to the player with the given tag replacements. Note that this method + * issues an exception if the number of supplied replacements doesn't correspond to the number of tags + * the message key contains. + * + * @param sender The entity to send the message to + * @param key The key of the message to send + * @param replacements The replacements to apply for the tags + */ + public void send(CommandSender sender, MessageKey key, String... replacements) { + String message = retrieveSingle(key); + String[] tags = key.getTags(); + if (replacements.length != tags.length) { + throw new RuntimeException("Given replacement size does not match the tags in message key '" + key + "'"); + } + + for (int i = 0; i < tags.length; ++i) { + message = message.replace(tags[i], replacements[i]); + } + + for (String line : message.split("\n")) { + sender.sendMessage(line); + } + } + /** * Retrieve the message from the text file and return it split by new line as an array. * 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 025defb2..b588361c 100644 --- a/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java +++ b/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java @@ -57,20 +57,10 @@ public class AsynchronousLogin { this.database = data; } - /** - * Method getIP. - * - * @return String - */ protected String getIP() { return plugin.getIP(player); } - /** - * Method needsCaptcha. - * - * @return boolean - */ protected boolean needsCaptcha() { if (Settings.useCaptcha) { if (!plugin.captcha.containsKey(name)) { @@ -82,9 +72,7 @@ public class AsynchronousLogin { } if (plugin.captcha.containsKey(name) && plugin.captcha.get(name) > Settings.maxLoginTry) { plugin.cap.putIfAbsent(name, rdm.nextString()); - for (String s : m.retrieve(MessageKey.USAGE_CAPTCHA)) { - player.sendMessage(s.replace("THE_CAPTCHA", plugin.cap.get(name)).replace("", plugin.cap.get(name))); - } + m.send(player, MessageKey.USAGE_CAPTCHA, plugin.cap.get(name)); return true; } } @@ -230,12 +218,6 @@ public class AsynchronousLogin { } } - /** - * Method displayOtherAccounts. - * - * @param auth PlayerAuth - * @param p Player - */ public void displayOtherAccounts(PlayerAuth auth, Player p) { if (!Settings.displayOtherAccounts) { return; diff --git a/src/main/resources/messages/messages_cz.yml b/src/main/resources/messages/messages_cz.yml index 591e4e75..4108ea5a 100644 --- a/src/main/resources/messages/messages_cz.yml +++ b/src/main/resources/messages/messages_cz.yml @@ -38,7 +38,7 @@ regex: '&cTvuj nick obsahuje nepovolene znaky. Pripustne znaky jsou: REG_EX' add_email: '&cPridej prosim svuj email pomoci : /email add TvujEmail TvujEmail' recovery_email: '&cZapomel jsi heslo? Zadej: /email recovery ' usage_captcha: '&cPouzij: /captcha ' -wrong_captcha: '&cSpatne opsana Captcha, pouzij prosim: /captcha CAPTCHA_TEXT' +wrong_captcha: '&cSpatne opsana Captcha, pouzij prosim: /captcha THE_CAPTCHA' valid_captcha: '&cZadana captcha je v poradku!' kick_forvip: '&cVIP Hrac se pripojil na plny server!' kick_fullserver: '&cServer je plne obsazen, zkus to pozdeji prosim!' diff --git a/src/main/resources/messages/messages_es.yml b/src/main/resources/messages/messages_es.yml index 850d750a..a7066330 100644 --- a/src/main/resources/messages/messages_es.yml +++ b/src/main/resources/messages/messages_es.yml @@ -39,7 +39,7 @@ regex: '&cTu usuario tiene carácteres no admitidos, los cuales son: REG_EX' add_email: '&cPor favor agrega tu e-mail con: /email add tuEmail confirmarEmail' recovery_email: '&c¿Olvidaste tu contraseña? Por favor usa /email recovery ' usage_captcha: '&cUso: /captcha ' -wrong_captcha: '&cCaptcha incorrecto, please use : /captcha EL_CAPTCHA' +wrong_captcha: '&cCaptcha incorrecto, please use : /captcha THE_CAPTCHA' valid_captcha: '&c¡ Captcha ingresado correctamente !' kick_forvip: '&cUn jugador VIP ha ingresado al servidor lleno!' kick_fullserver: '&cEl servidor está lleno, lo sentimos!' diff --git a/src/test/java/fr/xephi/authme/output/MessagesIntegrationTest.java b/src/test/java/fr/xephi/authme/output/MessagesIntegrationTest.java index aa7367e2..343a5687 100644 --- a/src/test/java/fr/xephi/authme/output/MessagesIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/output/MessagesIntegrationTest.java @@ -2,9 +2,11 @@ package fr.xephi.authme.output; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.util.WrapperMock; +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 java.io.File; @@ -14,6 +16,8 @@ import static org.hamcrest.Matchers.arrayWithSize; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; /** @@ -137,4 +141,58 @@ public class MessagesIntegrationTest { verify(player).sendMessage(line); } } + + @Test + public void shouldSendMessageToPlayerWithTagReplacement() { + // given + MessageKey key = MessageKey.CAPTCHA_WRONG_ERROR; + CommandSender sender = Mockito.mock(CommandSender.class); + + // when + 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")); + } + + @Test + public void shouldNotThrowForKeyWithNoTagReplacements() { + // given + MessageKey key = MessageKey.CAPTCHA_WRONG_ERROR; + CommandSender sender = mock(CommandSender.class); + + // when + 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")); + } + + @Test(expected = RuntimeException.class) + public void shouldThrowForInvalidReplacementCount() { + // given + MessageKey key = MessageKey.CAPTCHA_WRONG_ERROR; + + // when + messages.send(mock(CommandSender.class), key, "rep", "rep2"); + + // then - expect exception + } + + @Test(expected = RuntimeException.class) + public void shouldThrowForReplacementsOnKeyWithNoTags() { + // given + MessageKey key = MessageKey.UNKNOWN_USER; + + // when + messages.send(mock(CommandSender.class), key, "Replacement"); + + // then - expect exception + } } diff --git a/src/test/resources/messages_test.yml b/src/test/resources/messages_test.yml index 23dd12bd..73aea93e 100644 --- a/src/test/resources/messages_test.yml +++ b/src/test/resources/messages_test.yml @@ -4,3 +4,4 @@ not_logged_in: 'Apostrophes '' should be loaded correctly, don''t you think?' reg_voluntarily: 'You can register yourself to the server with the command "/register "' usage_log: '&cUsage: /login ' wrong_pwd: '&cWrong password!' +wrong_captcha: 'Use /captcha THE_CAPTCHA to solve the captcha' From 879aa24a6ef8cdc78c5b08f19cf8bb1c590bef73 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Wed, 16 Dec 2015 22:48:06 +0100 Subject: [PATCH 15/17] Minor - fix spelling in messages return to the player --- .../java/fr/xephi/authme/listener/AuthMePlayerListener.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java b/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java index e49215b3..337e13ec 100644 --- a/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java +++ b/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java @@ -229,7 +229,7 @@ public class AuthMePlayerListener implements Listener { if (auth != null && !auth.getRealName().equals("Player") && !auth.getRealName().equals(event.getName())) { event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER); event.setKickMessage("You should join using username: " + ChatColor.AQUA + auth.getRealName() + - ChatColor.RESET + "\nnot :" + ChatColor.RED + event.getName()); // TODO: write a better message + ChatColor.RESET + "\nnot: " + ChatColor.RED + event.getName()); // TODO: write a better message return; } @@ -288,7 +288,7 @@ public class AuthMePlayerListener implements Listener { pl.kickPlayer(m.retrieveSingle(MessageKey.KICK_FOR_VIP)); event.allow(); } else { - ConsoleLogger.info("The player " + event.getPlayer().getName() + " tryed to join, but the server was full"); + ConsoleLogger.info("The player " + event.getPlayer().getName() + " tried to join, but the server was full"); event.setKickMessage(m.retrieveSingle(MessageKey.KICK_FULL_SERVER)); event.setResult(PlayerLoginEvent.Result.KICK_FULL); } From f1950543034369b9d54aeb5f44abb9f81717b24e Mon Sep 17 00:00:00 2001 From: Gabriele C Date: Wed, 16 Dec 2015 23:58:21 +0100 Subject: [PATCH 16/17] Should fix the /register auto-login feature --- .../fr/xephi/authme/process/register/AsyncRegister.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 668c0e3d..fb102ec9 100644 --- a/src/main/java/fr/xephi/authme/process/register/AsyncRegister.java +++ b/src/main/java/fr/xephi/authme/process/register/AsyncRegister.java @@ -141,8 +141,10 @@ public class AsyncRegister { return; } if (!Settings.forceRegLogin) { - PlayerCache.getInstance().addPlayer(auth); - database.setLogged(name); + //PlayerCache.getInstance().addPlayer(auth); + //database.setLogged(name); + // TODO: check this... + plugin.getManagement().performLogin(player, "dontneed", true); } plugin.otherAccounts.addPlayer(player.getUniqueId()); ProcessSyncPasswordRegister sync = new ProcessSyncPasswordRegister(player, plugin); From 21d25e5ad34e23eb6078ac35a93214f3aec69f1d Mon Sep 17 00:00:00 2001 From: Xephi Date: Thu, 17 Dec 2015 18:56:58 +0100 Subject: [PATCH 17/17] Add email.html to resources --- pom.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pom.xml b/pom.xml index e92495db..574f362f 100644 --- a/pom.xml +++ b/pom.xml @@ -90,6 +90,14 @@ plugin.yml + + . + true + src/main/resources/ + + email.html + + . false