#760 Fix single session feature

- Move the check from PlayerLoginEvent to AsyncPlayerPreLoginEvent. Single session can only be implemented with PreLoginEvent; it is already to late to check this in the PlayerLoginEvent. Ergo, we cannot offer this for CraftBukkit.
- Remove interactions with LimboCache - no interactions with LimboCache expected until after OnJoinVerification checks. (Thanks sgdc3!)
This commit is contained in:
ljacqu 2016-06-14 21:03:32 +02:00
parent 367f785610
commit 3411450ff1
3 changed files with 13 additions and 28 deletions

View File

@ -217,6 +217,9 @@ public class AuthMePlayerListener implements Listener {
onJoinVerifier.checkAntibot(name, isAuthAvailable); onJoinVerifier.checkAntibot(name, isAuthAvailable);
onJoinVerifier.checkKickNonRegistered(isAuthAvailable); onJoinVerifier.checkKickNonRegistered(isAuthAvailable);
onJoinVerifier.checkIsValidName(name); onJoinVerifier.checkIsValidName(name);
// Note #760: Single session must be checked here - checking with PlayerLoginEvent is too late and
// the first connection will have been kicked. This means this feature doesn't work on CraftBukkit.
onJoinVerifier.checkSingleSession(name);
} catch (FailedVerificationException e) { } catch (FailedVerificationException e) {
event.setKickMessage(m.retrieveSingle(e.getReason(), e.getArgs())); event.setKickMessage(m.retrieveSingle(e.getReason(), e.getArgs()));
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER); event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
@ -243,7 +246,6 @@ public class AuthMePlayerListener implements Listener {
onJoinVerifier.checkKickNonRegistered(isAuthAvailable); onJoinVerifier.checkKickNonRegistered(isAuthAvailable);
onJoinVerifier.checkIsValidName(name); onJoinVerifier.checkIsValidName(name);
onJoinVerifier.checkNameCasing(player, auth); onJoinVerifier.checkNameCasing(player, auth);
onJoinVerifier.checkSingleSession(player);
onJoinVerifier.checkPlayerCountry(isAuthAvailable, event); onJoinVerifier.checkPlayerCountry(isAuthAvailable, event);
} catch (FailedVerificationException e) { } catch (FailedVerificationException e) {
event.setKickMessage(m.retrieveSingle(e.getReason(), e.getArgs())); event.setKickMessage(m.retrieveSingle(e.getReason(), e.getArgs()));

View File

@ -3,9 +3,6 @@ package fr.xephi.authme.listener;
import fr.xephi.authme.AntiBot; import fr.xephi.authme.AntiBot;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.cache.limbo.LimboPlayer;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.initialization.Reloadable; import fr.xephi.authme.initialization.Reloadable;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
@ -18,7 +15,6 @@ import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings; import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.util.BukkitService; import fr.xephi.authme.util.BukkitService;
import fr.xephi.authme.util.StringUtils; import fr.xephi.authme.util.StringUtils;
import fr.xephi.authme.util.Utils;
import fr.xephi.authme.util.ValidationService; import fr.xephi.authme.util.ValidationService;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -49,8 +45,6 @@ class OnJoinVerifier implements Reloadable {
@Inject @Inject
private BukkitService bukkitService; private BukkitService bukkitService;
@Inject @Inject
private LimboCache limboCache;
@Inject
private Server server; private Server server;
private Pattern nicknamePattern; private Pattern nicknamePattern;
@ -187,21 +181,15 @@ class OnJoinVerifier implements Reloadable {
* Checks if a player with the same name (case-insensitive) is already playing and refuses the * Checks if a player with the same name (case-insensitive) is already playing and refuses the
* connection if so configured. * connection if so configured.
* *
* @param player the player to verify * @param name the player name to check
*/ */
public void checkSingleSession(Player player) throws FailedVerificationException { public void checkSingleSession(String name) throws FailedVerificationException {
if (!settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION)) { if (!settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION)) {
return; return;
} }
Player onlinePlayer = bukkitService.getPlayerExact(player.getName()); Player onlinePlayer = bukkitService.getPlayerExact(name);
if (onlinePlayer != null) { if (onlinePlayer != null) {
String name = player.getName().toLowerCase();
LimboPlayer limbo = limboCache.getLimboPlayer(name);
if (limbo != null && PlayerCache.getInstance().isAuthenticated(name)) {
Utils.addNormal(player, limbo.getGroup());
limboCache.deleteLimboPlayer(name);
}
throw new FailedVerificationException(MessageKey.USERNAME_ALREADY_ONLINE_ERROR); throw new FailedVerificationException(MessageKey.USERNAME_ALREADY_ONLINE_ERROR);
} }
} }

View File

@ -3,7 +3,6 @@ package fr.xephi.authme.listener;
import fr.xephi.authme.AntiBot; import fr.xephi.authme.AntiBot;
import fr.xephi.authme.TestHelper; import fr.xephi.authme.TestHelper;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages; import fr.xephi.authme.output.Messages;
@ -67,8 +66,6 @@ public class OnJoinVerifierTest {
@Mock @Mock
private BukkitService bukkitService; private BukkitService bukkitService;
@Mock @Mock
private LimboCache limboCache;
@Mock
private Server server; private Server server;
@Rule @Rule
@ -341,21 +338,21 @@ public class OnJoinVerifierTest {
@Test @Test
public void shouldAcceptNameThatIsNotOnline() throws FailedVerificationException { public void shouldAcceptNameThatIsNotOnline() throws FailedVerificationException {
// given // given
Player player = newPlayerWithName("bobby"); String name = "bobby";
given(settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION)).willReturn(true); given(settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION)).willReturn(true);
given(bukkitService.getPlayerExact("bobby")).willReturn(null); given(bukkitService.getPlayerExact("bobby")).willReturn(null);
// when // when
onJoinVerifier.checkSingleSession(player); onJoinVerifier.checkSingleSession(name);
// then // then
verifyZeroInteractions(limboCache); verify(bukkitService).getPlayerExact(name);
} }
@Test @Test
public void shouldRejectNameAlreadyOnline() throws FailedVerificationException { public void shouldRejectNameAlreadyOnline() throws FailedVerificationException {
// given // given
Player player = newPlayerWithName("Charlie"); String name = "Charlie";
Player onlinePlayer = newPlayerWithName("charlie"); Player onlinePlayer = newPlayerWithName("charlie");
given(bukkitService.getPlayerExact("Charlie")).willReturn(onlinePlayer); given(bukkitService.getPlayerExact("Charlie")).willReturn(onlinePlayer);
given(settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION)).willReturn(true); given(settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION)).willReturn(true);
@ -364,22 +361,20 @@ public class OnJoinVerifierTest {
expectValidationExceptionWith(MessageKey.USERNAME_ALREADY_ONLINE_ERROR); expectValidationExceptionWith(MessageKey.USERNAME_ALREADY_ONLINE_ERROR);
// when / then // when / then
onJoinVerifier.checkSingleSession(player); onJoinVerifier.checkSingleSession(name);
verify(limboCache).getLimboPlayer("charlie");
} }
@Test @Test
public void shouldAcceptAlreadyOnlineNameForDisabledSetting() throws FailedVerificationException { public void shouldAcceptAlreadyOnlineNameForDisabledSetting() throws FailedVerificationException {
// given // given
Player player = newPlayerWithName("Felipe"); String name = "Felipe";
given(settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION)).willReturn(false); given(settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION)).willReturn(false);
// when // when
onJoinVerifier.checkSingleSession(player); onJoinVerifier.checkSingleSession(name);
// then // then
verifyZeroInteractions(bukkitService); verifyZeroInteractions(bukkitService);
verifyZeroInteractions(limboCache);
} }
private static Player newPlayerWithName(String name) { private static Player newPlayerWithName(String name) {