#831 Cleanup, finalization

- Handle AsyncPlayerPreLoginEvent in main PlayerListener class: Spigot emits it in offline mode, whereas offline CraftBukkit doesn't
- Remove listener for sync PlayerPreLoginEvent; not fired by offline CraftBukkit either
- Add warning when offline CraftBukkit is detected and single session setting is enabled
This commit is contained in:
ljacqu 2016-08-03 19:58:10 +02:00
parent b892b8e3a8
commit 80337f758b
10 changed files with 54 additions and 111 deletions

View File

@ -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() {

View File

@ -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;
}
}
}

View File

@ -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);

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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;

View File

@ -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() {

View File

@ -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;

View File

@ -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;

View File

@ -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));
}
}