From 88ce493438247b9aaa68673c1fffc8d021f63bf1 Mon Sep 17 00:00:00 2001 From: Gabriele C Date: Sun, 2 Oct 2016 19:41:14 +0200 Subject: [PATCH] AntiBot cleanup + moved to services Some test needs to be fixed/added --- src/main/java/fr/xephi/authme/AntiBot.java | 145 ------------ .../authme/SwitchAntiBotCommand.java | 10 +- .../xephi/authme/listener/OnJoinVerifier.java | 24 +- .../xephi/authme/listener/PlayerListener.java | 16 +- .../xephi/authme/service/AntiBotService.java | 207 ++++++++++++++++++ .../authme/SwitchAntiBotCommandTest.java | 6 +- .../authme/listener/OnJoinVerifierTest.java | 39 +--- .../authme/listener/PlayerListenerTest.java | 18 +- .../authme/{ => service}/AntiBotTest.java | 90 ++------ 9 files changed, 282 insertions(+), 273 deletions(-) delete mode 100644 src/main/java/fr/xephi/authme/AntiBot.java create mode 100644 src/main/java/fr/xephi/authme/service/AntiBotService.java rename src/test/java/fr/xephi/authme/{ => service}/AntiBotTest.java (61%) diff --git a/src/main/java/fr/xephi/authme/AntiBot.java b/src/main/java/fr/xephi/authme/AntiBot.java deleted file mode 100644 index 53ced436..00000000 --- a/src/main/java/fr/xephi/authme/AntiBot.java +++ /dev/null @@ -1,145 +0,0 @@ -package fr.xephi.authme; - -import fr.xephi.authme.output.MessageKey; -import fr.xephi.authme.output.Messages; -import fr.xephi.authme.permission.AdminPermission; -import fr.xephi.authme.permission.PermissionsManager; -import fr.xephi.authme.permission.PlayerStatePermission; -import fr.xephi.authme.settings.Settings; -import fr.xephi.authme.settings.properties.ProtectionSettings; -import fr.xephi.authme.util.BukkitService; -import org.bukkit.entity.Player; - -import javax.inject.Inject; -import java.util.concurrent.CopyOnWriteArrayList; - -import static fr.xephi.authme.util.BukkitService.TICKS_PER_MINUTE; -import static fr.xephi.authme.util.BukkitService.TICKS_PER_SECOND; - -/** - * The AntiBot Service Management class. - */ -public class AntiBot { - - private final Settings settings; - private final Messages messages; - private final PermissionsManager permissionsManager; - private final BukkitService bukkitService; - private final CopyOnWriteArrayList antibotKicked = new CopyOnWriteArrayList(); - private final CopyOnWriteArrayList antibotPlayers = new CopyOnWriteArrayList(); - private AntiBotStatus antiBotStatus = AntiBotStatus.DISABLED; - - @Inject - AntiBot(Settings settings, Messages messages, PermissionsManager permissionsManager, - BukkitService bukkitService) { - this.settings = settings; - this.messages = messages; - this.permissionsManager = permissionsManager; - this.bukkitService = bukkitService; - - setupAntiBotService(); - } - - private void setupAntiBotService() { - if (settings.getProperty(ProtectionSettings.ENABLE_ANTIBOT)) { - bukkitService.scheduleSyncDelayedTask(new Runnable() { - @Override - public void run() { - antiBotStatus = AntiBotStatus.LISTENING; - } - }, 2 * TICKS_PER_MINUTE); - } - } - - public void overrideAntiBotStatus(boolean activated) { - if (antiBotStatus != AntiBotStatus.DISABLED) { - if (activated) { - antiBotStatus = AntiBotStatus.ACTIVE; - } else { - antiBotStatus = AntiBotStatus.LISTENING; - } - } - } - - public AntiBotStatus getAntiBotStatus() { - return antiBotStatus; - } - - public void activateAntiBot() { - antiBotStatus = AntiBotStatus.ACTIVE; - for (Player player : bukkitService.getOnlinePlayers()) { - if (permissionsManager.hasPermission(player, AdminPermission.ANTIBOT_MESSAGES)) { - messages.send(player, MessageKey.ANTIBOT_AUTO_ENABLED_MESSAGE); - } - } - - final int duration = settings.getProperty(ProtectionSettings.ANTIBOT_DURATION); - bukkitService.scheduleSyncDelayedTask(new Runnable() { - @Override - public void run() { - if (antiBotStatus == AntiBotStatus.ACTIVE) { - antiBotStatus = AntiBotStatus.LISTENING; - antibotPlayers.clear(); - antibotKicked.clear(); - for (String s : messages.retrieve(MessageKey.ANTIBOT_AUTO_DISABLED_MESSAGE)) { - bukkitService.broadcastMessage(s.replace("%m", Integer.toString(duration))); - } - } - } - }, duration * TICKS_PER_MINUTE); - } - - /** - * Handles a player joining the server and checks if AntiBot needs to be activated. - * - * @param player the player who joined the server - */ - public void handlePlayerJoin(final Player player) { - if (antiBotStatus == AntiBotStatus.ACTIVE || antiBotStatus == AntiBotStatus.DISABLED) { - return; - } - if (permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT)) { - return; - } - - antibotPlayers.add(player.getName().toLowerCase()); - if (antibotPlayers.size() > settings.getProperty(ProtectionSettings.ANTIBOT_SENSIBILITY)) { - activateAntiBot(); - return; - } - bukkitService.scheduleSyncDelayedTask(new Runnable() { - @Override - public void run() { - antibotPlayers.remove(player.getName().toLowerCase()); - } - }, 15 * TICKS_PER_SECOND); - } - - /** - * Returns whether the player was kicked because of activated antibot. The list is reset - * when antibot is deactivated. - * - * @param name the name to check - * @return true if the given name has been kicked because of Antibot - */ - public boolean wasPlayerKicked(String name) { - return antibotKicked.contains(name.toLowerCase()); - } - - /** - * Adds a name to the list of players kicked by antibot. Should only be used when a player - * is determined to be kicked because of failed antibot verification. - * - * @param name the name to add - */ - public void addPlayerKick(String name) { - antibotKicked.addIfAbsent(name.toLowerCase()); - } - - public enum AntiBotStatus { - LISTENING, - DISABLED, - ACTIVE - } - -} diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java index 64a7241f..44c30384 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java @@ -1,6 +1,6 @@ package fr.xephi.authme.command.executable.authme; -import fr.xephi.authme.AntiBot; +import fr.xephi.authme.service.AntiBotService; import fr.xephi.authme.command.CommandMapper; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.FoundCommandResult; @@ -18,7 +18,7 @@ import java.util.List; public class SwitchAntiBotCommand implements ExecutableCommand { @Inject - private AntiBot antiBot; + private AntiBotService antiBotService; @Inject private CommandMapper commandMapper; @@ -29,7 +29,7 @@ public class SwitchAntiBotCommand implements ExecutableCommand { @Override public void executeCommand(final CommandSender sender, List arguments) { if (arguments.isEmpty()) { - sender.sendMessage("[AuthMe] AntiBot status: " + antiBot.getAntiBotStatus().name()); + sender.sendMessage("[AuthMe] AntiBot status: " + antiBotService.getAntiBotStatus().name()); return; } @@ -37,10 +37,10 @@ public class SwitchAntiBotCommand implements ExecutableCommand { // Enable or disable the mod if ("ON".equalsIgnoreCase(newState)) { - antiBot.overrideAntiBotStatus(true); + antiBotService.overrideAntiBotStatus(true); sender.sendMessage("[AuthMe] AntiBot Manual Override: enabled!"); } else if ("OFF".equalsIgnoreCase(newState)) { - antiBot.overrideAntiBotStatus(false); + antiBotService.overrideAntiBotStatus(false); sender.sendMessage("[AuthMe] AntiBot Manual Override: disabled!"); } else { sender.sendMessage(ChatColor.DARK_RED + "Invalid AntiBot mode!"); diff --git a/src/main/java/fr/xephi/authme/listener/OnJoinVerifier.java b/src/main/java/fr/xephi/authme/listener/OnJoinVerifier.java index 745a1908..1767e0e0 100644 --- a/src/main/java/fr/xephi/authme/listener/OnJoinVerifier.java +++ b/src/main/java/fr/xephi/authme/listener/OnJoinVerifier.java @@ -1,6 +1,5 @@ package fr.xephi.authme.listener; -import fr.xephi.authme.AntiBot; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; @@ -9,6 +8,7 @@ import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PlayerStatePermission; +import fr.xephi.authme.service.AntiBotService; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.ProtectionSettings; import fr.xephi.authme.settings.properties.RegistrationSettings; @@ -40,7 +40,7 @@ class OnJoinVerifier implements Reloadable { @Inject private PermissionsManager permissionsManager; @Inject - private AntiBot antiBot; + private AntiBotService antiBotService; @Inject private ValidationService validationService; @Inject @@ -50,7 +50,8 @@ class OnJoinVerifier implements Reloadable { private Pattern nicknamePattern; - OnJoinVerifier() { } + OnJoinVerifier() { + } @PostConstruct @@ -63,12 +64,15 @@ class OnJoinVerifier implements Reloadable { /** * Checks if Antibot is enabled. * - * @param playerName the name of the player (lowercase) + * @param player the player * @param isAuthAvailable whether or not the player is registered */ - public void checkAntibot(String playerName, boolean isAuthAvailable) throws FailedVerificationException { - if (antiBot.getAntiBotStatus() == AntiBot.AntiBotStatus.ACTIVE && !isAuthAvailable) { - antiBot.addPlayerKick(playerName); + public void checkAntibot(Player player, boolean isAuthAvailable) throws FailedVerificationException { + if (permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT)) { + return; + } + if (antiBotService.shouldKick(isAuthAvailable)) { + antiBotService.addPlayerKick(player.getName()); throw new FailedVerificationException(MessageKey.KICK_ANTIBOT); } } @@ -105,6 +109,7 @@ class OnJoinVerifier implements Reloadable { * joining player is a VIP. * * @param event the login event to verify + * * @return true if the player's connection should be refused (i.e. the event does not need to be processed * further), false if the player is not refused */ @@ -141,7 +146,7 @@ class OnJoinVerifier implements Reloadable { * Checks that the casing in the username corresponds to the one in the database, if so configured. * * @param player the player to verify - * @param auth the auth object associated with the player + * @param auth the auth object associated with the player */ public void checkNameCasing(Player player, PlayerAuth auth) throws FailedVerificationException { if (auth != null && settings.getProperty(RegistrationSettings.PREVENT_OTHER_CASE)) { @@ -160,7 +165,7 @@ class OnJoinVerifier implements Reloadable { * Checks that the player's country is admitted. * * @param isAuthAvailable whether or not the user is registered - * @param playerIp the ip address of the player + * @param playerIp the ip address of the player */ public void checkPlayerCountry(boolean isAuthAvailable, String playerIp) throws FailedVerificationException { @@ -193,6 +198,7 @@ class OnJoinVerifier implements Reloadable { * Selects a non-VIP player to kick when a VIP player joins the server when full. * * @param onlinePlayers list of online players + * * @return the player to kick, or null if none applicable */ private Player generateKickPlayer(Collection onlinePlayers) { diff --git a/src/main/java/fr/xephi/authme/listener/PlayerListener.java b/src/main/java/fr/xephi/authme/listener/PlayerListener.java index c498e6ec..63a7ec96 100644 --- a/src/main/java/fr/xephi/authme/listener/PlayerListener.java +++ b/src/main/java/fr/xephi/authme/listener/PlayerListener.java @@ -1,11 +1,11 @@ package fr.xephi.authme.listener; -import fr.xephi.authme.AntiBot; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; import fr.xephi.authme.process.Management; +import fr.xephi.authme.service.AntiBotService; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.SpawnLoader; import fr.xephi.authme.settings.properties.HooksSettings; @@ -62,7 +62,7 @@ public class PlayerListener implements Listener { @Inject private DataSource dataSource; @Inject - private AntiBot antiBot; + private AntiBotService antiBotService; @Inject private Management management; @Inject @@ -218,13 +218,13 @@ public class PlayerListener implements Listener { // Fast stuff onJoinVerifier.checkSingleSession(name); onJoinVerifier.checkIsValidName(name); - + // Get the auth later as this may cause the single session check to fail // Slow stuff final PlayerAuth auth = dataSource.getAuth(name); final boolean isAuthAvailable = (auth != null); final String lowerName = name.toLowerCase(); - onJoinVerifier.checkAntibot(lowerName, isAuthAvailable); + onJoinVerifier.checkAntibot(player, isAuthAvailable); onJoinVerifier.checkKickNonRegistered(isAuthAvailable); onJoinVerifier.checkNameCasing(player, auth); onJoinVerifier.checkPlayerCountry(isAuthAvailable, event.getAddress().getHostAddress()); @@ -234,7 +234,7 @@ public class PlayerListener implements Listener { return; } - antiBot.handlePlayerJoin(player); + antiBotService.handlePlayerJoin(); teleportationService.teleportOnJoin(player); } @@ -245,12 +245,12 @@ public class PlayerListener implements Listener { if (settings.getProperty(RegistrationSettings.REMOVE_LEAVE_MESSAGE)) { event.setQuitMessage(null); } else if (settings.getProperty(RegistrationSettings.REMOVE_UNLOGGED_LEAVE_MESSAGE)) { - if(listenerService.shouldCancelEvent(event)) { + if (listenerService.shouldCancelEvent(event)) { event.setQuitMessage(null); } } - if (antiBot.wasPlayerKicked(player.getName())) { + if (antiBotService.wasPlayerKicked(player.getName())) { return; } @@ -268,7 +268,7 @@ public class PlayerListener implements Listener { } final Player player = event.getPlayer(); - if (!antiBot.wasPlayerKicked(player.getName())) { + if (!antiBotService.wasPlayerKicked(player.getName())) { management.performQuit(player); } } diff --git a/src/main/java/fr/xephi/authme/service/AntiBotService.java b/src/main/java/fr/xephi/authme/service/AntiBotService.java new file mode 100644 index 00000000..12d1bf94 --- /dev/null +++ b/src/main/java/fr/xephi/authme/service/AntiBotService.java @@ -0,0 +1,207 @@ +package fr.xephi.authme.service; + +import fr.xephi.authme.initialization.SettingsDependent; +import fr.xephi.authme.output.MessageKey; +import fr.xephi.authme.output.Messages; +import fr.xephi.authme.permission.AdminPermission; +import fr.xephi.authme.permission.PermissionsManager; +import fr.xephi.authme.settings.Settings; +import fr.xephi.authme.settings.properties.ProtectionSettings; +import fr.xephi.authme.util.BukkitService; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitTask; + +import javax.inject.Inject; +import java.util.concurrent.CopyOnWriteArrayList; + +import static fr.xephi.authme.util.BukkitService.TICKS_PER_MINUTE; +import static fr.xephi.authme.util.BukkitService.TICKS_PER_SECOND; + +/** + * The AntiBot Service Management class. + */ +public class AntiBotService implements SettingsDependent { + + // Instances + private final Messages messages; + private final PermissionsManager permissionsManager; + private final BukkitService bukkitService; + + // Settings + private int duration; + private int sensibility; + + // Service status + private AntiBotStatus antiBotStatus; + private BukkitTask disableTask; + private int antibotPlayers; + private final CopyOnWriteArrayList antibotKicked = new CopyOnWriteArrayList(); + + @Inject + AntiBotService(Settings settings, Messages messages, PermissionsManager permissionsManager, BukkitService bukkitService) { + // Instances + this.messages = messages; + this.permissionsManager = permissionsManager; + this.bukkitService = bukkitService; + // Initial status + disableTask = null; + antibotPlayers = 0; + antiBotStatus = AntiBotStatus.DISABLED; + // Load settings and start if required + reload(settings); + } + + @Override + public void reload(Settings settings) { + // Load settings + duration = settings.getProperty(ProtectionSettings.ANTIBOT_DURATION); + sensibility = settings.getProperty(ProtectionSettings.ANTIBOT_SENSIBILITY); + + // Stop existing protection + stopProtection(); + antiBotStatus = AntiBotStatus.DISABLED; + + // If antibot is disabled, just stop + if (!settings.getProperty(ProtectionSettings.ENABLE_ANTIBOT)) { + return; + } + + // Schedule the bot activation + bukkitService.scheduleSyncDelayedTask(new Runnable() { + @Override + public void run() { + antiBotStatus = AntiBotStatus.LISTENING; + } + }, 90 * TICKS_PER_SECOND); + } + + protected void startProtection() { + // Disable existing antibot session + stopProtection(); + // Enable the new session + antiBotStatus = AntiBotStatus.ACTIVE; + + // Inform admins + for (Player player : bukkitService.getOnlinePlayers()) { + if (permissionsManager.hasPermission(player, AdminPermission.ANTIBOT_MESSAGES)) { + messages.send(player, MessageKey.ANTIBOT_AUTO_ENABLED_MESSAGE); + } + } + + // Schedule auto-disable + disableTask = bukkitService.runTaskLater(new Runnable() { + @Override + public void run() { + stopProtection(); + } + }, duration * TICKS_PER_MINUTE); + } + + private void stopProtection() { + if(antiBotStatus != AntiBotStatus.ACTIVE) { + return; + } + + // Change status + antiBotStatus = AntiBotStatus.LISTENING; + antibotPlayers = 0; + antibotKicked.clear(); + + // Cancel auto-disable task + disableTask.cancel(); + disableTask = null; + + // Inform admins + for (Player player : bukkitService.getOnlinePlayers()) { + if (permissionsManager.hasPermission(player, AdminPermission.ANTIBOT_MESSAGES)) { + messages.send(player, MessageKey.ANTIBOT_AUTO_DISABLED_MESSAGE, Integer.toString(duration)); + } + } + } + + /** + * Returns the status of the AntiBot service. + * + * @return status of the antibot service + */ + public AntiBotStatus getAntiBotStatus() { + return antiBotStatus; + } + + /** + * Allows to override the status of the protection. + * + * @param started the new protection status + */ + public void overrideAntiBotStatus(boolean started) { + if (antiBotStatus == AntiBotStatus.DISABLED) { + return; + } + if (started) { + startProtection(); + } else { + stopProtection(); + } + } + + /** + * Handles a player joining the server and checks if AntiBot needs to be activated. + */ + public void handlePlayerJoin() { + if (antiBotStatus != AntiBotStatus.LISTENING) { + return; + } + + antibotPlayers++; + if (antibotPlayers > sensibility) { + startProtection(); + return; + } + + bukkitService.scheduleSyncDelayedTask(new Runnable() { + @Override + public void run() { + antibotPlayers--; + } + }, 15 * TICKS_PER_SECOND); + } + + /** + * Returns if a player should be kicked due to antibot service. + * + * @param isAuthAvailable if the player is registered + * @return if the player should be kicked + */ + public boolean shouldKick(boolean isAuthAvailable) { + return !isAuthAvailable && (antiBotStatus == AntiBotStatus.ACTIVE); + } + + /** + * Returns whether the player was kicked because of activated antibot. The list is reset + * when antibot is deactivated. + * + * @param name the name to check + * + * @return true if the given name has been kicked because of Antibot + */ + public boolean wasPlayerKicked(String name) { + return antibotKicked.contains(name.toLowerCase()); + } + + /** + * Adds a name to the list of players kicked by antibot. Should only be used when a player + * is determined to be kicked because of failed antibot verification. + * + * @param name the name to add + */ + public void addPlayerKick(String name) { + antibotKicked.addIfAbsent(name.toLowerCase()); + } + + public enum AntiBotStatus { + LISTENING, + DISABLED, + ACTIVE + } + +} diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommandTest.java index 9b380411..239ba33d 100644 --- a/src/test/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommandTest.java @@ -1,6 +1,6 @@ package fr.xephi.authme.command.executable.authme; -import fr.xephi.authme.AntiBot; +import fr.xephi.authme.service.AntiBotService; import fr.xephi.authme.command.CommandMapper; import fr.xephi.authme.command.FoundCommandResult; import fr.xephi.authme.command.help.HelpProvider; @@ -32,7 +32,7 @@ public class SwitchAntiBotCommandTest { private SwitchAntiBotCommand command; @Mock - private AntiBot antiBot; + private AntiBotService antiBot; @Mock private CommandMapper commandMapper; @@ -43,7 +43,7 @@ public class SwitchAntiBotCommandTest { @Test public void shouldReturnAntiBotState() { // given - given(antiBot.getAntiBotStatus()).willReturn(AntiBot.AntiBotStatus.ACTIVE); + given(antiBot.getAntiBotStatus()).willReturn(AntiBotService.AntiBotStatus.ACTIVE); CommandSender sender = mock(CommandSender.class); // when diff --git a/src/test/java/fr/xephi/authme/listener/OnJoinVerifierTest.java b/src/test/java/fr/xephi/authme/listener/OnJoinVerifierTest.java index c77b5724..32ee6171 100644 --- a/src/test/java/fr/xephi/authme/listener/OnJoinVerifierTest.java +++ b/src/test/java/fr/xephi/authme/listener/OnJoinVerifierTest.java @@ -1,6 +1,6 @@ package fr.xephi.authme.listener; -import fr.xephi.authme.AntiBot; +import fr.xephi.authme.service.AntiBotService; import fr.xephi.authme.TestHelper; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; @@ -61,7 +61,7 @@ public class OnJoinVerifierTest { @Mock private PermissionsManager permissionsManager; @Mock - private AntiBot antiBot; + private AntiBotService antiBotService; @Mock private ValidationService validationService; @Mock @@ -378,46 +378,31 @@ public class OnJoinVerifierTest { @Test public void shouldCheckAntiBot() throws FailedVerificationException { // given - String name = "user123"; + Player player = newPlayerWithName("test123"); boolean hasAuth = false; - given(antiBot.getAntiBotStatus()).willReturn(AntiBot.AntiBotStatus.LISTENING); + given(permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT)).willReturn(false); + given(antiBotService.getAntiBotStatus()).willReturn(AntiBotService.AntiBotStatus.LISTENING); // when - onJoinVerifier.checkAntibot(name, hasAuth); + onJoinVerifier.checkAntibot(player, hasAuth); // then - verify(antiBot).getAntiBotStatus(); + verify(antiBotService).shouldKick(hasAuth); } @Test public void shouldAllowUserWithAuth() throws FailedVerificationException { // given - String name = "Bobby"; + Player player = newPlayerWithName("Bobby"); boolean hasAuth = true; - given(antiBot.getAntiBotStatus()).willReturn(AntiBot.AntiBotStatus.ACTIVE); + given(permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT)).willReturn(false); + given(antiBotService.getAntiBotStatus()).willReturn(AntiBotService.AntiBotStatus.ACTIVE); // when - onJoinVerifier.checkAntibot(name, hasAuth); + onJoinVerifier.checkAntibot(player, hasAuth); // then - verify(antiBot).getAntiBotStatus(); - } - - @Test - public void shouldThrowForActiveAntiBot() { - // given - String name = "Bobby"; - boolean hasAuth = false; - given(antiBot.getAntiBotStatus()).willReturn(AntiBot.AntiBotStatus.ACTIVE); - - // when / then - try { - onJoinVerifier.checkAntibot(name, hasAuth); - fail("Expected exception to be thrown"); - } catch (FailedVerificationException e) { - assertThat(e, exceptionWithData(MessageKey.KICK_ANTIBOT)); - verify(antiBot).addPlayerKick(name); - } + verify(antiBotService).shouldKick(hasAuth); } /** diff --git a/src/test/java/fr/xephi/authme/listener/PlayerListenerTest.java b/src/test/java/fr/xephi/authme/listener/PlayerListenerTest.java index 35179e6e..f9efc830 100644 --- a/src/test/java/fr/xephi/authme/listener/PlayerListenerTest.java +++ b/src/test/java/fr/xephi/authme/listener/PlayerListenerTest.java @@ -1,6 +1,6 @@ package fr.xephi.authme.listener; -import fr.xephi.authme.AntiBot; +import fr.xephi.authme.service.AntiBotService; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.output.MessageKey; @@ -80,7 +80,7 @@ public class PlayerListenerTest { @Mock private DataSource dataSource; @Mock - private AntiBot antiBot; + private AntiBotService antiBotService; @Mock private Management management; @Mock @@ -112,7 +112,7 @@ public class PlayerListenerTest { // then assertThat(event.isCancelled(), equalTo(true)); - verifyZeroInteractions(player, management, antiBot); + verifyZeroInteractions(player, management, antiBotService); } @Test @@ -122,14 +122,14 @@ public class PlayerListenerTest { String name = "Bobby"; Player player = mockPlayerWithName(name); PlayerKickEvent event = new PlayerKickEvent(player, "You logged in from another location", ""); - given(antiBot.wasPlayerKicked(name)).willReturn(false); + given(antiBotService.wasPlayerKicked(name)).willReturn(false); // when listener.onPlayerKick(event); // then assertThat(event.isCancelled(), equalTo(false)); - verify(antiBot).wasPlayerKicked(name); + verify(antiBotService).wasPlayerKicked(name); verify(management).performQuit(player); } @@ -140,14 +140,14 @@ public class PlayerListenerTest { String name = "Bobby"; Player player = mockPlayerWithName(name); PlayerKickEvent event = new PlayerKickEvent(player, "No longer desired here!", ""); - given(antiBot.wasPlayerKicked(name)).willReturn(true); + given(antiBotService.wasPlayerKicked(name)).willReturn(true); // when listener.onPlayerKick(event); // then assertThat(event.isCancelled(), equalTo(false)); - verify(antiBot).wasPlayerKicked(name); + verify(antiBotService).wasPlayerKicked(name); verifyZeroInteractions(management); } @@ -560,11 +560,11 @@ public class PlayerListenerTest { verify(onJoinVerifier).refusePlayerForFullServer(event); verify(onJoinVerifier).checkSingleSession(name); verify(onJoinVerifier).checkIsValidName(name); - verify(onJoinVerifier).checkAntibot(name, true); + verify(onJoinVerifier).checkAntibot(player, true); verify(onJoinVerifier).checkKickNonRegistered(true); verify(onJoinVerifier).checkNameCasing(player, auth); verify(onJoinVerifier).checkPlayerCountry(true, ip); - verify(antiBot).handlePlayerJoin(player); + verify(antiBotService).handlePlayerJoin(); verify(teleportationService).teleportOnJoin(player); verifyNoModifyingCalls(event); } diff --git a/src/test/java/fr/xephi/authme/AntiBotTest.java b/src/test/java/fr/xephi/authme/service/AntiBotTest.java similarity index 61% rename from src/test/java/fr/xephi/authme/AntiBotTest.java rename to src/test/java/fr/xephi/authme/service/AntiBotTest.java index 2b46bab1..0ec5089e 100644 --- a/src/test/java/fr/xephi/authme/AntiBotTest.java +++ b/src/test/java/fr/xephi/authme/service/AntiBotTest.java @@ -1,10 +1,13 @@ -package fr.xephi.authme; +package fr.xephi.authme.service; +import fr.xephi.authme.ReflectionTestUtils; +import fr.xephi.authme.TestHelper; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; import fr.xephi.authme.permission.AdminPermission; import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PlayerStatePermission; +import fr.xephi.authme.service.AntiBotService; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.ProtectionSettings; import fr.xephi.authme.util.BukkitService; @@ -37,7 +40,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; /** - * Test for {@link AntiBot}. + * Test for {@link AntiBotService}. */ @RunWith(MockitoJUnitRunner.class) public class AntiBotTest { @@ -60,58 +63,58 @@ public class AntiBotTest { public void shouldKeepAntiBotDisabled() { // given / when given(settings.getProperty(ProtectionSettings.ENABLE_ANTIBOT)).willReturn(false); - AntiBot antiBot = new AntiBot(settings, messages, permissionsManager, bukkitService); + AntiBotService antiBot = new AntiBotService(settings, messages, permissionsManager, bukkitService); // then verify(bukkitService, never()).scheduleSyncDelayedTask(any(Runnable.class), anyLong()); - assertThat(antiBot.getAntiBotStatus(), equalTo(AntiBot.AntiBotStatus.DISABLED)); + assertThat(antiBot.getAntiBotStatus(), equalTo(AntiBotService.AntiBotStatus.DISABLED)); } @Test public void shouldTransitionToListening() { // given / when - AntiBot antiBot = new AntiBot(settings, messages, permissionsManager, bukkitService); + AntiBotService antiBot = new AntiBotService(settings, messages, permissionsManager, bukkitService); TestHelper.runSyncDelayedTaskWithDelay(bukkitService); // then - assertThat(antiBot.getAntiBotStatus(), equalTo(AntiBot.AntiBotStatus.LISTENING)); + assertThat(antiBot.getAntiBotStatus(), equalTo(AntiBotService.AntiBotStatus.LISTENING)); } @Test public void shouldSetStatusToActive() { // given - AntiBot antiBot = createListeningAntiBot(); + AntiBotService antiBot = createListeningAntiBot(); // when antiBot.overrideAntiBotStatus(true); // then - assertThat(antiBot.getAntiBotStatus(), equalTo(AntiBot.AntiBotStatus.ACTIVE)); + assertThat(antiBot.getAntiBotStatus(), equalTo(AntiBotService.AntiBotStatus.ACTIVE)); } @Test public void shouldSetStatusToListening() { // given - AntiBot antiBot = createListeningAntiBot(); + AntiBotService antiBot = createListeningAntiBot(); // when antiBot.overrideAntiBotStatus(false); // then - assertThat(antiBot.getAntiBotStatus(), equalTo(AntiBot.AntiBotStatus.LISTENING)); + assertThat(antiBot.getAntiBotStatus(), equalTo(AntiBotService.AntiBotStatus.LISTENING)); } @Test public void shouldRemainDisabled() { // given given(settings.getProperty(ProtectionSettings.ENABLE_ANTIBOT)).willReturn(false); - AntiBot antiBot = new AntiBot(settings, messages, permissionsManager, bukkitService); + AntiBotService antiBot = new AntiBotService(settings, messages, permissionsManager, bukkitService); // when antiBot.overrideAntiBotStatus(true); // then - assertThat(antiBot.getAntiBotStatus(), equalTo(AntiBot.AntiBotStatus.DISABLED)); + assertThat(antiBot.getAntiBotStatus(), equalTo(AntiBotService.AntiBotStatus.DISABLED)); } @Test @@ -119,7 +122,7 @@ public class AntiBotTest { // given int duration = 300; given(settings.getProperty(ProtectionSettings.ANTIBOT_DURATION)).willReturn(duration); - AntiBot antiBot = createListeningAntiBot(); + AntiBotService antiBot = createListeningAntiBot(); List onlinePlayers = Arrays.asList(mock(Player.class), mock(Player.class), mock(Player.class)); given(bukkitService.getOnlinePlayers()).willReturn((List) onlinePlayers); given(permissionsManager.hasPermission(onlinePlayers.get(0), AdminPermission.ANTIBOT_MESSAGES)).willReturn(true); @@ -127,10 +130,10 @@ public class AntiBotTest { given(permissionsManager.hasPermission(onlinePlayers.get(2), AdminPermission.ANTIBOT_MESSAGES)).willReturn(true); // when - antiBot.activateAntiBot(); + antiBot.startProtection(); // then - assertThat(antiBot.getAntiBotStatus(), equalTo(AntiBot.AntiBotStatus.ACTIVE)); + assertThat(antiBot.getAntiBotStatus(), equalTo(AntiBotService.AntiBotStatus.ACTIVE)); verify(bukkitService).getOnlinePlayers(); verify(permissionsManager, times(3)).hasPermission(any(Player.class), eq(AdminPermission.ANTIBOT_MESSAGES)); verify(messages).send(onlinePlayers.get(0), MessageKey.ANTIBOT_AUTO_ENABLED_MESSAGE); @@ -147,69 +150,22 @@ public class AntiBotTest { given(messages.retrieve(MessageKey.ANTIBOT_AUTO_DISABLED_MESSAGE)) .willReturn(new String[]{"Disabled...", "Placeholder: %m."}); given(settings.getProperty(ProtectionSettings.ANTIBOT_DURATION)).willReturn(4); - AntiBot antiBot = createListeningAntiBot(); + AntiBotService antiBot = createListeningAntiBot(); // when - antiBot.activateAntiBot(); + antiBot.startProtection(); TestHelper.runSyncDelayedTaskWithDelay(bukkitService); // then - assertThat(antiBot.getAntiBotStatus(), equalTo(AntiBot.AntiBotStatus.LISTENING)); + assertThat(antiBot.getAntiBotStatus(), equalTo(AntiBotService.AntiBotStatus.LISTENING)); verify(bukkitService).scheduleSyncDelayedTask(any(Runnable.class), eq((long) 4800)); ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); verify(bukkitService, times(2)).broadcastMessage(captor.capture()); assertThat(captor.getAllValues(), contains("Disabled...", "Placeholder: 4.")); } - @Test - public void shouldCheckPlayerAndRemoveHimLater() { - // given - Player player = mock(Player.class); - given(player.getName()).willReturn("Plaer"); - given(permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT)).willReturn(false); - given(settings.getProperty(ProtectionSettings.ANTIBOT_SENSIBILITY)).willReturn(10); - AntiBot antiBot = createListeningAntiBot(); - - // when - antiBot.handlePlayerJoin(player); - - // then - List playerList = ReflectionTestUtils - .getFieldValue(AntiBot.class, antiBot, "antibotPlayers"); - assertThat(playerList, hasSize(1)); - verify(bukkitService).scheduleSyncDelayedTask(any(Runnable.class), eq((long) 15 * TICKS_PER_SECOND)); - - // Follow-up: Check that player will be removed from list again by running the Runnable - // given (2) - // Add another player to the list - playerList.add("other_player"); - - // when (2) - TestHelper.runSyncDelayedTaskWithDelay(bukkitService); - - // then (2) - assertThat(playerList, contains("other_player")); - } - - @Test - public void shouldNotUpdateListForPlayerWithByPassPermission() { - // given - Player player = mock(Player.class); - given(permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT)).willReturn(true); - given(settings.getProperty(ProtectionSettings.ANTIBOT_SENSIBILITY)).willReturn(3); - AntiBot antiBot = createListeningAntiBot(); - - // when - antiBot.handlePlayerJoin(player); - - // then - List playerList = ReflectionTestUtils.getFieldValue(AntiBot.class, antiBot, "antibotPlayers"); - assertThat(playerList, empty()); - verify(bukkitService, never()).scheduleSyncDelayedTask(any(Runnable.class), anyLong()); - } - - private AntiBot createListeningAntiBot() { - AntiBot antiBot = new AntiBot(settings, messages, permissionsManager, bukkitService); + private AntiBotService createListeningAntiBot() { + AntiBotService antiBot = new AntiBotService(settings, messages, permissionsManager, bukkitService); TestHelper.runSyncDelayedTaskWithDelay(bukkitService); // Make BukkitService forget about all interactions up to here reset(bukkitService);