diff --git a/pom.xml b/pom.xml index a3ac7819e..21efb0763 100644 --- a/pom.xml +++ b/pom.xml @@ -709,7 +709,7 @@ ch.jalu configme - 0.4 + 0.4.1 compile true diff --git a/src/main/java/fr/xephi/authme/process/login/ProcessSyncPlayerLogin.java b/src/main/java/fr/xephi/authme/process/login/ProcessSyncPlayerLogin.java index bd06dd6b3..299fc5846 100644 --- a/src/main/java/fr/xephi/authme/process/login/ProcessSyncPlayerLogin.java +++ b/src/main/java/fr/xephi/authme/process/login/ProcessSyncPlayerLogin.java @@ -107,9 +107,9 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess { // Login is now finished; we can force all commands if (isFirstLogin) { - commandManager.runCommandsOnFirstLogin(player); + commandManager.runCommandsOnFirstLogin(player, authsWithSameIp); } - commandManager.runCommandsOnLogin(player); + commandManager.runCommandsOnLogin(player, authsWithSameIp); // Send Bungee stuff. The service will check if it is enabled or not. bungeeSender.connectPlayerOnLogin(player); diff --git a/src/main/java/fr/xephi/authme/settings/SettingsMigrationService.java b/src/main/java/fr/xephi/authme/settings/SettingsMigrationService.java index 641492be2..c394fa36f 100644 --- a/src/main/java/fr/xephi/authme/settings/SettingsMigrationService.java +++ b/src/main/java/fr/xephi/authme/settings/SettingsMigrationService.java @@ -2,7 +2,6 @@ package fr.xephi.authme.settings; import ch.jalu.configme.migration.PlainMigrationService; import ch.jalu.configme.properties.Property; -import ch.jalu.configme.properties.StringListProperty; import ch.jalu.configme.resource.PropertyResource; import com.google.common.base.MoreObjects; import fr.xephi.authme.ConsoleLogger; @@ -19,7 +18,6 @@ import javax.inject.Inject; import java.io.File; import java.io.FileWriter; import java.io.IOException; -import java.util.Collections; import java.util.List; import java.util.Set; @@ -39,15 +37,6 @@ public class SettingsMigrationService extends PlainMigrationService { private final File pluginFolder; - // Stores old commands that need to be migrated to the new commands configuration - // We need to store it in here for retrieval when we build the CommandConfig. Retrieving it from the config.yml is - // not possible since this migration service may trigger config.yml to be resaved. As the old command settings - // don't exist in the code anymore, as soon as config.yml is resaved we lose this information. - private List onLoginCommands = Collections.emptyList(); - private List onLoginConsoleCommands = Collections.emptyList(); - private List onRegisterCommands = Collections.emptyList(); - private List onRegisterConsoleCommands = Collections.emptyList(); - @Inject SettingsMigrationService(@DataFolder File pluginFolder) { this.pluginFolder = pluginFolder; @@ -62,8 +51,6 @@ public class SettingsMigrationService extends PlainMigrationService { changes = true; } - gatherOldCommandSettings(resource); - // Note ljacqu 20160211: Concatenating migration methods with | instead of the usual || // ensures that all migrations will be performed return changes @@ -97,35 +84,6 @@ public class SettingsMigrationService extends PlainMigrationService { return false; } - // ---------------- - // Forced commands relocation (from config.yml to commands.yml) - // ---------------- - private void gatherOldCommandSettings(PropertyResource resource) { - onLoginCommands = getStringList(resource, "settings.forceCommands"); - onLoginConsoleCommands = getStringList(resource, "settings.forceCommandsAsConsole"); - onRegisterCommands = getStringList(resource, "settings.forceRegisterCommands"); - onRegisterConsoleCommands = getStringList(resource, "settings.forceRegisterCommandsAsConsole"); - } - - private List getStringList(PropertyResource resource, String path) { - return new StringListProperty(path).getValue(resource); - } - - public List getOnLoginCommands() { - return onLoginCommands; - } - - public List getOnLoginConsoleCommands() { - return onLoginConsoleCommands; - } - - public List getOnRegisterCommands() { - return onRegisterCommands; - } - - public List getOnRegisterConsoleCommands() { - return onRegisterConsoleCommands; - } // -------- // Specific migrations diff --git a/src/main/java/fr/xephi/authme/settings/commandconfig/CommandConfig.java b/src/main/java/fr/xephi/authme/settings/commandconfig/CommandConfig.java index e210f597c..29484ccdd 100644 --- a/src/main/java/fr/xephi/authme/settings/commandconfig/CommandConfig.java +++ b/src/main/java/fr/xephi/authme/settings/commandconfig/CommandConfig.java @@ -11,9 +11,9 @@ import java.util.Map; public class CommandConfig { private Map onJoin = new LinkedHashMap<>(); - private Map onLogin = new LinkedHashMap<>(); + private Map onLogin = new LinkedHashMap<>(); private Map onSessionLogin = new LinkedHashMap<>(); - private Map onFirstLogin = new LinkedHashMap<>(); + private Map onFirstLogin = new LinkedHashMap<>(); private Map onRegister = new LinkedHashMap<>(); private Map onUnregister = new LinkedHashMap<>(); private Map onLogout = new LinkedHashMap<>(); @@ -26,11 +26,11 @@ public class CommandConfig { this.onJoin = onJoin; } - public Map getOnLogin() { + public Map getOnLogin() { return onLogin; } - public void setOnLogin(Map onLogin) { + public void setOnLogin(Map onLogin) { this.onLogin = onLogin; } @@ -42,11 +42,11 @@ public class CommandConfig { this.onSessionLogin = onSessionLogin; } - public Map getOnFirstLogin() { + public Map getOnFirstLogin() { return onFirstLogin; } - public void setOnFirstLogin(Map onFirstLogin) { + public void setOnFirstLogin(Map onFirstLogin) { this.onFirstLogin = onFirstLogin; } diff --git a/src/main/java/fr/xephi/authme/settings/commandconfig/CommandManager.java b/src/main/java/fr/xephi/authme/settings/commandconfig/CommandManager.java index 6fdb5fdee..12579cbae 100644 --- a/src/main/java/fr/xephi/authme/settings/commandconfig/CommandManager.java +++ b/src/main/java/fr/xephi/authme/settings/commandconfig/CommandManager.java @@ -17,6 +17,7 @@ import java.io.File; import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.function.Predicate; import static fr.xephi.authme.util.lazytags.TagBuilder.createTag; @@ -32,9 +33,9 @@ public class CommandManager implements Reloadable { private final List> availableTags = buildAvailableTags(); private WrappedTagReplacer onJoinCommands; - private WrappedTagReplacer onLoginCommands; + private WrappedTagReplacer onLoginCommands; private WrappedTagReplacer onSessionLoginCommands; - private WrappedTagReplacer onFirstLoginCommands; + private WrappedTagReplacer onFirstLoginCommands; private WrappedTagReplacer onRegisterCommands; private WrappedTagReplacer onUnregisterCommands; private WrappedTagReplacer onLogoutCommands; @@ -71,9 +72,12 @@ public class CommandManager implements Reloadable { * Runs the configured commands for when a player has logged in successfully. * * @param player the player that logged in + * @param otherAccounts account names whose IP is the same as the player's */ - public void runCommandsOnLogin(Player player) { - executeCommands(player, onLoginCommands.getAdaptedItems(player)); + public void runCommandsOnLogin(Player player, List otherAccounts) { + final int numberOfOtherAccounts = otherAccounts.size(); + executeCommands(player, onLoginCommands.getAdaptedItems(player), + cmd -> shouldCommandBeRun(cmd, numberOfOtherAccounts)); } /** @@ -89,9 +93,12 @@ public class CommandManager implements Reloadable { * Runs the configured commands for when a player logs in the first time. * * @param player the player that has logged in for the first time + * @param otherAccounts account names whose IP is the same as the player's */ - public void runCommandsOnFirstLogin(Player player) { - executeCommands(player, onFirstLoginCommands.getAdaptedItems(player)); + public void runCommandsOnFirstLogin(Player player, List otherAccounts) { + final int numberOfOtherAccounts = otherAccounts.size(); + executeCommands(player, onFirstLoginCommands.getAdaptedItems(player), + cmd -> shouldCommandBeRun(cmd, numberOfOtherAccounts)); } /** @@ -113,16 +120,29 @@ public class CommandManager implements Reloadable { } private void executeCommands(Player player, List commands) { - for (Command command : commands) { - final String execution = command.getCommand(); - if (Executor.CONSOLE.equals(command.getExecutor())) { - bukkitService.dispatchConsoleCommand(execution); - } else { - bukkitService.dispatchCommand(player, execution); + executeCommands(player, commands, c -> true); + } + + private void executeCommands(Player player, List commands, Predicate predicate) { + for (T command : commands) { + if (predicate.test(command)) { + final String execution = command.getCommand(); + if (Executor.CONSOLE.equals(command.getExecutor())) { + bukkitService.dispatchConsoleCommand(execution); + } else { + bukkitService.dispatchCommand(player, execution); + } } } } + private static boolean shouldCommandBeRun(OnLoginCommand command, int numberOfOtherAccounts) { + return (!command.getIfNumberOfAccountsAtLeast().isPresent() + || command.getIfNumberOfAccountsAtLeast().get() <= numberOfOtherAccounts) + && (!command.getIfNumberOfAccountsLessThan().isPresent() + || command.getIfNumberOfAccountsLessThan().get() > numberOfOtherAccounts); + } + @Override public void reload() { File file = new File(dataFolder, "commands.yml"); @@ -132,8 +152,8 @@ public class CommandManager implements Reloadable { new YamlFileResource(file), commandMigrationService, CommandSettingsHolder.class); CommandConfig commandConfig = settingsManager.getProperty(CommandSettingsHolder.COMMANDS); onJoinCommands = newReplacer(commandConfig.getOnJoin()); - onLoginCommands = newReplacer(commandConfig.getOnLogin()); - onFirstLoginCommands = newReplacer(commandConfig.getOnFirstLogin()); + onLoginCommands = newOnLoginCmdReplacer(commandConfig.getOnLogin()); + onFirstLoginCommands = newOnLoginCmdReplacer(commandConfig.getOnFirstLogin()); onSessionLoginCommands = newReplacer(commandConfig.getOnSessionLogin()); onRegisterCommands = newReplacer(commandConfig.getOnRegister()); onUnregisterCommands = newReplacer(commandConfig.getOnUnregister()); @@ -145,6 +165,14 @@ public class CommandManager implements Reloadable { (cmd, text) -> new Command(text, cmd.getExecutor())); } + private WrappedTagReplacer newOnLoginCmdReplacer( + Map commands) { + + return new WrappedTagReplacer<>(availableTags, commands.values(), Command::getCommand, + (cmd, text) -> new OnLoginCommand(text, cmd.getExecutor(), cmd.getIfNumberOfAccountsAtLeast(), + cmd.getIfNumberOfAccountsLessThan())); + } + private List> buildAvailableTags() { return Arrays.asList( createTag("%p", pl -> pl.getName()), diff --git a/src/main/java/fr/xephi/authme/settings/commandconfig/CommandMigrationService.java b/src/main/java/fr/xephi/authme/settings/commandconfig/CommandMigrationService.java index acd39cc64..9775f8e02 100644 --- a/src/main/java/fr/xephi/authme/settings/commandconfig/CommandMigrationService.java +++ b/src/main/java/fr/xephi/authme/settings/commandconfig/CommandMigrationService.java @@ -5,15 +5,8 @@ import ch.jalu.configme.properties.Property; import ch.jalu.configme.resource.PropertyResource; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; -import fr.xephi.authme.ConsoleLogger; -import fr.xephi.authme.settings.SettingsMigrationService; -import fr.xephi.authme.util.RandomStringUtils; -import javax.inject.Inject; import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; /** * Migrates the commands from their old location, in config.yml, to the dedicated commands configuration file. @@ -25,108 +18,20 @@ class CommandMigrationService implements MigrationService { static final List COMMAND_CONFIG_PROPERTIES = ImmutableList.of( "onJoin", "onLogin", "onSessionLogin", "onFirstLogin", "onRegister", "onUnregister", "onLogout"); - @Inject - private SettingsMigrationService settingsMigrationService; - CommandMigrationService() { } @Override public boolean checkAndMigrate(PropertyResource resource, List> properties) { final CommandConfig commandConfig = CommandSettingsHolder.COMMANDS.getValue(resource); - final boolean didMoveCommands = transformOldCommands(commandConfig); - - if (didMoveCommands || isFileEmpty(resource)) { + if (isFileEmpty(resource)) { resource.setValue("", commandConfig); return true; } return false; } - private boolean isFileEmpty(PropertyResource resource) { + private static boolean isFileEmpty(PropertyResource resource) { return COMMAND_CONFIG_PROPERTIES.stream().anyMatch(property -> resource.getObject(property) == null); } - - /** - * Adds command settings from their old location (in config.yml) to the given command configuration object. - * - * @param commandConfig the command config object to move old commands to - * @return true if commands have been moved, false if no migration was necessary - */ - @VisibleForTesting - boolean transformOldCommands(CommandConfig commandConfig) { - boolean didMoveCommands = false; - for (MigratableCommandSection section : MigratableCommandSection.values()) { - didMoveCommands |= section.convertCommands(settingsMigrationService, commandConfig); - } - return didMoveCommands; - } - - /** - * Enum defining the forced command settings that should be moved from config.yml to the new commands.yml file. - */ - private enum MigratableCommandSection { - - ON_JOIN( - SettingsMigrationService::getOnLoginCommands, - Executor.PLAYER, - CommandConfig::getOnLogin), - - ON_JOIN_CONSOLE( - SettingsMigrationService::getOnLoginConsoleCommands, - Executor.CONSOLE, - CommandConfig::getOnLogin), - - ON_REGISTER( - SettingsMigrationService::getOnRegisterCommands, - Executor.PLAYER, - CommandConfig::getOnRegister), - - ON_REGISTER_CONSOLE( - SettingsMigrationService::getOnRegisterConsoleCommands, - Executor.CONSOLE, - CommandConfig::getOnRegister); - - private final Function> legacyCommandsGetter; - private final Executor executor; - private final Function> commandMapGetter; - - /** - * Constructor. - * - * @param legacyCommandsGetter getter on MigrationService to get the deprecated command entries - * @param executor the executor of the commands - * @param commandMapGetter the getter for the commands map in the new settings structure to add the old - * settings to after conversion - */ - MigratableCommandSection(Function> legacyCommandsGetter, - Executor executor, - Function> commandMapGetter) { - this.legacyCommandsGetter = legacyCommandsGetter; - this.executor = executor; - this.commandMapGetter = commandMapGetter; - } - - /** - * Adds the commands from the sections' settings migration service to the appropriate place in the new - * command config object. - * - * @param settingsMigrationService settings migration service to read old commands from - * @param commandConfig command config object to add converted commands to - * @return true if there were commands to migrate, false otherwise - */ - boolean convertCommands(SettingsMigrationService settingsMigrationService, CommandConfig commandConfig) { - List commands = legacyCommandsGetter.apply(settingsMigrationService).stream() - .map(cmd -> new Command(cmd, executor)).collect(Collectors.toList()); - - if (commands.isEmpty()) { - return false; - } - Map commandMap = commandMapGetter.apply(commandConfig); - commands.forEach(cmd -> commandMap.put(RandomStringUtils.generate(10), cmd)); - ConsoleLogger.info("Moving " + commands.size() + " commands of type " + this - + " from config.yml to commands.yml"); - return true; - } - } } diff --git a/src/main/java/fr/xephi/authme/settings/commandconfig/CommandSettingsHolder.java b/src/main/java/fr/xephi/authme/settings/commandconfig/CommandSettingsHolder.java index 87530d22f..965813c96 100644 --- a/src/main/java/fr/xephi/authme/settings/commandconfig/CommandSettingsHolder.java +++ b/src/main/java/fr/xephi/authme/settings/commandconfig/CommandSettingsHolder.java @@ -49,8 +49,17 @@ public final class CommandSettingsHolder implements SettingsHolder { " executor: CONSOLE", "", "Supported command events: onLogin, onSessionLogin, onFirstLogin, onJoin, onLogout, onRegister, " - + "onUnregister" + + "onUnregister", + "", + "For onLogin and onFirstLogin, you can use 'ifNumberOfAccountsLessThan' and 'ifNumberOfAccountsAtLeast'", + "to specify limits to how many accounts a player can have (matched by IP) for a command to be run:", + "onLogin:", + " warnOnManyAccounts:", + " command: 'say Uh oh! %p has many alt accounts!'", + " executor: CONSOLE", + " ifNumberOfAccountsAtLeast: 5" }; + Map commentMap = new HashMap<>(); commentMap.put("", rootComments); commentMap.put("onFirstLogin", new String[]{ diff --git a/src/main/java/fr/xephi/authme/settings/commandconfig/OnLoginCommand.java b/src/main/java/fr/xephi/authme/settings/commandconfig/OnLoginCommand.java new file mode 100644 index 000000000..4396b3211 --- /dev/null +++ b/src/main/java/fr/xephi/authme/settings/commandconfig/OnLoginCommand.java @@ -0,0 +1,59 @@ +package fr.xephi.authme.settings.commandconfig; + +import java.util.Optional; + +/** + * Configurable command for when a player logs in. + */ +public class OnLoginCommand extends Command { + + private Optional ifNumberOfAccountsAtLeast; + private Optional ifNumberOfAccountsLessThan; + + /** + * Default constructor (for bean mapping). + */ + public OnLoginCommand() { + } + + /** + * Constructor. + * + * @param command the command to execute + * @param executor the executor of the command + */ + public OnLoginCommand(String command, Executor executor) { + super(command, executor); + } + + /** + * Constructor. + * + * @param command the command to execute + * @param executor the executor of the command + * @param ifNumberOfAccountsAtLeast required number of accounts for the command to run + * @param ifNumberOfAccountsLessThan max threshold of accounts, from which the command will not be run + */ + public OnLoginCommand(String command, Executor executor, Optional ifNumberOfAccountsAtLeast, + Optional ifNumberOfAccountsLessThan) { + super(command, executor); + this.ifNumberOfAccountsAtLeast = ifNumberOfAccountsAtLeast; + this.ifNumberOfAccountsLessThan = ifNumberOfAccountsLessThan; + } + + public Optional getIfNumberOfAccountsAtLeast() { + return ifNumberOfAccountsAtLeast; + } + + public void setIfNumberOfAccountsAtLeast(Optional ifNumberOfAccountsAtLeast) { + this.ifNumberOfAccountsAtLeast = ifNumberOfAccountsAtLeast; + } + + public Optional getIfNumberOfAccountsLessThan() { + return ifNumberOfAccountsLessThan; + } + + public void setIfNumberOfAccountsLessThan(Optional ifNumberOfAccountsLessThan) { + this.ifNumberOfAccountsLessThan = ifNumberOfAccountsLessThan; + } +} diff --git a/src/main/resources/commands.yml b/src/main/resources/commands.yml index 5e7717ac9..67ec44907 100644 --- a/src/main/resources/commands.yml +++ b/src/main/resources/commands.yml @@ -25,6 +25,14 @@ # executor: CONSOLE # # Supported command events: onLogin, onSessionLogin, onFirstLogin, onJoin, onLogout, onRegister, onUnregister +# +# For onLogin and onFirstLogin, you can use 'ifNumberOfAccountsLessThan' and 'ifNumberOfAccountsAtLeast' +# to specify limits to how many accounts a player can have (matched by IP) for a command to be run: +# onLogin: +# warnOnManyAccounts: +# command: 'say Uh oh! %p has many alt accounts!' +# executor: CONSOLE +# ifNumberOfAccountsAtLeast: 5 # Commands to run for players logging in whose 'last login date' was empty onFirstLogin: {} onJoin: {} diff --git a/src/test/java/fr/xephi/authme/settings/SettingsMigrationServiceTest.java b/src/test/java/fr/xephi/authme/settings/SettingsMigrationServiceTest.java index 0a952bb0b..64e9c1396 100644 --- a/src/test/java/fr/xephi/authme/settings/SettingsMigrationServiceTest.java +++ b/src/test/java/fr/xephi/authme/settings/SettingsMigrationServiceTest.java @@ -97,25 +97,6 @@ public class SettingsMigrationServiceTest { assertThat(migrationService.returnedValues, contains(true, false)); } - @Test - public void shouldKeepOldForceCommandSettings() throws IOException { - // given - File dataFolder = temporaryFolder.newFolder(); - File configFile = new File(dataFolder, "config.yml"); - Files.copy(getJarFile(OLD_CONFIG_FILE), configFile); - PropertyResource resource = new YamlFileResource(configFile); - SettingsMigrationService migrationService = new SettingsMigrationService(dataFolder); - - // when - migrationService.performMigrations(resource, AuthMeSettingsRetriever.buildConfigurationData().getProperties()); - - // then - assertThat(migrationService.getOnLoginCommands(), contains("spawn")); - assertThat(migrationService.getOnLoginConsoleCommands(), contains("sethome %p:lastloc", "msg %p Welcome back")); - assertThat(migrationService.getOnRegisterCommands(), contains("me registers", "msg CONSOLE hi")); - assertThat(migrationService.getOnRegisterConsoleCommands(), contains("sethome %p:regloc")); - } - private void verifyHasUpToDateSettings(Settings settings, File dataFolder) throws IOException { assertThat(settings.getProperty(ALLOWED_NICKNAME_CHARACTERS), equalTo(ALLOWED_NICKNAME_CHARACTERS.getDefaultValue())); assertThat(settings.getProperty(DELAY_JOIN_MESSAGE), equalTo(true)); diff --git a/src/test/java/fr/xephi/authme/settings/commandconfig/CommandConfigTestHelper.java b/src/test/java/fr/xephi/authme/settings/commandconfig/CommandConfigTestHelper.java deleted file mode 100644 index 88ee90f3d..000000000 --- a/src/test/java/fr/xephi/authme/settings/commandconfig/CommandConfigTestHelper.java +++ /dev/null @@ -1,35 +0,0 @@ -package fr.xephi.authme.settings.commandconfig; - -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; - -/** - * Helper class for tests around the command configuration. - */ -final class CommandConfigTestHelper { - - private CommandConfigTestHelper() { - } - - /** - * Returns a matcher for verifying a {@link Command} object. - * - * @param cmd the expected command line - * @param executor the expected executor - * @return the matcher - */ - static Matcher isCommand(String cmd, Executor executor) { - return new TypeSafeMatcher() { - @Override - protected boolean matchesSafely(Command item) { - return executor.equals(item.getExecutor()) && cmd.equals(item.getCommand()); - } - - @Override - public void describeTo(Description description) { - description.appendText("Command '" + cmd + "' run by '" + executor + "'"); - } - }; - } -} diff --git a/src/test/java/fr/xephi/authme/settings/commandconfig/CommandManagerTest.java b/src/test/java/fr/xephi/authme/settings/commandconfig/CommandManagerTest.java index b4183d700..a482eedb8 100644 --- a/src/test/java/fr/xephi/authme/settings/commandconfig/CommandManagerTest.java +++ b/src/test/java/fr/xephi/authme/settings/commandconfig/CommandManagerTest.java @@ -17,6 +17,8 @@ import org.mockito.junit.MockitoJUnitRunner; import java.io.File; import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -66,7 +68,7 @@ public class CommandManagerTest { initManager(); // when - manager.runCommandsOnLogin(player); + manager.runCommandsOnLogin(player, Collections.emptyList()); // then verify(bukkitService).dispatchConsoleCommand("msg Bobby Welcome back"); @@ -76,6 +78,61 @@ public class CommandManagerTest { verifyZeroInteractions(geoIpService); } + @Test + public void shouldExecuteCommandsOnLoginWithTwoAlts() { + // given + copyJarFileAsCommandsYml(TEST_FILES_FOLDER + "commands.complete.yml"); + initManager(); + + // when + manager.runCommandsOnLogin(player, Arrays.asList("willy", "nilly", "billy", "silly")); + + // then + verify(bukkitService).dispatchConsoleCommand("msg Bobby Welcome back"); + verify(bukkitService).dispatchCommand(player, "motd"); + verify(bukkitService).dispatchCommand(player, "list"); + verify(bukkitService).dispatchConsoleCommand("helpop Player Bobby has more than 1 account"); + verifyNoMoreInteractions(bukkitService); + verifyZeroInteractions(geoIpService); + } + + @Test + public void shouldExecuteCommandsOnLoginWithFifteenAlts() { + // given + copyJarFileAsCommandsYml(TEST_FILES_FOLDER + "commands.complete.yml"); + initManager(); + + // when + manager.runCommandsOnLogin(player, Collections.nCopies(15, "swag")); + + // then + verify(bukkitService).dispatchConsoleCommand("msg Bobby Welcome back"); + verify(bukkitService).dispatchCommand(player, "motd"); + verify(bukkitService).dispatchCommand(player, "list"); + verify(bukkitService).dispatchConsoleCommand("helpop Player Bobby has more than 1 account"); + verify(bukkitService).dispatchConsoleCommand("log Bobby 127.0.0.3 many accounts"); + verifyNoMoreInteractions(bukkitService); + verifyZeroInteractions(geoIpService); + } + + @Test + public void shouldExecuteCommandsOnLoginWithTwentyFiveAlts() { + // given + copyJarFileAsCommandsYml(TEST_FILES_FOLDER + "commands.complete.yml"); + initManager(); + + // when + manager.runCommandsOnLogin(player, Collections.nCopies(25, "yolo")); + + // then + verify(bukkitService).dispatchConsoleCommand("msg Bobby Welcome back"); + verify(bukkitService).dispatchCommand(player, "motd"); + verify(bukkitService).dispatchCommand(player, "list"); + verify(bukkitService).dispatchConsoleCommand("helpop Player Bobby has more than 1 account"); + verifyNoMoreInteractions(bukkitService); + verifyZeroInteractions(geoIpService); + } + @Test public void shouldExecuteCommandsOnLoginWithIncompleteConfig() { // given @@ -83,7 +140,7 @@ public class CommandManagerTest { initManager(); // when - manager.runCommandsOnLogin(player); + manager.runCommandsOnLogin(player, Collections.emptyList()); // then verify(bukkitService).dispatchConsoleCommand("msg Bobby Welcome back, bob"); @@ -114,7 +171,7 @@ public class CommandManagerTest { initManager(); // when - manager.runCommandsOnFirstLogin(player); + manager.runCommandsOnFirstLogin(player, Collections.emptyList()); // then verify(bukkitService).dispatchConsoleCommand("pay Bobby 30"); @@ -122,6 +179,19 @@ public class CommandManagerTest { verifyZeroInteractions(geoIpService); } + @Test + public void shouldNotExecuteFirstLoginCommandWhoseThresholdIsNotMet() { + // given + copyJarFileAsCommandsYml(TEST_FILES_FOLDER + "commands.complete.yml"); + initManager(); + + // when + manager.runCommandsOnFirstLogin(player, Arrays.asList("u", "wot", "m8")); + + // then + verifyZeroInteractions(bukkitService, geoIpService); + } + @Test public void shouldExecuteCommandsOnJoin() { // given diff --git a/src/test/java/fr/xephi/authme/settings/commandconfig/CommandMigrationServiceTest.java b/src/test/java/fr/xephi/authme/settings/commandconfig/CommandMigrationServiceTest.java index 21f4d0479..1c68a4571 100644 --- a/src/test/java/fr/xephi/authme/settings/commandconfig/CommandMigrationServiceTest.java +++ b/src/test/java/fr/xephi/authme/settings/commandconfig/CommandMigrationServiceTest.java @@ -6,33 +6,17 @@ import ch.jalu.configme.configurationdata.ConfigurationDataBuilder; import ch.jalu.configme.resource.PropertyResource; import ch.jalu.configme.resource.YamlFileResource; import fr.xephi.authme.TestHelper; -import fr.xephi.authme.settings.SettingsMigrationService; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; -import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import java.io.File; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import static fr.xephi.authme.settings.commandconfig.CommandConfigTestHelper.isCommand; -import static java.util.Collections.emptyList; -import static org.hamcrest.Matchers.anEmptyMap; -import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.sameInstance; import static org.junit.Assert.assertThat; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verifyZeroInteractions; /** * Test for {@link CommandMigrationService}. @@ -43,79 +27,11 @@ public class CommandMigrationServiceTest { @InjectMocks private CommandMigrationService commandMigrationService; - @Mock - private SettingsMigrationService settingsMigrationService; - - private CommandConfig commandConfig = new CommandConfig(); - @BeforeClass public static void setUpLogger() { TestHelper.setupLogger(); } - @Test - public void shouldNotPerformAnyMigration() { - // given - given(settingsMigrationService.getOnLoginCommands()).willReturn(emptyList()); - given(settingsMigrationService.getOnLoginConsoleCommands()).willReturn(emptyList()); - given(settingsMigrationService.getOnRegisterCommands()).willReturn(emptyList()); - given(settingsMigrationService.getOnRegisterConsoleCommands()).willReturn(emptyList()); - commandConfig.getOnRegister().put("existing", new Command("existing cmd", Executor.PLAYER)); - CommandConfig configSpy = spy(commandConfig); - - // when - boolean result = commandMigrationService.transformOldCommands(configSpy); - - // then - assertThat(result, equalTo(false)); - verifyZeroInteractions(configSpy); - assertThat(configSpy.getOnRegister().keySet(), contains("existing")); - assertThat(configSpy.getOnLogin(), anEmptyMap()); - } - - @Test - @SuppressWarnings("unchecked") - public void shouldPerformMigration() { - // given - List onLogin = Collections.singletonList("on login command"); - given(settingsMigrationService.getOnLoginCommands()).willReturn(onLogin); - List onLoginConsole = Arrays.asList("cmd1", "cmd2 %p", "cmd3"); - given(settingsMigrationService.getOnLoginConsoleCommands()).willReturn(onLoginConsole); - given(settingsMigrationService.getOnRegisterCommands()).willReturn(emptyList()); - List onRegisterConsole = Arrays.asList("log %p registered", "whois %p"); - given(settingsMigrationService.getOnRegisterConsoleCommands()).willReturn(onRegisterConsole); - - Map onLoginCommands = new LinkedHashMap<>(); - onLoginCommands.put("bcast", new Command("bcast %p returned", Executor.CONSOLE)); - commandConfig.setOnLogin(onLoginCommands); - Map onRegisterCommands = new LinkedHashMap<>(); - onRegisterCommands.put("ex_cmd", new Command("existing", Executor.CONSOLE)); - onRegisterCommands.put("ex_cmd2", new Command("existing2", Executor.PLAYER)); - commandConfig.setOnRegister(onRegisterCommands); - - // when - boolean result = commandMigrationService.transformOldCommands(commandConfig); - - // then - assertThat(result, equalTo(true)); - assertThat(commandConfig.getOnLogin(), sameInstance(onLoginCommands)); - Collection loginCmdList = onLoginCommands.values(); - assertThat(loginCmdList, contains( - equalTo(onLoginCommands.get("bcast")), - isCommand("on login command", Executor.PLAYER), - isCommand("cmd1", Executor.CONSOLE), - isCommand("cmd2 %p", Executor.CONSOLE), - isCommand("cmd3", Executor.CONSOLE))); - - assertThat(commandConfig.getOnRegister(), sameInstance(onRegisterCommands)); - Collection registerCmdList = onRegisterCommands.values(); - assertThat(registerCmdList, contains( - isCommand("existing", Executor.CONSOLE), - isCommand("existing2", Executor.PLAYER), - isCommand("log %p registered", Executor.CONSOLE), - isCommand("whois %p", Executor.CONSOLE))); - } - @Test public void shouldRewriteForEmptyFile() { // given diff --git a/src/test/java/fr/xephi/authme/settings/commandconfig/CommandYmlConsistencyTest.java b/src/test/java/fr/xephi/authme/settings/commandconfig/CommandYmlConsistencyTest.java index 8c599e929..342994814 100644 --- a/src/test/java/fr/xephi/authme/settings/commandconfig/CommandYmlConsistencyTest.java +++ b/src/test/java/fr/xephi/authme/settings/commandconfig/CommandYmlConsistencyTest.java @@ -4,22 +4,17 @@ import ch.jalu.configme.configurationdata.ConfigurationDataBuilder; import ch.jalu.configme.resource.PropertyResource; import ch.jalu.configme.resource.YamlFileResource; import fr.xephi.authme.TestHelper; -import fr.xephi.authme.settings.SettingsMigrationService; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.mockito.InjectMocks; -import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import java.io.File; -import java.util.Collections; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; -import static org.mockito.BDDMockito.given; /** * Tests that commands.yml is well-formed. @@ -30,20 +25,9 @@ public class CommandYmlConsistencyTest { @InjectMocks private CommandMigrationService commandMigrationService; - @Mock - private SettingsMigrationService settingsMigrationService; - @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); - @Before - public void setUpSettingsMigrationService() { - given(settingsMigrationService.getOnLoginCommands()).willReturn(Collections.emptyList()); - given(settingsMigrationService.getOnLoginConsoleCommands()).willReturn(Collections.emptyList()); - given(settingsMigrationService.getOnRegisterCommands()).willReturn(Collections.emptyList()); - given(settingsMigrationService.getOnRegisterConsoleCommands()).willReturn(Collections.emptyList()); - } - @Test public void shouldLoadWithNoMigrations() { // given diff --git a/src/test/resources/fr/xephi/authme/settings/commandconfig/commands.complete.yml b/src/test/resources/fr/xephi/authme/settings/commandconfig/commands.complete.yml index 7bcf0b770..efd11db56 100644 --- a/src/test/resources/fr/xephi/authme/settings/commandconfig/commands.complete.yml +++ b/src/test/resources/fr/xephi/authme/settings/commandconfig/commands.complete.yml @@ -21,6 +21,15 @@ onLogin: display_list: command: 'list' executor: PLAYER + warn_for_alts: + command: 'helpop Player %p has more than 1 account' + executor: CONSOLE + ifNumberOfAccountsAtLeast: 2 + log_suspicious_user: + command: 'log %p %ip many accounts' + executor: CONSOLE + ifNumberOfAccountsAtLeast: 5 + ifNumberOfAccountsLessThan: 20 onSessionLogin: welcome: command: 'msg %p Session login!' @@ -29,6 +38,7 @@ onFirstLogin: give_money: command: 'pay %p 30' executor: CONSOLE + ifNumberOfAccountsLessThan: 3 onUnregister: {} onLogout: announce: