diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java index b71b7dba..d00f901f 100644 --- a/src/main/java/fr/xephi/authme/AuthMe.java +++ b/src/main/java/fr/xephi/authme/AuthMe.java @@ -20,14 +20,12 @@ import fr.xephi.authme.hooks.BungeeCordMessage; import fr.xephi.authme.hooks.PluginHooks; import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.initialization.MetricsStarter; -import fr.xephi.authme.listener.AsyncSingleSessionListener; import fr.xephi.authme.listener.BlockListener; import fr.xephi.authme.listener.EntityListener; import fr.xephi.authme.listener.PlayerListener; import fr.xephi.authme.listener.PlayerListener16; import fr.xephi.authme.listener.PlayerListener18; import fr.xephi.authme.listener.ServerListener; -import fr.xephi.authme.listener.SyncSingleSessionListener; import fr.xephi.authme.output.ConsoleFilter; import fr.xephi.authme.output.Log4JFilter; import fr.xephi.authme.output.MessageKey; @@ -52,11 +50,10 @@ import fr.xephi.authme.util.BukkitService; import fr.xephi.authme.util.FileUtils; import fr.xephi.authme.util.GeoLiteAPI; import fr.xephi.authme.util.MigrationService; +import fr.xephi.authme.util.ServerUtils; import fr.xephi.authme.util.StringUtils; import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.ValidationService; -import fr.xephi.authme.util.ServerUtils; - import org.apache.logging.log4j.LogManager; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -310,6 +307,13 @@ public class AuthMe extends JavaPlugin { && settings.getProperty(PluginSettings.SESSIONS_ENABLED)) { ConsoleLogger.warning("WARNING!!! You set session timeout to 0, this may cause security issues!"); } + + // Single session not possible on CraftBukkit + if (settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION) + && !Bukkit.getOnlineMode() && !ServerUtils.isSpigot()) { + ConsoleLogger.warning("WARNING: You have force single session enabled but are not running on Spigot. " + + "This feature is not supported on CraftBukkit in offline mode"); + } } /** @@ -338,13 +342,6 @@ public class AuthMe extends JavaPlugin { pluginManager.registerEvents(injector.getSingleton(PlayerListener18.class), this); } catch (ClassNotFoundException ignore) { } - - // Choose the right SingleSessionListener - if(Bukkit.getOnlineMode() || ServerUtils.isSpigot()) { - pluginManager.registerEvents(injector.getSingleton(AsyncSingleSessionListener.class), this); - } else { - pluginManager.registerEvents(injector.getSingleton(SyncSingleSessionListener.class), this); - } } private void reloadSupportHook() { diff --git a/src/main/java/fr/xephi/authme/listener/AsyncSingleSessionListener.java b/src/main/java/fr/xephi/authme/listener/AsyncSingleSessionListener.java deleted file mode 100644 index 14d81332..00000000 --- a/src/main/java/fr/xephi/authme/listener/AsyncSingleSessionListener.java +++ /dev/null @@ -1,39 +0,0 @@ -package fr.xephi.authme.listener; - -import javax.inject.Inject; - -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.player.AsyncPlayerPreLoginEvent; - -import fr.xephi.authme.output.Messages; - -/* - * This listener is registered only if the server is in online-mode or the implementation is Spigot. - * The reason is that only Spigot fires the Async version of the event on an offline-mode server! - */ -public class AsyncSingleSessionListener implements Listener { - - @Inject - private Messages m; - @Inject - private OnJoinVerifier onJoinVerifier; - - @EventHandler(priority = EventPriority.LOWEST) - public void onSyncPreLogin(AsyncPlayerPreLoginEvent event) { - if(event.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { - return; - } - - final String name = event.getName(); - - try { - onJoinVerifier.checkSingleSession(name); - } catch (FailedVerificationException e) { - event.setKickMessage(m.retrieveSingle(e.getReason(), e.getArgs())); - event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER); - return; - } - } -} diff --git a/src/main/java/fr/xephi/authme/listener/PlayerListener.java b/src/main/java/fr/xephi/authme/listener/PlayerListener.java index 33323735..c00462ab 100644 --- a/src/main/java/fr/xephi/authme/listener/PlayerListener.java +++ b/src/main/java/fr/xephi/authme/listener/PlayerListener.java @@ -195,6 +195,26 @@ public class PlayerListener implements Listener { } } + // Note: AsyncPlayerPreLoginEvent is not fired by all servers in offline mode + // e.g. CraftBukkit does not. So we need to run crucial things in onPlayerLogin + // We have no performance improvements if we do the same thing on two different events + // The single session feature only works with the AsyncPlayerPreLoginEvent, i.e. it does not work + // with CraftBukkit, cf. issue #831 + @EventHandler(priority = EventPriority.LOWEST) + public void onAsyncPreLogin(AsyncPlayerPreLoginEvent event) { + if (!AsyncPlayerPreLoginEvent.Result.ALLOWED.equals(event.getLoginResult())) { + return; + } + + final String name = event.getName(); + try { + onJoinVerifier.checkSingleSession(name); + } catch (FailedVerificationException e) { + event.setKickMessage(m.retrieveSingle(e.getReason(), e.getArgs())); + event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER); + } + } + @EventHandler(priority = EventPriority.LOW) public void onPlayerJoin(PlayerJoinEvent event) { final Player player = event.getPlayer(); @@ -214,17 +234,15 @@ public class PlayerListener implements Listener { } final String name = player.getName(); - final String lowerName = name.toLowerCase(); - try { // Fast stuff - // onJoinVerifier.checkSingleSession(lowerName); onJoinVerifier.checkIsValidName(name); // Get the auth later as this may cause the single session check to fail // Slow stuff final PlayerAuth auth = dataSource.getAuth(player.getName()); final boolean isAuthAvailable = (auth != null); + final String lowerName = name.toLowerCase(); onJoinVerifier.checkAntibot(lowerName, isAuthAvailable); onJoinVerifier.checkKickNonRegistered(isAuthAvailable); onJoinVerifier.checkNameCasing(player, auth); diff --git a/src/main/java/fr/xephi/authme/listener/SyncSingleSessionListener.java b/src/main/java/fr/xephi/authme/listener/SyncSingleSessionListener.java deleted file mode 100644 index 57f78ff6..00000000 --- a/src/main/java/fr/xephi/authme/listener/SyncSingleSessionListener.java +++ /dev/null @@ -1,41 +0,0 @@ -package fr.xephi.authme.listener; - -import javax.inject.Inject; - -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerPreLoginEvent; - -import fr.xephi.authme.output.Messages; - -/* - * This listener is registered only if the server is in offline-mode and the implementation is not Spigot. - * The reason is that only Spigot fires the Async version of this event on an offline-mode server! - */ -public class SyncSingleSessionListener implements Listener { - - @Inject - private Messages m; - @Inject - private OnJoinVerifier onJoinVerifier; - - // Note: the PlayerPreLoginEvent causes the login thread to synchronize with the main thread - @SuppressWarnings("deprecation") - @EventHandler(priority = EventPriority.LOWEST) - public void onSyncPreLogin(PlayerPreLoginEvent event) { - if(event.getResult() != PlayerPreLoginEvent.Result.ALLOWED) { - return; - } - - final String name = event.getName(); - - try { - onJoinVerifier.checkSingleSession(name); - } catch (FailedVerificationException e) { - event.setKickMessage(m.retrieveSingle(e.getReason(), e.getArgs())); - event.setResult(PlayerPreLoginEvent.Result.KICK_OTHER); - return; - } - } -} diff --git a/src/main/java/fr/xephi/authme/util/ServerUtils.java b/src/main/java/fr/xephi/authme/util/ServerUtils.java index 3ead88c4..ae5306b8 100644 --- a/src/main/java/fr/xephi/authme/util/ServerUtils.java +++ b/src/main/java/fr/xephi/authme/util/ServerUtils.java @@ -1,6 +1,9 @@ package fr.xephi.authme.util; -public class ServerUtils { +public final class ServerUtils { + + private ServerUtils() { + } /** * Check if the server implementation is based on Spigot diff --git a/src/test/java/fr/xephi/authme/listener/AuthMeBlockListenerTest.java b/src/test/java/fr/xephi/authme/listener/BlockListenerTest.java similarity index 95% rename from src/test/java/fr/xephi/authme/listener/AuthMeBlockListenerTest.java rename to src/test/java/fr/xephi/authme/listener/BlockListenerTest.java index 91147cde..e798c4df 100644 --- a/src/test/java/fr/xephi/authme/listener/AuthMeBlockListenerTest.java +++ b/src/test/java/fr/xephi/authme/listener/BlockListenerTest.java @@ -9,9 +9,6 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import fr.xephi.authme.listener.BlockListener; -import fr.xephi.authme.listener.ListenerService; - import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -21,7 +18,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; * Test for {@link BlockListener}. */ @RunWith(MockitoJUnitRunner.class) -public class AuthMeBlockListenerTest { +public class BlockListenerTest { @InjectMocks private BlockListener listener; diff --git a/src/test/java/fr/xephi/authme/listener/ListenerConsistencyTest.java b/src/test/java/fr/xephi/authme/listener/ListenerConsistencyTest.java index f4b61648..045c7975 100644 --- a/src/test/java/fr/xephi/authme/listener/ListenerConsistencyTest.java +++ b/src/test/java/fr/xephi/authme/listener/ListenerConsistencyTest.java @@ -1,14 +1,6 @@ package fr.xephi.authme.listener; import com.google.common.collect.Sets; - -import fr.xephi.authme.listener.BlockListener; -import fr.xephi.authme.listener.EntityListener; -import fr.xephi.authme.listener.PlayerListener; -import fr.xephi.authme.listener.PlayerListener16; -import fr.xephi.authme.listener.PlayerListener18; -import fr.xephi.authme.listener.ServerListener; - import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.junit.Test; @@ -36,7 +28,7 @@ public final class ListenerConsistencyTest { "PlayerListener#onPlayerJoin", "PlayerListener#onPlayerLogin", "PlayerListener#onPlayerQuit", "ServerListener#onPluginDisable", "ServerListener#onServerPing", "ServerListener#onPluginEnable", - "PlayerListener#onJoinMessage", "PlayerListener#onLoginSingleSession"); + "PlayerListener#onJoinMessage", "PlayerListener#onAsyncPreLogin"); @Test public void shouldSetIgnoreCancelledToTrue() { diff --git a/src/test/java/fr/xephi/authme/listener/ListenerServiceTest.java b/src/test/java/fr/xephi/authme/listener/ListenerServiceTest.java index 01805a34..17276858 100644 --- a/src/test/java/fr/xephi/authme/listener/ListenerServiceTest.java +++ b/src/test/java/fr/xephi/authme/listener/ListenerServiceTest.java @@ -6,7 +6,6 @@ import ch.jalu.injector.testing.InjectDelayed; import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.hooks.PluginHooks; -import fr.xephi.authme.listener.ListenerService; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.RegistrationSettings; import fr.xephi.authme.util.ValidationService; diff --git a/src/test/java/fr/xephi/authme/listener/OnJoinVerifierTest.java b/src/test/java/fr/xephi/authme/listener/OnJoinVerifierTest.java index 3861b4df..f2e9ee9e 100644 --- a/src/test/java/fr/xephi/authme/listener/OnJoinVerifierTest.java +++ b/src/test/java/fr/xephi/authme/listener/OnJoinVerifierTest.java @@ -4,8 +4,6 @@ import fr.xephi.authme.AntiBot; import fr.xephi.authme.TestHelper; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; -import fr.xephi.authme.listener.FailedVerificationException; -import fr.xephi.authme.listener.OnJoinVerifier; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; import fr.xephi.authme.permission.PermissionsManager; diff --git a/src/test/java/fr/xephi/authme/util/ServerUtilsTest.java b/src/test/java/fr/xephi/authme/util/ServerUtilsTest.java new file mode 100644 index 00000000..04aaf88b --- /dev/null +++ b/src/test/java/fr/xephi/authme/util/ServerUtilsTest.java @@ -0,0 +1,19 @@ +package fr.xephi.authme.util; + +import org.junit.Test; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; + +/** + * Test for {@link ServerUtils}. + */ +public class ServerUtilsTest { + + @Test + public void shouldReturnTrueForSpigotImplementation() { + // Spigot is a provided dependency of the project, so the ClassLoader knows about it + assertThat(ServerUtils.isSpigot(), equalTo(true)); + } + +}