From d727def4badda82101099be4b3e5ed07ebee769e Mon Sep 17 00:00:00 2001 From: Gabriele C Date: Sun, 14 Feb 2016 17:06:52 +0100 Subject: [PATCH 01/13] Move the command --- src/main/java/fr/xephi/authme/command/CommandInitializer.java | 4 ++-- .../executable/{converter => authme}/ConverterCommand.java | 2 +- .../java/fr/xephi/authme/converter/ForceFlatToSqlite.java | 2 -- .../java/fr/xephi/authme/listener/AuthMePlayerListener.java | 1 - .../java/fr/xephi/authme/process/join/AsynchronousJoin.java | 1 - .../java/fr/xephi/authme/process/login/AsynchronousLogin.java | 1 - .../java/fr/xephi/authme/process/register/AsyncRegister.java | 2 -- 7 files changed, 3 insertions(+), 10 deletions(-) rename src/main/java/fr/xephi/authme/command/executable/{converter => authme}/ConverterCommand.java (98%) diff --git a/src/main/java/fr/xephi/authme/command/CommandInitializer.java b/src/main/java/fr/xephi/authme/command/CommandInitializer.java index 12d07f9e..d89864ce 100644 --- a/src/main/java/fr/xephi/authme/command/CommandInitializer.java +++ b/src/main/java/fr/xephi/authme/command/CommandInitializer.java @@ -5,6 +5,7 @@ import fr.xephi.authme.command.executable.HelpCommand; import fr.xephi.authme.command.executable.authme.AccountsCommand; import fr.xephi.authme.command.executable.authme.AuthMeCommand; import fr.xephi.authme.command.executable.authme.ChangePasswordAdminCommand; +import fr.xephi.authme.command.executable.authme.ConverterCommand; import fr.xephi.authme.command.executable.authme.FirstSpawnCommand; import fr.xephi.authme.command.executable.authme.ForceLoginCommand; import fr.xephi.authme.command.executable.authme.GetEmailCommand; @@ -24,7 +25,6 @@ import fr.xephi.authme.command.executable.authme.UnregisterAdminCommand; import fr.xephi.authme.command.executable.authme.VersionCommand; import fr.xephi.authme.command.executable.captcha.CaptchaCommand; import fr.xephi.authme.command.executable.changepassword.ChangePasswordCommand; -import fr.xephi.authme.command.executable.converter.ConverterCommand; import fr.xephi.authme.command.executable.email.AddEmailCommand; import fr.xephi.authme.command.executable.email.ChangeEmailCommand; import fr.xephi.authme.command.executable.email.EmailBaseCommand; @@ -383,7 +383,7 @@ public final class CommandInitializer { // Register the base converter command CommandDescription CONVERTER_BASE = CommandDescription.builder() - .parent(null) + .parent(AUTHME_BASE) .labels("converter", "convert", "conv") .description("Converter Command") .detailedDescription("Converter command for AuthMeReloaded.") diff --git a/src/main/java/fr/xephi/authme/command/executable/converter/ConverterCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java similarity index 98% rename from src/main/java/fr/xephi/authme/command/executable/converter/ConverterCommand.java rename to src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java index cb3f6c7f..e3414480 100644 --- a/src/main/java/fr/xephi/authme/command/executable/converter/ConverterCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java @@ -1,4 +1,4 @@ -package fr.xephi.authme.command.executable.converter; +package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; import fr.xephi.authme.command.CommandService; diff --git a/src/main/java/fr/xephi/authme/converter/ForceFlatToSqlite.java b/src/main/java/fr/xephi/authme/converter/ForceFlatToSqlite.java index 443e20ac..c87297d8 100644 --- a/src/main/java/fr/xephi/authme/converter/ForceFlatToSqlite.java +++ b/src/main/java/fr/xephi/authme/converter/ForceFlatToSqlite.java @@ -7,8 +7,6 @@ import fr.xephi.authme.datasource.DataSourceType; import fr.xephi.authme.datasource.SQLite; import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.settings.properties.DatabaseSettings; -import fr.xephi.authme.util.StringUtils; - import java.sql.SQLException; /** diff --git a/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java b/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java index b15007e6..fc6a1540 100644 --- a/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java +++ b/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java @@ -12,7 +12,6 @@ import fr.xephi.authme.cache.limbo.LimboPlayer; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; import fr.xephi.authme.permission.PermissionsManager; -import fr.xephi.authme.permission.PlayerPermission; import fr.xephi.authme.permission.PlayerStatePermission; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.util.GeoLiteAPI; 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 052045b6..5d65929a 100644 --- a/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java +++ b/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java @@ -12,7 +12,6 @@ import fr.xephi.authme.events.SpawnTeleportEvent; import fr.xephi.authme.listener.AuthMePlayerListener; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; -import fr.xephi.authme.permission.PlayerPermission; import fr.xephi.authme.permission.PlayerStatePermission; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Spawn; 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 19b75f34..7ac10e25 100644 --- a/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java +++ b/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java @@ -23,7 +23,6 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; -import java.util.Date; import java.util.List; /** 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 29616fe5..c9ce3f6c 100644 --- a/src/main/java/fr/xephi/authme/process/register/AsyncRegister.java +++ b/src/main/java/fr/xephi/authme/process/register/AsyncRegister.java @@ -1,13 +1,11 @@ package fr.xephi.authme.process.register; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; -import fr.xephi.authme.permission.PlayerPermission; import fr.xephi.authme.permission.PlayerStatePermission; import fr.xephi.authme.security.HashAlgorithm; import fr.xephi.authme.security.crypts.HashedPassword; From 15792f01e934eb0b0de73d631127afa38ada34df Mon Sep 17 00:00:00 2001 From: Gabriele C Date: Sun, 14 Feb 2016 17:38:13 +0100 Subject: [PATCH 02/13] Fix docs --- README.md | 2 +- src/main/resources/plugin.yml | 5 +---- src/tools/docs/commands.md | 4 ++-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index c862068f..ff0b7f4d 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ typing commands or using the inventory. It can also kick players with uncommonly
  • Website Integration
  • Click here for an example of the Config file
  • How to convert from Rakamak -
  • Convert from FlatFile (auths.db but not the sqlite one) to MySQL: /converter +
  • Convert from FlatFile (auths.db but not the sqlite one) to MySQL: /authme converter

  • diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index be7b792f..bf63b364 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -16,7 +16,7 @@ softdepend: commands: authme: description: AuthMe op commands - usage: '/authme reload|register playername password|changepassword playername password|unregister playername|version' + usage: '/authme reload|register playername password|changepassword playername password|unregister playername|version|converter' register: description: Register an account usage: /register @@ -40,9 +40,6 @@ commands: captcha: description: Captcha command usage: /captcha - converter: - description: Converter from different other auth plugins - usage: /converter permissions: authme.admin.*: description: Give access to all admin commands. diff --git a/src/tools/docs/commands.md b/src/tools/docs/commands.md index 39efe977..34a743d3 100644 --- a/src/tools/docs/commands.md +++ b/src/tools/docs/commands.md @@ -70,7 +70,7 @@ brackets; optional arguments are enclosed in square brackets (`[ ]`). - **/captcha** <captcha>: Captcha command for AuthMeReloaded.
    Requires `authme.player.captcha` - **/captcha help** [query]: View detailed help pages about AuthMeReloaded captcha commands. -- **/converter** <job>: Converter command for AuthMeReloaded. +- **/authme converter** <job>: Converter command for AuthMeReloaded.
    Requires `authme.admin.converter` -- **/converter help** [query]: View detailed help pages about AuthMeReloaded converter commands. +- **/authme converter help** [query]: View detailed help pages about AuthMeReloaded converter commands. From edc20debea0a3dcc7ff67db6ef38d40b7088e47c Mon Sep 17 00:00:00 2001 From: DNx5 Date: Fri, 19 Feb 2016 21:55:53 +0700 Subject: [PATCH 03/13] Going back to GeoIP legacy. :) --- pom.xml | 6 ++-- .../java/fr/xephi/authme/util/GeoLiteAPI.java | 31 +++++++------------ 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/pom.xml b/pom.xml index 0ed8714c..64877be4 100644 --- a/pom.xml +++ b/pom.xml @@ -416,9 +416,9 @@ - com.maxmind.geoip2 - geoip2 - 2.6.0 + com.maxmind.geoip + geoip-api + 1.3.1 compile true diff --git a/src/main/java/fr/xephi/authme/util/GeoLiteAPI.java b/src/main/java/fr/xephi/authme/util/GeoLiteAPI.java index 065d1961..f878d85a 100644 --- a/src/main/java/fr/xephi/authme/util/GeoLiteAPI.java +++ b/src/main/java/fr/xephi/authme/util/GeoLiteAPI.java @@ -1,6 +1,6 @@ package fr.xephi.authme.util; -import com.maxmind.geoip2.DatabaseReader; +import com.maxmind.geoip.LookupService; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.settings.Settings; @@ -9,18 +9,17 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.net.InetAddress; import java.net.URL; import java.net.URLConnection; import java.util.concurrent.TimeUnit; import java.util.zip.GZIPInputStream; public class GeoLiteAPI { - - private static final String LICENSE = "[LICENSE] This product includes GeoLite2 data created by MaxMind," + - " available from http://www.maxmind.com"; - private static final String GEOIP_URL = "http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz"; - private static DatabaseReader databaseReader; + private static final String LICENSE = + "[LICENSE] This product uses data from the GeoLite API created by MaxMind, available at http://www.maxmind.com"; + private static final String GEOIP_URL = + "http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz"; + private static LookupService lookupService; private static Thread downloadTask; /** @@ -32,17 +31,17 @@ public class GeoLiteAPI { if (downloadTask != null && downloadTask.isAlive()) { return false; } - if (databaseReader != null) { + if (lookupService != null) { return true; } - final File data = new File(Settings.PLUGIN_FOLDER, "GeoLite2-Country.mmdb"); + final File data = new File(Settings.PLUGIN_FOLDER, "GeoIP.dat"); boolean dataIsOld = (System.currentTimeMillis() - data.lastModified()) > TimeUnit.DAYS.toMillis(30); if (dataIsOld && !data.delete()) { ConsoleLogger.showError("Failed to delete GeoLiteAPI database"); } if (data.exists()) { try { - databaseReader = new DatabaseReader.Builder(data).build(); + lookupService = new LookupService(data); ConsoleLogger.info(LICENSE); return true; } catch (IOException e) { @@ -90,11 +89,7 @@ public class GeoLiteAPI { */ public static String getCountryCode(String ip) { if (!"127.0.0.1".equals(ip) && isDataAvailable()) { - try { - return databaseReader.country(InetAddress.getByName(ip)).getCountry().getIsoCode(); - } catch (Exception e) { - ConsoleLogger.writeStackTrace(e); - } + return lookupService.getCountry(ip).getCode(); } return "--"; } @@ -108,11 +103,7 @@ public class GeoLiteAPI { */ public static String getCountryName(String ip) { if (!"127.0.0.1".equals(ip) && isDataAvailable()) { - try { - return databaseReader.country(InetAddress.getByName(ip)).getCountry().getName(); - } catch (Exception e) { - ConsoleLogger.writeStackTrace(e); - } + return lookupService.getCountry(ip).getName(); } return "N/A"; } From 1714b416571d29aeabdcfd880b9ab581c625f600 Mon Sep 17 00:00:00 2001 From: Gabriele C Date: Fri, 19 Feb 2016 16:30:31 +0100 Subject: [PATCH 04/13] Update dependencies --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 64877be4..e5d70cd1 100644 --- a/pom.xml +++ b/pom.xml @@ -372,7 +372,7 @@ org.slf4j slf4j-jdk14 - 1.7.14 + 1.7.16 compile true @@ -400,7 +400,7 @@ com.google.code.gson gson - 2.5 + 2.6.1 compile true From 715622826f1e67ec50c63fadab90ffdbef1c468f Mon Sep 17 00:00:00 2001 From: Gabriele C Date: Fri, 19 Feb 2016 16:38:18 +0100 Subject: [PATCH 05/13] Fix command registration --- .../authme/command/CommandInitializer.java | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/main/java/fr/xephi/authme/command/CommandInitializer.java b/src/main/java/fr/xephi/authme/command/CommandInitializer.java index d89864ce..0f73effa 100644 --- a/src/main/java/fr/xephi/authme/command/CommandInitializer.java +++ b/src/main/java/fr/xephi/authme/command/CommandInitializer.java @@ -269,6 +269,17 @@ public final class CommandInitializer { .executableCommand(new VersionCommand()) .build(); + CommandDescription.builder() + .parent(AUTHME_BASE) + .labels("converter", "convert", "conv") + .description("Converter Command") + .detailedDescription("Converter command for AuthMeReloaded.") + .withArgument("job", "Conversion job: xauth / crazylogin / rakamak / " + + "royalauth / vauth / sqlitetosql", false) + .permissions(OP_ONLY, AdminPermission.CONVERTER) + .executableCommand(new ConverterCommand()) + .build(); + // Register the base login command final CommandDescription LOGIN_BASE = CommandDescription.builder() .parent(null) @@ -381,18 +392,6 @@ public final class CommandInitializer { .executableCommand(new CaptchaCommand()) .build(); - // Register the base converter command - CommandDescription CONVERTER_BASE = CommandDescription.builder() - .parent(AUTHME_BASE) - .labels("converter", "convert", "conv") - .description("Converter Command") - .detailedDescription("Converter command for AuthMeReloaded.") - .withArgument("job", "Conversion job: xauth / crazylogin / rakamak / " + - "royalauth / vauth / sqlitetosql", false) - .permissions(OP_ONLY, AdminPermission.CONVERTER) - .executableCommand(new ConverterCommand()) - .build(); - Set baseCommands = ImmutableSet.of( AUTHME_BASE, LOGIN_BASE, @@ -401,8 +400,7 @@ public final class CommandInitializer { UNREGISTER_BASE, CHANGE_PASSWORD_BASE, EMAIL_BASE, - CAPTCHA_BASE, - CONVERTER_BASE); + CAPTCHA_BASE); setHelpOnAllBases(baseCommands); return baseCommands; From 4620ead3115ff053c3fd43e88c1ef58ee5c023e5 Mon Sep 17 00:00:00 2001 From: Gabriele C Date: Fri, 19 Feb 2016 16:42:48 +0100 Subject: [PATCH 06/13] Fix number of commands in test --- .../java/fr/xephi/authme/command/CommandInitializerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java b/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java index f8b0d256..62c2b890 100644 --- a/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java +++ b/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java @@ -50,7 +50,7 @@ public class CommandInitializerTest { // It obviously doesn't make sense to test much of the concrete data // that is being initialized; we just want to guarantee with this test // that data is indeed being initialized and we take a few "probes" - assertThat(commands.size(), equalTo(9)); + assertThat(commands.size(), equalTo(8)); assertThat(commandsIncludeLabel(commands, "authme"), equalTo(true)); assertThat(commandsIncludeLabel(commands, "register"), equalTo(true)); assertThat(commandsIncludeLabel(commands, "help"), equalTo(false)); From 6dfdcf103b1ee7bb6e205c07e366bb0a79d24751 Mon Sep 17 00:00:00 2001 From: DNx5 Date: Fri, 19 Feb 2016 22:40:37 +0700 Subject: [PATCH 07/13] I forget this one, Fix #507 --- .../java/fr/xephi/authme/listener/AuthMeServerListener.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/fr/xephi/authme/listener/AuthMeServerListener.java b/src/main/java/fr/xephi/authme/listener/AuthMeServerListener.java index e6874d4d..5d080ef6 100644 --- a/src/main/java/fr/xephi/authme/listener/AuthMeServerListener.java +++ b/src/main/java/fr/xephi/authme/listener/AuthMeServerListener.java @@ -28,17 +28,13 @@ public class AuthMeServerListener implements Listener { @EventHandler(priority = EventPriority.HIGHEST) public void onServerPing(ServerListPingEvent event) { - if (!Settings.enableProtection) { - return; - } - if (!Settings.countriesBlacklist.isEmpty() || !Settings.countries.isEmpty()){ String countryCode = GeoLiteAPI.getCountryCode(event.getAddress().getHostAddress()); if( Settings.countriesBlacklist.contains(countryCode)) { event.setMotd(m.retrieveSingle(MessageKey.COUNTRY_BANNED_ERROR)); return; } - if (!Settings.countries.contains(countryCode)) { + if (Settings.enableProtection && !Settings.countries.contains(countryCode)) { event.setMotd(m.retrieveSingle(MessageKey.COUNTRY_BANNED_ERROR)); } } From 05e79e6356245560a199245a6caaf9f539ef071a Mon Sep 17 00:00:00 2001 From: DNx5 Date: Fri, 19 Feb 2016 23:25:25 +0700 Subject: [PATCH 08/13] Fix email not getting updated in database #527 --- .../java/fr/xephi/authme/process/email/AsyncAddEmail.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/fr/xephi/authme/process/email/AsyncAddEmail.java b/src/main/java/fr/xephi/authme/process/email/AsyncAddEmail.java index c7673f70..9dace0f2 100644 --- a/src/main/java/fr/xephi/authme/process/email/AsyncAddEmail.java +++ b/src/main/java/fr/xephi/authme/process/email/AsyncAddEmail.java @@ -46,10 +46,12 @@ public class AsyncAddEmail { messages.send(player, MessageKey.INVALID_EMAIL); } else if (dataSource.isEmailStored(email)) { messages.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR); - } else { + } else if (dataSource.updateEmail(auth)) { auth.setEmail(email); playerCache.updatePlayer(auth); messages.send(player, MessageKey.EMAIL_ADDED_SUCCESS); + } else { + messages.send(player, MessageKey.ERROR); } } else { sendUnloggedMessage(dataSource); From 5795b9d8fd3efb64f552c15715e824d265084ab7 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Fri, 19 Feb 2016 19:13:49 +0100 Subject: [PATCH 09/13] #533 Add integration sample for BCrypt --- samples/website_integration/bcrypt/form.php | 86 ++++++++++++++ .../bcrypt/integration.php | 107 ++++++++++++++++++ .../website_integration/{ => sha256}/form.php | 4 +- .../{ => sha256}/integration.php | 2 +- 4 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 samples/website_integration/bcrypt/form.php create mode 100644 samples/website_integration/bcrypt/integration.php rename samples/website_integration/{ => sha256}/form.php (91%) rename samples/website_integration/{ => sha256}/integration.php (97%) diff --git a/samples/website_integration/bcrypt/form.php b/samples/website_integration/bcrypt/form.php new file mode 100644 index 00000000..7801be4d --- /dev/null +++ b/samples/website_integration/bcrypt/form.php @@ -0,0 +1,86 @@ + + + + + AuthMe Integration Sample + + + +Login sample +This is a demo form for AuthMe website integration. Enter your AuthMe login details +into the following form to test it. +
    + + + + + + + +
    Name
    Pass
    +
    '; +} + +function get_from_post_or_empty($index_name) { + return trim( + filter_input(INPUT_POST, $index_name, FILTER_UNSAFE_RAW, FILTER_REQUIRE_SCALAR | FILTER_FLAG_STRIP_LOW) + ?: ''); +} + + +// Login logic +function process_login($user, $pass) { + if (authme_check_password($user, $pass)) { + printf('

    Hello, %s!

    ', htmlspecialchars($user)); + echo 'Successful login. Nice to have you back!' + . '
    Back to form'; + return true; + } else { + echo '

    Error

    Invalid username or password.'; + } + return false; +} + +// Register logic +function process_register($user, $pass) { + if (authme_has_user($user)) { + echo '

    Error

    This user already exists.'; + } else { + // Note that we don't validate the password or username at all in this demo... + $register_success = authme_register($user, $pass); + if ($register_success) { + printf('

    Welcome, %s!

    Thanks for registering', htmlspecialchars($user)); + echo '
    Back to form'; + return true; + } else { + echo '

    Error

    Unfortunately, there was an error during the registration.'; + } + } + return false; +} + +?> + + + diff --git a/samples/website_integration/bcrypt/integration.php b/samples/website_integration/bcrypt/integration.php new file mode 100644 index 00000000..75911838 --- /dev/null +++ b/samples/website_integration/bcrypt/integration.php @@ -0,0 +1,107 @@ +prepare('SELECT password FROM ' . AUTHME_TABLE . ' WHERE username = ?'); + $stmt->bind_param('s', $username); + $stmt->execute(); + $stmt->bind_result($password); + if ($stmt->fetch()) { + return $password; + } + } + return null; +} + +/** + * Returns whether the user exists in the database or not. + * + * @param string $username the username to check + * @return bool true if the user exists; false otherwise + */ +function authme_has_user($username) { + $mysqli = authme_get_mysqli(); + if ($mysqli !== null) { + $stmt = $mysqli->prepare('SELECT 1 FROM ' . AUTHME_TABLE . ' WHERE username = ?'); + $stmt->bind_param('s', $username); + $stmt->execute(); + return $stmt->fetch(); + } + + // Defensive default to true; we actually don't know + return true; +} + +/** + * Registers a player with the given username. + * + * @param string $username the username to register + * @param string $password the password to associate to the user + * @return bool whether or not the registration was successful + */ +function authme_register($username, $password) { + $mysqli = authme_get_mysqli(); + if ($mysqli !== null) { + $hash = password_hash($password, PASSWORD_BCRYPT); + $stmt = $mysqli->prepare('INSERT INTO ' . AUTHME_TABLE . ' (username, realname, password, ip) ' + . 'VALUES (?, ?, ?, ?)'); + $username_low = strtolower($username); + $stmt->bind_param('ssss', $username, $username_low, $hash, $_SERVER['REMOTE_ADDR']); + return $stmt->execute(); + } + return false; +} + diff --git a/samples/website_integration/form.php b/samples/website_integration/sha256/form.php similarity index 91% rename from samples/website_integration/form.php rename to samples/website_integration/sha256/form.php index 5f2985cb..5ffecf34 100644 --- a/samples/website_integration/form.php +++ b/samples/website_integration/sha256/form.php @@ -1,5 +1,5 @@ @@ -36,7 +36,7 @@ into the following form to test it. -
    Name
    Pass
    +
    '; } diff --git a/samples/website_integration/integration.php b/samples/website_integration/sha256/integration.php similarity index 97% rename from samples/website_integration/integration.php rename to samples/website_integration/sha256/integration.php index 3008fb98..e0de0bb1 100644 --- a/samples/website_integration/integration.php +++ b/samples/website_integration/sha256/integration.php @@ -1,6 +1,6 @@ Date: Fri, 19 Feb 2016 19:26:16 +0100 Subject: [PATCH 10/13] Update add email tests (#527) --- .../process/email/AsyncAddEmailTest.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/test/java/fr/xephi/authme/process/email/AsyncAddEmailTest.java b/src/test/java/fr/xephi/authme/process/email/AsyncAddEmailTest.java index 4aea5e57..fb4c7fd5 100644 --- a/src/test/java/fr/xephi/authme/process/email/AsyncAddEmailTest.java +++ b/src/test/java/fr/xephi/authme/process/email/AsyncAddEmailTest.java @@ -56,16 +56,38 @@ public class AsyncAddEmailTest { given(auth.getEmail()).willReturn(null); given(playerCache.getAuth("tester")).willReturn(auth); given(dataSource.isEmailStored("my.mail@example.org")).willReturn(false); + given(dataSource.updateEmail(any(PlayerAuth.class))).willReturn(true); // when process.process(); // then + verify(dataSource).updateEmail(auth); verify(messages).send(player, MessageKey.EMAIL_ADDED_SUCCESS); verify(auth).setEmail("my.mail@example.org"); verify(playerCache).updatePlayer(auth); } + @Test + public void shouldReturnErrorWhenMailCannotBeSaved() { + // given + AsyncAddEmail process = createProcess("my.mail@example.org"); + given(player.getName()).willReturn("testEr"); + given(playerCache.isAuthenticated("tester")).willReturn(true); + PlayerAuth auth = mock(PlayerAuth.class); + given(auth.getEmail()).willReturn(null); + given(playerCache.getAuth("tester")).willReturn(auth); + given(dataSource.isEmailStored("my.mail@example.org")).willReturn(false); + given(dataSource.updateEmail(any(PlayerAuth.class))).willReturn(false); + + // when + process.process(); + + // then + verify(dataSource).updateEmail(auth); + verify(messages).send(player, MessageKey.ERROR); + } + @Test public void shouldNotAddMailIfPlayerAlreadyHasEmail() { // given From 6f694cf818347be57611943857bff486ddadbd44 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Fri, 19 Feb 2016 21:47:52 +0100 Subject: [PATCH 11/13] #527 Persist email after changing it --- .../xephi/authme/process/email/AsyncAddEmail.java | 14 +++++++++----- .../authme/process/email/AsyncAddEmailTest.java | 2 ++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/fr/xephi/authme/process/email/AsyncAddEmail.java b/src/main/java/fr/xephi/authme/process/email/AsyncAddEmail.java index 9dace0f2..d5908820 100644 --- a/src/main/java/fr/xephi/authme/process/email/AsyncAddEmail.java +++ b/src/main/java/fr/xephi/authme/process/email/AsyncAddEmail.java @@ -1,6 +1,7 @@ package fr.xephi.authme.process.email; import fr.xephi.authme.AuthMe; +import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.datasource.DataSource; @@ -46,12 +47,15 @@ public class AsyncAddEmail { messages.send(player, MessageKey.INVALID_EMAIL); } else if (dataSource.isEmailStored(email)) { messages.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR); - } else if (dataSource.updateEmail(auth)) { - auth.setEmail(email); - playerCache.updatePlayer(auth); - messages.send(player, MessageKey.EMAIL_ADDED_SUCCESS); } else { - messages.send(player, MessageKey.ERROR); + auth.setEmail(email); + if (dataSource.updateEmail(auth)) { + playerCache.updatePlayer(auth); + messages.send(player, MessageKey.EMAIL_ADDED_SUCCESS); + } else { + ConsoleLogger.showError("Could not save email for player '" + player + "'"); + messages.send(player, MessageKey.ERROR); + } } } else { sendUnloggedMessage(dataSource); diff --git a/src/test/java/fr/xephi/authme/process/email/AsyncAddEmailTest.java b/src/test/java/fr/xephi/authme/process/email/AsyncAddEmailTest.java index fb4c7fd5..7cc7c55d 100644 --- a/src/test/java/fr/xephi/authme/process/email/AsyncAddEmailTest.java +++ b/src/test/java/fr/xephi/authme/process/email/AsyncAddEmailTest.java @@ -1,6 +1,7 @@ package fr.xephi.authme.process.email; import fr.xephi.authme.AuthMe; +import fr.xephi.authme.ConsoleLoggerTestInitializer; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.datasource.DataSource; @@ -35,6 +36,7 @@ public class AsyncAddEmailTest { @BeforeClass public static void setUp() { WrapperMock.createInstance(); + ConsoleLoggerTestInitializer.setupLogger(); } // Clean up the fields to ensure that no test uses elements of another test From 90e0dc18751c7d1a58fd4e970d1b33a77a1961d9 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Fri, 19 Feb 2016 23:09:55 +0100 Subject: [PATCH 12/13] Various code householding - Remove unused API on DataSource - Add some sensible javadoc to DataSource - Minor code simplification --- .../executable/authme/AccountsCommand.java | 2 +- .../authme/datasource/CacheDataSource.java | 23 ---- .../xephi/authme/datasource/DataSource.java | 123 +++++++----------- .../fr/xephi/authme/datasource/FlatFile.java | 106 --------------- .../fr/xephi/authme/datasource/MySQL.java | 60 +-------- .../fr/xephi/authme/datasource/SQLite.java | 61 +-------- .../process/login/AsynchronousLogin.java | 2 +- .../process/register/AsyncRegister.java | 11 +- .../authme/AccountsCommandTest.java | 18 ++- .../xephi/authme/settings/NewSettingTest.java | 21 +-- 10 files changed, 77 insertions(+), 350 deletions(-) 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 5d4d8cda..d3698cfd 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 @@ -30,7 +30,7 @@ public class AccountsCommand implements ExecutableCommand { return; } - List accountList = commandService.getDataSource().getAllAuthsByName(auth); + List accountList = commandService.getDataSource().getAllAuthsByIp(auth.getIp()); if (accountList.isEmpty()) { commandService.send(sender, MessageKey.USER_NOT_REGISTERED); } else if (accountList.size() == 1) { diff --git a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java index fd743289..57fb7fe5 100644 --- a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java +++ b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java @@ -115,24 +115,6 @@ public class CacheDataSource implements DataSource { return result; } - @Override - public int getIps(String ip) { - return source.getIps(ip); - } - - @Override - public int purgeDatabase(long until) { - int cleared = source.purgeDatabase(until); - if (cleared > 0) { - for (Optional auth : cachedAuths.asMap().values()) { - if (auth.isPresent() && auth.get().getLastLogin() < until) { - cachedAuths.invalidate(auth.get().getNickname()); - } - } - } - return cleared; - } - @Override public List autoPurgeDatabase(long until) { List cleared = source.autoPurgeDatabase(until); @@ -172,11 +154,6 @@ public class CacheDataSource implements DataSource { return result; } - @Override - public synchronized List getAllAuthsByName(PlayerAuth auth) { - return source.getAllAuthsByName(auth); - } - @Override public synchronized List getAllAuthsByIp(final String ip) { return source.getAllAuthsByIp(ip); diff --git a/src/main/java/fr/xephi/authme/datasource/DataSource.java b/src/main/java/fr/xephi/authme/datasource/DataSource.java index ab46051c..8a22ffdd 100644 --- a/src/main/java/fr/xephi/authme/datasource/DataSource.java +++ b/src/main/java/fr/xephi/authme/datasource/DataSource.java @@ -6,146 +6,119 @@ import fr.xephi.authme.security.crypts.HashedPassword; import java.util.List; /** + * Interface for manipulating {@link PlayerAuth} objects from a data source. */ public interface DataSource { /** - * Method isAuthAvailable. + * Return whether there is a record for the given username. * - * @param user String - * - * @return boolean + * @param user The username to look up + * @return True if there is a record, false otherwise */ boolean isAuthAvailable(String user); /** - * Method getPassword. + * Return the hashed password of the player. * - * @param user String - * - * @return String + * @param user The user whose password should be retrieve + * @return The password hash of the player */ HashedPassword getPassword(String user); /** - * Method getAuth. + * Retrieve the entire PlayerAuth object associated with the username. * - * @param user String - * - * @return PlayerAuth + * @param user The user to retrieve + * @return The PlayerAuth object for the given username */ PlayerAuth getAuth(String user); /** - * Method saveAuth. + * Save a new PlayerAuth object. * - * @param auth PlayerAuth - * - * @return boolean + * @param auth The new PlayerAuth to persist + * @return True upon success, false upon failure */ boolean saveAuth(PlayerAuth auth); /** - * Method updateSession. + * Update the session of a record (IP, last login, real name). * - * @param auth PlayerAuth - * - * @return boolean + * @param auth The PlayerAuth object to update in the database + * @return True upon success, false upon failure */ boolean updateSession(PlayerAuth auth); /** - * Method updatePassword. + * Update the password of the given PlayerAuth object. * - * @param auth PlayerAuth - * - * @return boolean + * @param auth The PlayerAuth whose password should be updated + * @return True upon success, false upon failure */ boolean updatePassword(PlayerAuth auth); + /** + * Update the password of the given player. + * + * @param user The user whose password should be updated + * @param password The new password + * @return True upon success, false upon failure + */ boolean updatePassword(String user, HashedPassword password); /** - * Method purgeDatabase. + * Purge all records in the database whose last login was longer ago than + * the given time. * - * @param until long - * - * @return int - */ - int purgeDatabase(long until); - - /** - * Method autoPurgeDatabase. - * - * @param until long - * - * @return List of String + * @param until The minimum last login + * @return The account names that have been removed */ List autoPurgeDatabase(long until); /** - * Method removeAuth. + * Remove a user record from the database. * - * @param user String - * - * @return boolean + * @param user The user to remove + * @return True upon success, false upon failure */ boolean removeAuth(String user); /** - * Method updateQuitLoc. + * Update the quit location of a PlayerAuth. * - * @param auth PlayerAuth - * - * @return boolean + * @param auth The entry whose quit location should be updated + * @return True upon success, false upon failure */ boolean updateQuitLoc(PlayerAuth auth); /** - * Method getIps. + * Return all usernames associated with the given IP address. * - * @param ip String - * - * @return int - */ - int getIps(String ip); - - /** - * Method getAllAuthsByName. - * - * @param auth PlayerAuth - * - * @return List of String - */ - List getAllAuthsByName(PlayerAuth auth); - - /** - * Method getAllAuthsByIp. - * - * @param ip String - * - * @return List of String * @throws Exception + * @param ip The IP address to look up + * @return Usernames associated with the given IP address */ List getAllAuthsByIp(String ip); /** - * Method getAllAuthsByEmail. + * Return all usernames associated with the given email address. * - * @param email String - * - * @return List of String * @throws Exception + * @param email The email address to look up + * @return Users using the given email address */ List getAllAuthsByEmail(String email); /** - * Method updateEmail. + * Update the email of the PlayerAuth in the data source. * - * @param auth PlayerAuth - * - * @return boolean + * @param auth The PlayerAuth whose email should be updated + * @return True upon success, false upon failure */ boolean updateEmail(PlayerAuth auth); + /** + * Close the underlying connections to the data source. + */ void close(); void reload(); diff --git a/src/main/java/fr/xephi/authme/datasource/FlatFile.java b/src/main/java/fr/xephi/authme/datasource/FlatFile.java index 6404e1c0..8fce0f8f 100644 --- a/src/main/java/fr/xephi/authme/datasource/FlatFile.java +++ b/src/main/java/fr/xephi/authme/datasource/FlatFile.java @@ -278,82 +278,6 @@ public class FlatFile implements DataSource { return true; } - @Override - public int getIps(String ip) { - BufferedReader br = null; - int countIp = 0; - try { - br = new BufferedReader(new FileReader(source)); - String line; - while ((line = br.readLine()) != null) { - String[] args = line.split(":"); - if (args.length > 3 && args[2].equals(ip)) { - countIp++; - } - } - return countIp; - } catch (FileNotFoundException ex) { - ConsoleLogger.showError(ex.getMessage()); - return 0; - } catch (IOException ex) { - ConsoleLogger.showError(ex.getMessage()); - return 0; - } finally { - if (br != null) { - try { - br.close(); - } catch (IOException ignored) { - } - } - } - } - - @Override - public int purgeDatabase(long until) { - BufferedReader br = null; - BufferedWriter bw = null; - ArrayList lines = new ArrayList<>(); - int cleared = 0; - try { - br = new BufferedReader(new FileReader(source)); - String line; - while ((line = br.readLine()) != null) { - String[] args = line.split(":"); - if (args.length >= 4) { - if (Long.parseLong(args[3]) >= until) { - lines.add(line); - continue; - } - } - cleared++; - } - bw = new BufferedWriter(new FileWriter(source)); - for (String l : lines) { - bw.write(l + "\n"); - } - } catch (FileNotFoundException ex) { - ConsoleLogger.showError(ex.getMessage()); - return cleared; - } catch (IOException ex) { - ConsoleLogger.showError(ex.getMessage()); - return cleared; - } finally { - if (br != null) { - try { - br.close(); - } catch (IOException ignored) { - } - } - if (bw != null) { - try { - bw.close(); - } catch (IOException ignored) { - } - } - } - return cleared; - } - @Override public List autoPurgeDatabase(long until) { BufferedReader br = null; @@ -532,36 +456,6 @@ public class FlatFile implements DataSource { return true; } - @Override - public List getAllAuthsByName(PlayerAuth auth) { - BufferedReader br = null; - List countIp = new ArrayList<>(); - try { - br = new BufferedReader(new FileReader(source)); - String line; - while ((line = br.readLine()) != null) { - String[] args = line.split(":"); - if (args.length > 3 && args[2].equals(auth.getIp())) { - countIp.add(args[0]); - } - } - return countIp; - } catch (FileNotFoundException ex) { - ConsoleLogger.showError(ex.getMessage()); - return new ArrayList<>(); - } catch (IOException ex) { - ConsoleLogger.showError(ex.getMessage()); - return new ArrayList<>(); - } finally { - if (br != null) { - try { - br.close(); - } catch (IOException ignored) { - } - } - } - } - @Override public List getAllAuthsByIp(String ip) { BufferedReader br = null; diff --git a/src/main/java/fr/xephi/authme/datasource/MySQL.java b/src/main/java/fr/xephi/authme/datasource/MySQL.java index 33fd0edd..78ec0327 100644 --- a/src/main/java/fr/xephi/authme/datasource/MySQL.java +++ b/src/main/java/fr/xephi/authme/datasource/MySQL.java @@ -562,16 +562,14 @@ public class MySQL implements DataSource { @Override public synchronized boolean updateSession(PlayerAuth auth) { - try (Connection con = getConnection()) { - String sql = "UPDATE " + tableName + " SET " - + col.IP + "=?, " + col.LAST_LOGIN + "=?, " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;"; - PreparedStatement pst = con.prepareStatement(sql); + String sql = "UPDATE " + tableName + " SET " + + col.IP + "=?, " + col.LAST_LOGIN + "=?, " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;"; + try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) { pst.setString(1, auth.getIp()); pst.setTimestamp(2, new Timestamp(auth.getLastLogin())); pst.setString(3, auth.getRealName()); pst.setString(4, auth.getNickname()); pst.executeUpdate(); - pst.close(); return true; } catch (SQLException ex) { logSqlException(ex); @@ -579,20 +577,6 @@ public class MySQL implements DataSource { return false; } - @Override - public synchronized int purgeDatabase(long until) { - int result = 0; - try (Connection con = getConnection()) { - String sql = "DELETE FROM " + tableName + " WHERE " + col.LAST_LOGIN + " autoPurgeDatabase(long until) { List list = new ArrayList<>(); @@ -669,25 +653,6 @@ public class MySQL implements DataSource { return false; } - @Override - public synchronized int getIps(String ip) { - int countIp = 0; - try (Connection con = getConnection()) { - String sql = "SELECT COUNT(*) FROM " + tableName + " WHERE " + col.IP + "=?;"; - PreparedStatement pst = con.prepareStatement(sql); - pst.setString(1, ip); - ResultSet rs = pst.executeQuery(); - while (rs.next()) { - countIp = rs.getInt(1); - } - rs.close(); - pst.close(); - } catch (SQLException ex) { - logSqlException(ex); - } - return countIp; - } - @Override public synchronized boolean updateEmail(PlayerAuth auth) { try (Connection con = getConnection()) { @@ -722,25 +687,6 @@ public class MySQL implements DataSource { } } - @Override - public synchronized List getAllAuthsByName(PlayerAuth auth) { - List result = new ArrayList<>(); - try (Connection con = getConnection()) { - String sql = "SELECT " + col.NAME + " FROM " + tableName + " WHERE " + col.IP + "=?;"; - PreparedStatement pst = con.prepareStatement(sql); - pst.setString(1, auth.getIp()); - ResultSet rs = pst.executeQuery(); - while (rs.next()) { - result.add(rs.getString(col.NAME)); - } - rs.close(); - pst.close(); - } catch (SQLException ex) { - logSqlException(ex); - } - return result; - } - @Override public synchronized List getAllAuthsByIp(String ip) { List result = new ArrayList<>(); diff --git a/src/main/java/fr/xephi/authme/datasource/SQLite.java b/src/main/java/fr/xephi/authme/datasource/SQLite.java index 033bb838..86a6d115 100644 --- a/src/main/java/fr/xephi/authme/datasource/SQLite.java +++ b/src/main/java/fr/xephi/authme/datasource/SQLite.java @@ -266,18 +266,6 @@ public class SQLite implements DataSource { return false; } - @Override - public int purgeDatabase(long until) { - String sql = "DELETE FROM " + tableName + " WHERE " + col.LAST_LOGIN + " autoPurgeDatabase(long until) { PreparedStatement pst = null; @@ -336,29 +324,6 @@ public class SQLite implements DataSource { return false; } - @Override - public int getIps(String ip) { - PreparedStatement pst = null; - ResultSet rs = null; - int countIp = 0; - try { - // TODO ljacqu 20151230: Simply fetch COUNT(1) and return that - pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + col.IP + "=?;"); - pst.setString(1, ip); - rs = pst.executeQuery(); - while (rs.next()) { - countIp++; - } - return countIp; - } catch (SQLException ex) { - logSqlException(ex); - } finally { - close(rs); - close(pst); - } - return 0; - } - @Override public boolean updateEmail(PlayerAuth auth) { String sql = "UPDATE " + tableName + " SET " + col.EMAIL + "=? WHERE " + col.NAME + "=?;"; @@ -406,37 +371,13 @@ public class SQLite implements DataSource { } } - @Override - public List getAllAuthsByName(PlayerAuth auth) { - PreparedStatement pst = null; - ResultSet rs = null; - List names = new ArrayList<>(); - try { - // TODO ljacqu 20160214: Use SELECT name if only the name is required - pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + col.IP + "=?;"); - pst.setString(1, auth.getIp()); - rs = pst.executeQuery(); - while (rs.next()) { - names.add(rs.getString(col.NAME)); - } - return names; - } catch (SQLException ex) { - logSqlException(ex); - - } finally { - close(rs); - close(pst); - } - return new ArrayList<>(); - } - @Override public List getAllAuthsByIp(String ip) { PreparedStatement pst = null; ResultSet rs = null; List countIp = new ArrayList<>(); try { - pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + col.IP + "=?;"); + pst = con.prepareStatement("SELECT " + col.NAME + " FROM " + tableName + " WHERE " + col.IP + "=?;"); pst.setString(1, ip); rs = pst.executeQuery(); while (rs.next()) { 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 7ac10e25..a20227e5 100644 --- a/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java +++ b/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java @@ -225,7 +225,7 @@ public class AsynchronousLogin { return; } - List auths = this.database.getAllAuthsByName(auth); + List auths = this.database.getAllAuthsByIp(auth.getIp()); if (auths.size() < 2) { return; } 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 c9ce3f6c..ac921510 100644 --- a/src/main/java/fr/xephi/authme/process/register/AsyncRegister.java +++ b/src/main/java/fr/xephi/authme/process/register/AsyncRegister.java @@ -12,6 +12,7 @@ import fr.xephi.authme.security.crypts.HashedPassword; import fr.xephi.authme.security.crypts.TwoFactor; import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.settings.Settings; +import fr.xephi.authme.util.StringUtils; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -19,11 +20,11 @@ import org.bukkit.entity.Player; */ public class AsyncRegister { - protected final Player player; - protected final String name; - protected final String password; + private final Player player; + private final String name; + private final String password; private final String ip; - private String email = ""; + private final String email; private final AuthMe plugin; private final DataSource database; private final Messages m; @@ -86,7 +87,7 @@ public class AsyncRegister { public void process() { if (preRegisterCheck()) { - if (email != null && !email.isEmpty()) { + if (!StringUtils.isEmpty(email)) { emailRegister(); } else { passwordRegister(); diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/AccountsCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/AccountsCommandTest.java index 4743f699..92bcf4fc 100644 --- a/src/test/java/fr/xephi/authme/command/executable/authme/AccountsCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/authme/AccountsCommandTest.java @@ -16,7 +16,6 @@ import java.util.List; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.BDDMockito.given; -import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -48,8 +47,8 @@ public class AccountsCommandTest { // given given(sender.getName()).willReturn("Tester"); List arguments = Collections.EMPTY_LIST; - given(dataSource.getAuth("tester")).willReturn(mock(PlayerAuth.class)); - given(dataSource.getAllAuthsByName(any(PlayerAuth.class))).willReturn(Arrays.asList("Toaster", "Pester")); + given(dataSource.getAuth("tester")).willReturn(authWithIp("123.45.67.89")); + given(dataSource.getAllAuthsByIp("123.45.67.89")).willReturn(Arrays.asList("Toaster", "Pester")); // when command.executeCommand(sender, arguments, service); @@ -81,7 +80,7 @@ public class AccountsCommandTest { // given List arguments = Collections.singletonList("SomeUser"); given(dataSource.getAuth("someuser")).willReturn(mock(PlayerAuth.class)); - given(dataSource.getAllAuthsByName(any(PlayerAuth.class))).willReturn(Collections.EMPTY_LIST); + given(dataSource.getAllAuthsByIp(anyString())).willReturn(Collections.EMPTY_LIST); // when command.executeCommand(sender, arguments, service); @@ -96,8 +95,8 @@ public class AccountsCommandTest { public void shouldReturnSingleAccountMessage() { // given List arguments = Collections.singletonList("SomeUser"); - given(dataSource.getAuth("someuser")).willReturn(mock(PlayerAuth.class)); - given(dataSource.getAllAuthsByName(any(PlayerAuth.class))).willReturn(Collections.singletonList("SomeUser")); + given(dataSource.getAuth("someuser")).willReturn(authWithIp("56.78.90.123")); + given(dataSource.getAllAuthsByIp("56.78.90.123")).willReturn(Collections.singletonList("SomeUser")); // when command.executeCommand(sender, arguments, service); @@ -169,4 +168,11 @@ public class AccountsCommandTest { verify(sender, times(expectedCount)).sendMessage(captor.capture()); return captor.getAllValues().toArray(new String[expectedCount]); } + + private static PlayerAuth authWithIp(String ip) { + return PlayerAuth.builder() + .name("Test") + .ip(ip) + .build(); + } } diff --git a/src/test/java/fr/xephi/authme/settings/NewSettingTest.java b/src/test/java/fr/xephi/authme/settings/NewSettingTest.java index 64a79626..d381604c 100644 --- a/src/test/java/fr/xephi/authme/settings/NewSettingTest.java +++ b/src/test/java/fr/xephi/authme/settings/NewSettingTest.java @@ -5,8 +5,7 @@ import fr.xephi.authme.settings.properties.TestConfiguration; import fr.xephi.authme.settings.properties.TestEnum; import org.bukkit.configuration.file.YamlConfiguration; import org.junit.Test; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; +import org.mockito.internal.stubbing.answers.ReturnsArgumentAt; import java.io.File; @@ -32,10 +31,10 @@ public class NewSettingTest { public void shouldLoadAllConfigs() { // given YamlConfiguration configuration = mock(YamlConfiguration.class); - given(configuration.getString(anyString(), anyString())).willAnswer(withDefaultArgument()); - given(configuration.getBoolean(anyString(), anyBoolean())).willAnswer(withDefaultArgument()); - given(configuration.getDouble(anyString(), anyDouble())).willAnswer(withDefaultArgument()); - given(configuration.getInt(anyString(), anyInt())).willAnswer(withDefaultArgument()); + given(configuration.getString(anyString(), anyString())).willAnswer(new ReturnsArgumentAt(1)); + given(configuration.getBoolean(anyString(), anyBoolean())).willAnswer(new ReturnsArgumentAt(1)); + given(configuration.getDouble(anyString(), anyDouble())).willAnswer(new ReturnsArgumentAt(1)); + given(configuration.getInt(anyString(), anyInt())).willAnswer(new ReturnsArgumentAt(1)); setReturnValue(configuration, TestConfiguration.VERSION_NUMBER, 20); setReturnValue(configuration, TestConfiguration.SKIP_BORING_FEATURES, true); @@ -89,14 +88,4 @@ public class NewSettingTest { setting.getProperty(property).equals(property.getDefaultValue()), equalTo(true)); } - private static Answer withDefaultArgument() { - return new Answer() { - @Override - public T answer(InvocationOnMock invocation) throws Throwable { - // Return the second parameter -> the default - return (T) invocation.getArguments()[1]; - } - }; - } - } From cc29d8b628e7b33e0d7bb286fbaf72774a3cd35a Mon Sep 17 00:00:00 2001 From: DNx5 Date: Sat, 20 Feb 2016 06:47:59 +0700 Subject: [PATCH 13/13] Fix duplicate entry error, #528 --- .../authme/datasource/CacheDataSource.java | 9 +++++++++ .../fr/xephi/authme/datasource/DataSource.java | 18 +++++++++++++++++- .../fr/xephi/authme/datasource/FlatFile.java | 5 +++++ .../java/fr/xephi/authme/datasource/MySQL.java | 15 +++++++++++++++ .../fr/xephi/authme/datasource/SQLite.java | 14 ++++++++++++++ .../process/login/AsynchronousLogin.java | 6 +++--- 6 files changed, 63 insertions(+), 4 deletions(-) diff --git a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java index 57fb7fe5..4d0d4436 100644 --- a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java +++ b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java @@ -216,6 +216,15 @@ public class CacheDataSource implements DataSource { return result; } + @Override + public boolean updateIp(String user, String ip) { + boolean result = source.updateIp(user, ip); + if (result) { + cachedAuths.refresh(user); + } + return result; + } + @Override public List getAllAuths() { return source.getAllAuths(); diff --git a/src/main/java/fr/xephi/authme/datasource/DataSource.java b/src/main/java/fr/xephi/authme/datasource/DataSource.java index 8a22ffdd..43693313 100644 --- a/src/main/java/fr/xephi/authme/datasource/DataSource.java +++ b/src/main/java/fr/xephi/authme/datasource/DataSource.java @@ -14,6 +14,7 @@ public interface DataSource { * Return whether there is a record for the given username. * * @param user The username to look up + * * @return True if there is a record, false otherwise */ boolean isAuthAvailable(String user); @@ -22,6 +23,7 @@ public interface DataSource { * Return the hashed password of the player. * * @param user The user whose password should be retrieve + * * @return The password hash of the player */ HashedPassword getPassword(String user); @@ -30,6 +32,7 @@ public interface DataSource { * Retrieve the entire PlayerAuth object associated with the username. * * @param user The user to retrieve + * * @return The PlayerAuth object for the given username */ PlayerAuth getAuth(String user); @@ -38,6 +41,7 @@ public interface DataSource { * Save a new PlayerAuth object. * * @param auth The new PlayerAuth to persist + * * @return True upon success, false upon failure */ boolean saveAuth(PlayerAuth auth); @@ -46,6 +50,7 @@ public interface DataSource { * Update the session of a record (IP, last login, real name). * * @param auth The PlayerAuth object to update in the database + * * @return True upon success, false upon failure */ boolean updateSession(PlayerAuth auth); @@ -54,6 +59,7 @@ public interface DataSource { * Update the password of the given PlayerAuth object. * * @param auth The PlayerAuth whose password should be updated + * * @return True upon success, false upon failure */ boolean updatePassword(PlayerAuth auth); @@ -61,8 +67,9 @@ public interface DataSource { /** * Update the password of the given player. * - * @param user The user whose password should be updated + * @param user The user whose password should be updated * @param password The new password + * * @return True upon success, false upon failure */ boolean updatePassword(String user, HashedPassword password); @@ -72,6 +79,7 @@ public interface DataSource { * the given time. * * @param until The minimum last login + * * @return The account names that have been removed */ List autoPurgeDatabase(long until); @@ -80,6 +88,7 @@ public interface DataSource { * Remove a user record from the database. * * @param user The user to remove + * * @return True upon success, false upon failure */ boolean removeAuth(String user); @@ -88,6 +97,7 @@ public interface DataSource { * Update the quit location of a PlayerAuth. * * @param auth The entry whose quit location should be updated + * * @return True upon success, false upon failure */ boolean updateQuitLoc(PlayerAuth auth); @@ -96,6 +106,7 @@ public interface DataSource { * Return all usernames associated with the given IP address. * * @param ip The IP address to look up + * * @return Usernames associated with the given IP address */ List getAllAuthsByIp(String ip); @@ -104,6 +115,7 @@ public interface DataSource { * Return all usernames associated with the given email address. * * @param email The email address to look up + * * @return Users using the given email address */ List getAllAuthsByEmail(String email); @@ -112,6 +124,7 @@ public interface DataSource { * Update the email of the PlayerAuth in the data source. * * @param auth The PlayerAuth whose email should be updated + * * @return True upon success, false upon failure */ boolean updateEmail(PlayerAuth auth); @@ -178,6 +191,9 @@ public interface DataSource { void updateName(String oldOne, String newOne); boolean updateRealName(String user, String realName); + + boolean updateIp(String user, String ip); + /** * Method getAllAuths. * diff --git a/src/main/java/fr/xephi/authme/datasource/FlatFile.java b/src/main/java/fr/xephi/authme/datasource/FlatFile.java index 8fce0f8f..9bab76e1 100644 --- a/src/main/java/fr/xephi/authme/datasource/FlatFile.java +++ b/src/main/java/fr/xephi/authme/datasource/FlatFile.java @@ -615,6 +615,11 @@ public class FlatFile implements DataSource { return false; } + @Override + public boolean updateIp(String user, String ip) { + throw new UnsupportedOperationException("Flat file no longer supported"); + } + @Override public List getAllAuths() { BufferedReader br = null; diff --git a/src/main/java/fr/xephi/authme/datasource/MySQL.java b/src/main/java/fr/xephi/authme/datasource/MySQL.java index 78ec0327..a429d181 100644 --- a/src/main/java/fr/xephi/authme/datasource/MySQL.java +++ b/src/main/java/fr/xephi/authme/datasource/MySQL.java @@ -846,6 +846,21 @@ public class MySQL implements DataSource { return false; } + @Override + public boolean updateIp(String user, String ip) { + try (Connection con = getConnection()) { + String sql = "UPDATE " + tableName + " SET " + col.IP + "=? WHERE " + col.NAME + "=?;"; + PreparedStatement pst = con.prepareStatement(sql); + pst.setString(1, ip); + pst.setString(2, user); + pst.executeUpdate(); + return true; + } catch (SQLException ex) { + logSqlException(ex); + } + return false; + } + @Override public List getAllAuths() { List auths = new ArrayList<>(); diff --git a/src/main/java/fr/xephi/authme/datasource/SQLite.java b/src/main/java/fr/xephi/authme/datasource/SQLite.java index 86a6d115..081e386c 100644 --- a/src/main/java/fr/xephi/authme/datasource/SQLite.java +++ b/src/main/java/fr/xephi/authme/datasource/SQLite.java @@ -548,6 +548,20 @@ public class SQLite implements DataSource { return false; } + @Override + public boolean updateIp(String user, String ip) { + String sql = "UPDATE " + tableName + " SET " + col.IP + "=? WHERE " + col.NAME + "=?;"; + try(PreparedStatement pst = con.prepareStatement(sql)) { + pst.setString(1, ip); + pst.setString(2, user); + pst.executeUpdate(); + return true; + } catch (SQLException ex) { + logSqlException(ex); + } + return false; + } + @Override public List getAllAuths() { List auths = new ArrayList<>(); 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 a20227e5..5a4cf425 100644 --- a/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java +++ b/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java @@ -7,12 +7,12 @@ import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.limbo.LimboCache; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.events.AuthMeAsyncPreLoginEvent; +import fr.xephi.authme.output.MessageKey; +import fr.xephi.authme.output.Messages; import fr.xephi.authme.permission.AdminPermission; import fr.xephi.authme.permission.PlayerPermission; import fr.xephi.authme.permission.PlayerStatePermission; import fr.xephi.authme.security.RandomString; -import fr.xephi.authme.output.MessageKey; -import fr.xephi.authme.output.Messages; import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.RegistrationSettings; @@ -142,7 +142,7 @@ public class AsynchronousLogin { if (pAuth.getIp().equals("127.0.0.1") && !pAuth.getIp().equals(ip)) { pAuth.setIp(ip); - database.saveAuth(pAuth); + database.updateIp(pAuth.getNickname(), ip); } String email = pAuth.getEmail();