diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java index d49abed8..639a1f3a 100644 --- a/src/main/java/fr/xephi/authme/AuthMe.java +++ b/src/main/java/fr/xephi/authme/AuthMe.java @@ -226,11 +226,9 @@ public class AuthMe extends JavaPlugin { plugin = this; setupConstants(); - // Set up the permissions manager - setupPermissionsManager(); - - // Set up and initialize the command handler - setupCommandHandler(); + // Set up the permissions manager and command handler + permsMan = initializePermissionsManager(); + commandHandler = new CommandHandler(CommandInitializer.getBaseCommands(), permsMan); // Set up the module manager setupModuleManager(); @@ -442,13 +440,6 @@ public class AuthMe extends JavaPlugin { new API(this); } - /** - * Set up the command handler. - */ - private void setupCommandHandler() { - this.commandHandler = new CommandHandler(CommandInitializer.getBaseCommands()); - } - /** * Load the plugin's settings. * @@ -617,9 +608,10 @@ public class AuthMe extends JavaPlugin { /** * Set up the permissions manager. */ - public void setupPermissionsManager() { - this.permsMan = new PermissionsManager(Bukkit.getServer(), this, getLogger()); - this.permsMan.setup(); + private PermissionsManager initializePermissionsManager() { + PermissionsManager manager = new PermissionsManager(Bukkit.getServer(), this, getLogger()); + manager.setup(); + return manager; } /** diff --git a/src/main/java/fr/xephi/authme/command/CommandArgumentDescription.java b/src/main/java/fr/xephi/authme/command/CommandArgumentDescription.java index f846b789..9ae3da4b 100644 --- a/src/main/java/fr/xephi/authme/command/CommandArgumentDescription.java +++ b/src/main/java/fr/xephi/authme/command/CommandArgumentDescription.java @@ -6,9 +6,9 @@ package fr.xephi.authme.command; public class CommandArgumentDescription { /** - * Argument label (one-word description of the argument). + * Argument name (one-word description of the argument). */ - private final String label; + private final String name; /** * Argument description. */ @@ -21,23 +21,23 @@ public class CommandArgumentDescription { /** * Constructor. * - * @param label The argument label. + * @param name The argument name. * @param description The argument description. * @param isOptional True if the argument is optional, false otherwise. */ - public CommandArgumentDescription(String label, String description, boolean isOptional) { - this.label = label; + public CommandArgumentDescription(String name, String description, boolean isOptional) { + this.name = name; this.description = description; this.isOptional = isOptional; } /** - * Get the argument label. + * Get the argument name. * - * @return Argument label. + * @return Argument name. */ - public String getLabel() { - return this.label; + public String getName() { + return this.name; } /** diff --git a/src/main/java/fr/xephi/authme/command/CommandDescription.java b/src/main/java/fr/xephi/authme/command/CommandDescription.java index dbbd1ffa..d398af67 100644 --- a/src/main/java/fr/xephi/authme/command/CommandDescription.java +++ b/src/main/java/fr/xephi/authme/command/CommandDescription.java @@ -4,15 +4,13 @@ import fr.xephi.authme.permission.DefaultPermission; import fr.xephi.authme.permission.PermissionNode; import fr.xephi.authme.util.CollectionUtils; import fr.xephi.authme.util.StringUtils; -import org.bukkit.command.CommandSender; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; import java.util.List; +import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Arrays.asList; + /** * Command description - defines which labels ("names") will lead to a command and points to the * {@link ExecutableCommand} implementation that executes the logic of the command. @@ -29,15 +27,15 @@ public class CommandDescription { */ private List labels; /** - * Command description. + * Short description of the command. */ private String description; /** - * Detailed description of the command. + * Detailed description of what the command does. */ private String detailedDescription; /** - * The executable command instance. + * The executable command instance described by this object. */ private ExecutableCommand executableCommand; /** @@ -53,7 +51,7 @@ public class CommandDescription { */ private List arguments; /** - * Defines the command permissions. + * Command permissions required to execute this command. */ private CommandPermissions permissions; @@ -67,7 +65,7 @@ public class CommandDescription { } /** - * Create an instance for internal use. + * Create an instance. * * @param labels List of command labels. * @param description Command description. @@ -99,58 +97,29 @@ public class CommandDescription { return instance; } - /** - * Get the label most similar to the reference. The first label will be returned if no reference was supplied. - * - * @param reference The command reference. - * - * @return The most similar label, or the first label. An empty label will be returned if no label was set. - */ - public String getLabel(CommandParts reference) { - // Ensure there's any item in the command list - if (this.labels.size() == 0) - return ""; - - // Return the first label if we can't use the reference - if (reference == null) - return this.labels.get(0); - - // Get the correct label from the reference - String preferred = reference.get(getParentCount()); - - // Check whether the preferred label is in the label list - double currentDifference = -1; - String currentLabel = this.labels.get(0); - for (String entry : this.labels) { - double entryDifference = StringUtils.getDifference(entry, preferred); - if (entryDifference < currentDifference || currentDifference < 0) { - currentDifference = entryDifference; - currentLabel = entry; - } - } - - // Return the most similar label - return currentLabel; + private void addChild(CommandDescription command) { + children.add(command); } /** - * Get all relative command labels. + * Get all relative labels of this command. For example, if this object describes "/authme register" and + * "/authme r", then "r" and "register" are the relative labels, whereas "authme" is the label of the parent. * - * @return All relative labels labels. + * @return All relative labels. */ public List getLabels() { - return this.labels; + return labels; } /** * Check whether this command description has a specific command. * - * @param commandLabel Command to check for. + * @param commandLabel The label to check for. * - * @return True if this command label equals to the param command. + * @return {@code true} if this command contains the given label, {@code false} otherwise. */ public boolean hasLabel(String commandLabel) { - for (String label : this.labels) { + for (String label : labels) { if (label.equalsIgnoreCase(commandLabel)) { return true; } @@ -159,263 +128,55 @@ public class CommandDescription { } /** - * Check whether this command label is applicable with a command reference. This doesn't check if the parent - * are suitable too. + * Return the {@link ExecutableCommand} instance defined by the command description. * - * @param commandReference The command reference. - * - * @return True if the command reference is suitable to this command label, false otherwise. - */ - public boolean isSuitableLabel(CommandParts commandReference) { - // Get the parent count - //getParent() = getParent().getParentCount() + 1 - String element = commandReference.get(getParentCount()); - - // Check whether this command description has this command label - for (String label : labels) { - if (label.equalsIgnoreCase(element)) { - return true; - } - } - return false; - } - - /** - * Get the command reference. - * - * @param reference The reference to use as template, which is used to choose the most similar reference. - * - * @return Command reference. - */ - public CommandParts getCommandReference(CommandParts reference) { - // Build the reference - List referenceList = new ArrayList<>(); - - // Check whether this command has a parent, if so, add the absolute parent command - if (getParent() != null) { - referenceList.addAll(getParent().getCommandReference(reference).getList()); - } - - // Get the current label - referenceList.add(getLabel(reference)); - - // Return the reference - return new CommandParts(referenceList); - } - - /** - * Get the difference between this command and another command reference. - * - * @param other The other command reference. - * - * @return The command difference. Zero if there's no difference. A negative number on error. - */ - public double getCommandDifference(CommandParts other) { - return getCommandDifference(other, false); - } - - /** - * Get the difference between this command and another command reference. - * - * @param other The other command reference. - * @param fullCompare True to fully compare both command references. - * - * @return The command difference. Zero if there's no difference. A negative number on error. - */ - public double getCommandDifference(CommandParts other, boolean fullCompare) { - // Make sure the reference is valid - if (other == null) - return -1; - - // Get the command reference - CommandParts reference = getCommandReference(other); - - // Compare the two references, return the result - return CommandUtils.getDifference(reference.getList(), - CollectionUtils.getRange(other.getList(), 0, reference.getList().size()), fullCompare); - } - - /** - * Get the executable command. - * - * @return The executable command. + * @return The executable command object. */ public ExecutableCommand getExecutableCommand() { - return this.executableCommand; + return executableCommand; } /** - * Set the executable command. + * Return the parent. * - * @param executableCommand The executable command. - */ - public void setExecutableCommand(ExecutableCommand executableCommand) { - this.executableCommand = executableCommand; - } - - /** - * Execute the command, if possible. - * - * @param sender The command sender that triggered the execution of this command. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True on success, false on failure. - */ - public boolean execute(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // Execute the command, return the result - return getExecutableCommand().executeCommand(sender, commandReference, commandArguments); - } - - /** - * Get the parent command if this command description has a parent. - * - * @return Parent command, or null + * @return The parent command, or null for base commands. */ public CommandDescription getParent() { - return this.parent; + return parent; } /** - * Get the number of parent this description has. + * Return the number of labels necessary to get to this command. This corresponds to the number of parents + 1. * - * @return The number of parents. + * @return The number of labels, e.g. for "/authme abc def" the label count is 3 */ - public int getParentCount() { - // Check whether the this description has a parent - if (!hasParent()) - return 0; - - // Get the parent count of the parent, return the result - return getParent().getParentCount() + 1; + public int getLabelCount() { + if (parent == null) { + return 1; + } + return parent.getLabelCount() + 1; } /** - * Set the parent command. - * - * @param parent Parent command. - * - * @return True on success, false on failure. - */ - public boolean setParent(CommandDescription parent) { - // Make sure the parent is different - if (this.parent == parent) - return true; - - // Set the parent - this.parent = parent; - - // Make sure the parent isn't null - if (parent == null) - return true; - - // Add this description as a child to the parent - return parent.addChild(this); - } - - /** - * Check whether the plugin description has a parent command. - * - * @return True if the description has a parent command, false otherwise. - */ - public boolean hasParent() { - return this.parent != null; - } - - /** - * Get all command children. + * Return all command children. * * @return Command children. */ public List getChildren() { - return this.children; + return children; } /** - * Add a child to the command description. - * - * @param commandDescription The child to add. - * - * @return True on success, false on failure. - */ - public boolean addChild(CommandDescription commandDescription) { - // Make sure the description is valid - if (commandDescription == null) - return false; - - // Make sure the child doesn't exist already - if (isChild(commandDescription)) - return true; - - // The command description to add as a child - if (!this.children.add(commandDescription)) - return false; - - // Set this description as parent on the child - return commandDescription.setParent(this); - } - - /** - * Check whether this command has any child labels. - * - * @return True if this command has any child labels. - */ - public boolean hasChildren() { - return (this.children.size() != 0); - } - - /** - * Check if this command description has a specific child. - * - * @param commandDescription The command description to check for. - * - * @return True if this command description has the specific child, false otherwise. - */ - public boolean isChild(CommandDescription commandDescription) { - // Make sure the description is valid - if (commandDescription == null) - return false; - - // Check whether this child exists, return the result - return this.children.contains(commandDescription); - } - - /** - * Add an argument. - * - * @param argument The argument to add. - * - * @return True if succeed, false if failed. - */ - public boolean addArgument(CommandArgumentDescription argument) { - // Make sure the argument is valid - if (argument == null) - return false; - - // Add the argument, return the result - return this.arguments.add(argument); - } - - /** - * Get all command arguments. + * Return all arguments the command takes. * * @return Command arguments. */ public List getArguments() { - return this.arguments; + return arguments; } /** - * Check whether this command has any arguments. - * - * @return True if this command has any arguments. - */ - public boolean hasArguments() { - return !getArguments().isEmpty(); - } - - /** - * Get the command description. + * Return a short description of the command. * * @return Command description. */ @@ -424,119 +185,28 @@ public class CommandDescription { } /** - * Get the command detailed description. + * Return a detailed description of the command. * - * @return Command detailed description. + * @return Detailed description. */ public String getDetailedDescription() { return detailedDescription; } /** - * Find the best suitable command for a query reference. + * Return the permissions required to execute the command. * - * @param queryReference The query reference to find a command for. - * - * @return The command found, or null. - */ - public FoundCommandResult findCommand(final CommandParts queryReference) { - // Make sure the command reference is valid - if (queryReference.getCount() <= 0) - return null; - - // Check whether this description is for the last element in the command reference, if so return the current command - if (queryReference.getCount() <= getParentCount() + 1) { - return new FoundCommandResult( - this, - getCommandReference(queryReference), - new CommandParts(new ArrayList()), - queryReference); - } - - // Get the new command reference and arguments - CommandParts newReference = new CommandParts(CollectionUtils.getRange(queryReference.getList(), 0, getParentCount() + 1)); - CommandParts newArguments = new CommandParts(CollectionUtils.getRange(queryReference.getList(), getParentCount() + 1)); - - // Handle the child's, if this command has any - if (getChildren().size() > 0) { - // Get a new instance of the child's list, and sort them by their difference in comparison to the query reference - List commandChildren = new ArrayList<>(getChildren()); - Collections.sort(commandChildren, new Comparator() { - @Override - public int compare(CommandDescription o1, CommandDescription o2) { - return Double.compare( - o1.getCommandDifference(queryReference), - o2.getCommandDifference(queryReference)); - } - }); - - // Get the difference of the first child in the list - double firstChildDifference = commandChildren.get(0).getCommandDifference(queryReference, true); - - // Check if the reference perfectly suits the arguments of the current command if it doesn't perfectly suits a child command - if (firstChildDifference > 0.0) - if (getSuitableArgumentsDifference(queryReference) == 0) - return new FoundCommandResult(this, newReference, newArguments, queryReference); - - // Loop through each child - for (CommandDescription child : commandChildren) { - // Get the best suitable command - FoundCommandResult result = child.findCommand(queryReference); - if (result != null) - return result; - } - } - - // Check if the remaining command reference elements fit the arguments for this command - if (getSuitableArgumentsDifference(queryReference) >= 0) - return new FoundCommandResult(this, newReference, newArguments, queryReference); - - // No command found, return null - return null; - } - - /** - * Check if the remaining command reference elements are suitable with arguments of the current command description, - * and get the difference in argument count. - * - * @param commandReference The command reference. - * - * @return The difference in argument count between the reference and the actual command. - */ - public int getSuitableArgumentsDifference(CommandParts commandReference) { - // Make sure the command reference is valid - if (commandReference.getCount() <= 0) { - return -1; - } - - // Get the remaining command reference element count - int remainingElementCount = commandReference.getCount() - getParentCount() - 1; - - // Check if there are too few arguments - int minArguments = CommandUtils.getMinNumberOfArguments(this); - if (minArguments > remainingElementCount) { - return Math.abs(minArguments - remainingElementCount); - } - - // Check if there are too many arguments - int maxArguments = CommandUtils.getMaxNumberOfArguments(this); - if (maxArguments >= 0 && maxArguments < remainingElementCount) { - return Math.abs(remainingElementCount - maxArguments); - } - - // The argument count is the same - return 0; - } - - /** - * Get the command permissions. Return null if the command doesn't require any permission. - * - * @return The command permissions. + * @return The command permissions, or null if none are required to execute the command. */ public CommandPermissions getCommandPermissions() { - return this.permissions; + return permissions; } + /** + * Return a builder instance to create a new command description. + * + * @return The builder + */ public static CommandBuilder builder() { return new CommandBuilder(); } @@ -554,21 +224,20 @@ public class CommandDescription { private CommandPermissions permissions; /** - * Build a CommandDescription from the builder or throw an exception if mandatory - * fields have not been set. + * Build a CommandDescription from the builder or throw an exception if a mandatory + * field has not been set. * * @return The generated CommandDescription object */ public CommandDescription build() { - return createInstance( - getOrThrow(labels, "labels"), - firstNonNull(description, ""), - firstNonNull(detailedDescription, ""), - getOrThrow(executableCommand, "executableCommand"), - firstNonNull(parent, null), - arguments, - firstNonNull(permissions, null) - ); + checkArgument(!CollectionUtils.isEmpty(labels), "Labels may not be empty"); + checkArgument(!StringUtils.isEmpty(description), "Description may not be empty"); + checkArgument(!StringUtils.isEmpty(detailedDescription), "Detailed description may not be empty"); + checkArgument(executableCommand != null, "Executable command must be set"); + // parents and permissions may be null; arguments may be empty + + return createInstance(labels, description, detailedDescription, executableCommand, + parent, arguments, permissions); } public CommandBuilder labels(List labels) { @@ -577,7 +246,7 @@ public class CommandDescription { } public CommandBuilder labels(String... labels) { - return labels(asMutableList(labels)); + return labels(asList(labels)); } public CommandBuilder description(String description) { @@ -606,7 +275,7 @@ public class CommandDescription { * * @param label The label of the argument (single word name of the argument) * @param description The description of the argument - * @param isOptional True if the argument is option, false if it is mandatory + * @param isOptional True if the argument is optional, false if it is mandatory * * @return The builder */ @@ -617,37 +286,9 @@ public class CommandDescription { public CommandBuilder permissions(DefaultPermission defaultPermission, PermissionNode... permissionNodes) { - this.permissions = new CommandPermissions(asMutableList(permissionNodes), defaultPermission); + this.permissions = new CommandPermissions(asList(permissionNodes), defaultPermission); return this; } - - @SafeVarargs - private static List asMutableList(T... items) { - return new ArrayList<>(Arrays.asList(items)); - } - - private static T firstNonNull(T first, T second) { - return first != null ? first : second; - } - - private static T getOrThrow(T element, String elementName) { - if (!isEmpty(element)) { - return element; - } - throw new RuntimeException("The element '" + elementName + "' may not be empty in CommandDescription"); - } - - private static boolean isEmpty(T element) { - if (element == null) { - return true; - } else if (element instanceof Collection) { - return ((Collection) element).isEmpty(); - } else if (element instanceof String) { - return StringUtils.isEmpty((String) element); - } - return false; - } - } } diff --git a/src/main/java/fr/xephi/authme/command/CommandHandler.java b/src/main/java/fr/xephi/authme/command/CommandHandler.java index 67a4fbe6..fad9a269 100644 --- a/src/main/java/fr/xephi/authme/command/CommandHandler.java +++ b/src/main/java/fr/xephi/authme/command/CommandHandler.java @@ -1,7 +1,9 @@ package fr.xephi.authme.command; import fr.xephi.authme.AuthMe; +import fr.xephi.authme.command.executable.HelpCommand; import fr.xephi.authme.command.help.HelpProvider; +import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.util.CollectionUtils; import fr.xephi.authme.util.StringUtils; import org.bukkit.ChatColor; @@ -11,86 +13,91 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; +import static fr.xephi.authme.command.FoundResultStatus.INCORRECT_ARGUMENTS; +import static fr.xephi.authme.command.FoundResultStatus.MISSING_BASE_COMMAND; +import static fr.xephi.authme.command.FoundResultStatus.UNKNOWN_LABEL; + /** * The AuthMe command handler, responsible for mapping incoming commands to the correct {@link CommandDescription} * or to display help messages for unknown invocations. */ public class CommandHandler { - /** - * The threshold for assuming an existing command. If the difference is below this value, we assume - * that the user meant the similar command and we will run it. - */ - private static final double ASSUME_COMMAND_THRESHOLD = 0.12; - /** * The threshold for suggesting a similar command. If the difference is below this value, we will * ask the player whether he meant the similar command. */ private static final double SUGGEST_COMMAND_THRESHOLD = 0.75; - private final Set commands; + /** + * The class of the help command, to which the base label should also be passed in the arguments. + */ + private static final Class HELP_COMMAND_CLASS = HelpCommand.class; + + private final Set baseCommands; + private final PermissionsManager permissionsManager; /** * Create a command handler. * - * @param commands The collection of available AuthMe commands + * @param baseCommands The collection of available AuthMe base commands */ - public CommandHandler(Set commands) { - this.commands = commands; + public CommandHandler(Set baseCommands, PermissionsManager permissionsManager) { + this.baseCommands = baseCommands; + this.permissionsManager = permissionsManager; } /** * Map a command that was invoked to the proper {@link CommandDescription} or return a useful error * message upon failure. * - * @param sender The command sender (Bukkit). + * @param sender The command sender. * @param bukkitCommandLabel The command label (Bukkit). * @param bukkitArgs The command arguments (Bukkit). * * @return True if the command was executed, false otherwise. */ public boolean processCommand(CommandSender sender, String bukkitCommandLabel, String[] bukkitArgs) { - List commandArgs = skipEmptyArguments(bukkitArgs); - // Add the Bukkit command label to the front so we get a list like [authme, register, pass, passConfirm] - commandArgs.add(0, bukkitCommandLabel); + // Add the Bukkit command label to the front so we get a list like [authme, register, bobby, mysecret] + List parts = skipEmptyArguments(bukkitArgs); + parts.add(0, bukkitCommandLabel); + FoundCommandResult result = mapPartsToCommand(parts); - // TODO: remove commandParts - CommandParts commandReference = new CommandParts(commandArgs); - - // Get a suitable command for this reference, and make sure it isn't null - FoundCommandResult result = findCommand(commandReference); - if (result == null) { - // TODO ljacqu 20151204: Log more information to the console (bukkitCommandLabel) - sender.sendMessage(ChatColor.DARK_RED + "Failed to parse " + AuthMe.getPluginName() + " command!"); - return false; + switch (result.getResultStatus()) { + case SUCCESS: + executeCommandIfAllowed(sender, result.getCommandDescription(), result.getArguments()); + break; + case MISSING_BASE_COMMAND: + sender.sendMessage(ChatColor.DARK_RED + "Failed to parse " + AuthMe.getPluginName() + " command!"); + return false; + case INCORRECT_ARGUMENTS: + sendImproperArgumentsMessage(sender, result); + break; + case UNKNOWN_LABEL: + sendUnknownCommandMessage(sender, result); + break; + default: + throw new IllegalStateException("Unknown result '" + result.getResultStatus() + "'"); } - - String baseCommand = commandArgs.get(0); - - // Make sure the difference between the command reference and the actual command isn't too big - final double commandDifference = result.getDifference(); - if (commandDifference <= ASSUME_COMMAND_THRESHOLD) { - - // Show a message when the command handler is assuming a command - if (commandDifference > 0) { - sendCommandAssumptionMessage(sender, result, commandReference); - } - - if (!result.hasPermission(sender)) { - sender.sendMessage(ChatColor.DARK_RED + "You don't have permission to use this command!"); - } else if (!result.hasProperArguments()) { - sendImproperArgumentsMessage(sender, result, commandReference, baseCommand); - } else { - return result.executeCommand(sender); - } - } else { - sendUnknownCommandMessage(sender, commandDifference, result, baseCommand); - } return true; } + /** + * Check a command's permissions and execute it with the given arguments if the check succeeds. + * + * @param sender The command sender + * @param command The command to process + * @param arguments The arguments to pass to the command + */ + private void executeCommandIfAllowed(CommandSender sender, CommandDescription command, List arguments) { + if (permissionsManager.hasPermission(sender, command)) { + command.getExecutableCommand().executeCommand(sender, arguments); + } else { + sendPermissionDeniedError(sender); + } + } + /** * Skip all entries of the given array that are simply whitespace. * @@ -98,7 +105,7 @@ public class CommandHandler { * @return List of the items that are not empty */ private static List skipEmptyArguments(String[] args) { - List cleanArguments = new ArrayList<>(args.length); + List cleanArguments = new ArrayList<>(); for (String argument : args) { if (!StringUtils.isEmpty(argument)) { cleanArguments.add(argument); @@ -107,131 +114,181 @@ public class CommandHandler { return cleanArguments; } - - private static CommandDescription mapToBase(String commandLabel) { - for (CommandDescription command : CommandInitializer.getBaseCommands()) { - if (command.getLabels().contains(commandLabel)) { - return command; - } - } - return null; - } - - /** - * Find the best suitable command for the specified reference. - * - * @param queryReference The query reference to find a command for. - * - * @return The command found, or null. - */ - public FoundCommandResult findCommand(CommandParts queryReference) { - // Make sure the command reference is valid - if (queryReference.getCount() <= 0) - return null; - - for (CommandDescription commandDescription : commands) { - // Check whether there's a command description available for the - // current command - if (!commandDescription.isSuitableLabel(queryReference)) - continue; - - // Find the command reference, return the result - return commandDescription.findCommand(queryReference); - } - - // No applicable command description found, return false - return null; - } - - /** - * Find the best suitable command for the specified reference. - * - * @param commandParts The query reference to find a command for. - * - * @return The command found, or null. - */ - private CommandDescription findCommand(List commandParts) { - // Make sure the command reference is valid - if (commandParts.isEmpty()) { - return null; - } - - // TODO ljacqu 20151129: Since we only use .contains() on the CommandDescription#labels after init, change - // the type to set for faster lookup - Iterable commandsToScan = CommandInitializer.getBaseCommands(); - CommandDescription result = null; - for (String label : commandParts) { - result = findLabel(label, commandsToScan); - if (result == null) { - return null; - } - commandsToScan = result.getChildren(); - } - return result; - } - - private static CommandDescription findLabel(String label, Iterable commands) { - if (commands == null) { - return null; - } - for (CommandDescription command : commands) { - if (command.getLabels().contains(label)) { // TODO ljacqu should be case-insensitive - return command; - } - } - return null; - } - /** * Show an "unknown command" to the user and suggests an existing command if its similarity is within * the defined threshold. * * @param sender The command sender - * @param commandDifference The difference between the invoked command and the existing one * @param result The command that was found during the mapping process - * @param baseCommand The base command (TODO: This is probably already in FoundCommandResult) */ - private static void sendUnknownCommandMessage(CommandSender sender, double commandDifference, - FoundCommandResult result, String baseCommand) { - CommandParts commandReference = result.getCommandReference(); + private static void sendUnknownCommandMessage(CommandSender sender, FoundCommandResult result) { sender.sendMessage(ChatColor.DARK_RED + "Unknown command!"); - // Show a command suggestion if available and the difference isn't too big - if (commandDifference < SUGGEST_COMMAND_THRESHOLD && result.getCommandDescription() != null) { - sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD + "/" - + result.getCommandDescription().getCommandReference(commandReference) + ChatColor.YELLOW + "?"); + if (result.getDifference() <= SUGGEST_COMMAND_THRESHOLD && result.getCommandDescription() != null) { + sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD + + CommandUtils.constructCommandPath(result.getCommandDescription()) + ChatColor.YELLOW + "?"); } - sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + baseCommand + " help" - + ChatColor.YELLOW + " to view help."); + sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + result.getLabels().get(0) + + " help" + ChatColor.YELLOW + " to view help."); } - private static void sendImproperArgumentsMessage(CommandSender sender, FoundCommandResult result, - CommandParts commandReference, String baseCommand) { - // Get the command and the suggested command reference - List suggestedCommandReference = - result.getCommandDescription().getCommandReference(commandReference).getList(); - List helpCommandReference = CollectionUtils.getRange(suggestedCommandReference, 1); - - // Show the invalid arguments warning - sender.sendMessage(ChatColor.DARK_RED + "Incorrect command arguments!"); + private void sendImproperArgumentsMessage(CommandSender sender, FoundCommandResult result) { + CommandDescription command = result.getCommandDescription(); + if (!permissionsManager.hasPermission(sender, command)) { + sendPermissionDeniedError(sender); + return; + } // Show the command argument help - HelpProvider.showHelp(sender, commandReference, new CommandParts(suggestedCommandReference), - true, false, true, false, false, false); + sender.sendMessage(ChatColor.DARK_RED + "Incorrect command arguments!"); + List lines = HelpProvider.printHelp(result, HelpProvider.SHOW_ARGUMENTS); + for (String line : lines) { + sender.sendMessage(line); + } - // Show the command to use for detailed help - sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/" + baseCommand - + " help " + CommandUtils.labelsToString(helpCommandReference)); + List labels = result.getLabels(); + String childLabel = labels.size() >= 2 ? labels.get(1) : ""; + sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + + "/" + labels.get(0) + " help " + childLabel); } - private static void sendCommandAssumptionMessage(CommandSender sender, FoundCommandResult result, - CommandParts commandReference) { - List assumedCommandParts = - result.getCommandDescription().getCommandReference(commandReference).getList(); - - sender.sendMessage(ChatColor.DARK_RED + "Unknown command, assuming " + ChatColor.GOLD + "/" - + CommandUtils.labelsToString(assumedCommandParts) + ChatColor.DARK_RED + "!"); + // TODO ljacqu 20151212: Remove me once I am a MessageKey + private void sendPermissionDeniedError(CommandSender sender) { + sender.sendMessage(ChatColor.DARK_RED + "You don't have permission to use this command!"); } + + /** + * Map incoming command parts to a command. This processes all parts and distinguishes the labels from arguments. + * + * @param parts The parts to map to commands and arguments + * @return The generated {@link FoundCommandResult} + */ + public FoundCommandResult mapPartsToCommand(final List parts) { + if (CollectionUtils.isEmpty(parts)) { + return new FoundCommandResult(null, parts, null, 0.0, MISSING_BASE_COMMAND); + } + + CommandDescription base = getBaseCommand(parts.get(0)); + if (base == null) { + return new FoundCommandResult(null, parts, null, 0.0, MISSING_BASE_COMMAND); + } + + // Prefer labels: /register help goes to "Help command", not "Register command" with argument 'help' + List remainingParts = parts.subList(1, parts.size()); + CommandDescription childCommand = getSuitableChild(base, remainingParts); + if (childCommand != null) { + FoundCommandResult result = new FoundCommandResult( + childCommand, parts.subList(0, 2), parts.subList(2, parts.size())); + return transformResultForHelp(result); + } else if (hasSuitableArgumentCount(base, remainingParts.size())) { + return new FoundCommandResult(base, parts.subList(0, 1), parts.subList(1, parts.size())); + } + + return getCommandWithSmallestDifference(base, parts); + } + + private FoundCommandResult getCommandWithSmallestDifference(CommandDescription base, List parts) { + // Return the base command with incorrect arg count error if we only have one part + if (parts.size() <= 1) { + return new FoundCommandResult(base, parts, new ArrayList(), 0.0, INCORRECT_ARGUMENTS); + } + + final String childLabel = parts.get(1); + double minDifference = Double.POSITIVE_INFINITY; + CommandDescription closestCommand = null; + + for (CommandDescription child : base.getChildren()) { + double difference = getLabelDifference(child, childLabel); + if (difference < minDifference) { + minDifference = difference; + closestCommand = child; + } + } + + // base command may have no children, in which case we return the base command with incorrect arguments error + if (closestCommand == null) { + return new FoundCommandResult( + base, parts.subList(0, 1), parts.subList(1, parts.size()), 0.0, INCORRECT_ARGUMENTS); + } + + FoundResultStatus status = (minDifference == 0.0) ? INCORRECT_ARGUMENTS : UNKNOWN_LABEL; + final int partsSize = parts.size(); + List labels = parts.subList(0, Math.min(closestCommand.getLabelCount(), partsSize)); + List arguments = (labels.size() == partsSize) + ? new ArrayList() + : parts.subList(labels.size(), partsSize); + + return new FoundCommandResult(closestCommand, labels, arguments, minDifference, status); + } + + private CommandDescription getBaseCommand(String label) { + String baseLabel = label.toLowerCase(); + for (CommandDescription command : baseCommands) { + if (command.hasLabel(baseLabel)) { + return command; + } + } + return null; + } + + /** + * Return a child from a base command if the label and the argument count match. + * + * @param baseCommand The base command whose children should be checked + * @param parts The command parts received from the invocation; the first item is the potential label and any + * other items are command arguments. The first initial part that led to the base command should not + * be present. + * + * @return A command if there was a complete match (including proper argument count), null otherwise + */ + private CommandDescription getSuitableChild(CommandDescription baseCommand, List parts) { + if (CollectionUtils.isEmpty(parts)) { + return null; + } + + final String label = parts.get(0).toLowerCase(); + final int argumentCount = parts.size() - 1; + + for (CommandDescription child : baseCommand.getChildren()) { + if (child.hasLabel(label) && hasSuitableArgumentCount(child, argumentCount)) { + return child; + } + } + return null; + } + + private static FoundCommandResult transformResultForHelp(FoundCommandResult result) { + if (result.getCommandDescription() != null + && HELP_COMMAND_CLASS.isAssignableFrom(result.getCommandDescription().getExecutableCommand().getClass())) { + // For "/authme help register" we have labels = [authme, help] and arguments = [register] + // But for the help command we want labels = [authme, help] and arguments = [authme, register], + // so we can use the arguments as the labels to the command to show help for + List arguments = new ArrayList<>(result.getArguments()); + arguments.add(0, result.getLabels().get(0)); + return new FoundCommandResult(result.getCommandDescription(), result.getLabels(), + arguments, result.getDifference(), result.getResultStatus()); + } + return result; + } + + private static boolean hasSuitableArgumentCount(CommandDescription command, int argumentCount) { + int minArgs = CommandUtils.getMinNumberOfArguments(command); + int maxArgs = CommandUtils.getMaxNumberOfArguments(command); + + return argumentCount >= minArgs && argumentCount <= maxArgs; + } + + private static double getLabelDifference(CommandDescription command, String givenLabel) { + double minDifference = Double.POSITIVE_INFINITY; + for (String commandLabel : command.getLabels()) { + double difference = StringUtils.getDifference(commandLabel, givenLabel); + if (difference < minDifference) { + minDifference = difference; + } + } + return minDifference; + } + } diff --git a/src/main/java/fr/xephi/authme/command/CommandInitializer.java b/src/main/java/fr/xephi/authme/command/CommandInitializer.java index 9381499c..82f45fc2 100644 --- a/src/main/java/fr/xephi/authme/command/CommandInitializer.java +++ b/src/main/java/fr/xephi/authme/command/CommandInitializer.java @@ -1,5 +1,6 @@ package fr.xephi.authme.command; +import com.google.common.collect.ImmutableSet; import fr.xephi.authme.command.executable.HelpCommand; import fr.xephi.authme.command.executable.authme.AccountsCommand; import fr.xephi.authme.command.executable.authme.AuthMeCommand; @@ -33,9 +34,10 @@ import fr.xephi.authme.command.executable.register.RegisterCommand; import fr.xephi.authme.command.executable.unregister.UnregisterCommand; import fr.xephi.authme.permission.AdminPermission; import fr.xephi.authme.permission.PlayerPermission; -import fr.xephi.authme.util.Wrapper; -import java.util.*; +import java.util.Arrays; +import java.util.List; +import java.util.Set; import static fr.xephi.authme.permission.DefaultPermission.ALLOWED; import static fr.xephi.authme.permission.DefaultPermission.OP_ONLY; @@ -53,7 +55,6 @@ public final class CommandInitializer { public static Set getBaseCommands() { if (baseCommands == null) { - Wrapper.getInstance().getLogger().info("Initializing AuthMe commands"); initializeCommands(); } return baseCommands; @@ -156,179 +157,179 @@ public final class CommandInitializer { .labels("getemail", "getmail", "email", "mail") .description("Display player's email") .detailedDescription("Display the email address of the specified player if set.") - .permissions(OP_ONLY, AdminPermission.GET_EMAIL) .withArgument("player", "Player name", true) + .permissions(OP_ONLY, AdminPermission.GET_EMAIL) .executableCommand(new GetEmailCommand()) .build(); // Register the setemail command CommandDescription.builder() - .executableCommand(new SetEmailCommand()) .parent(AUTHME_BASE) .labels("chgemail", "chgmail", "setemail", "setmail") .description("Change player's email") .detailedDescription("Change the email address of the specified player.") - .permissions(OP_ONLY, AdminPermission.CHANGE_EMAIL) .withArgument("player", "Player name", false) .withArgument("email", "Player email", false) + .permissions(OP_ONLY, AdminPermission.CHANGE_EMAIL) + .executableCommand(new SetEmailCommand()) .build(); // Register the getip command CommandDescription.builder() - .executableCommand(new GetIpCommand()) - .parent(AUTHME_BASE) - .labels("getip", "ip") - .description("Get player's IP") - .detailedDescription("Get the IP address of the specified online player.") - .permissions(OP_ONLY, AdminPermission.GET_IP) - .withArgument("player", "Player Name", false) - .build(); + .parent(AUTHME_BASE) + .labels("getip", "ip") + .description("Get player's IP") + .detailedDescription("Get the IP address of the specified online player.") + .withArgument("player", "Player Name", false) + .permissions(OP_ONLY, AdminPermission.GET_IP) + .executableCommand(new GetIpCommand()) + .build(); // Register the spawn command CommandDescription.builder() - .executableCommand(new SpawnCommand()) - .parent(AUTHME_BASE) - .labels("spawn", "home") - .description("Teleport to spawn") - .detailedDescription("Teleport to the spawn.") - .permissions(OP_ONLY, AdminPermission.SPAWN) - .withArgument("player", "Player Name", false) - .build(); + .parent(AUTHME_BASE) + .labels("spawn", "home") + .description("Teleport to spawn") + .detailedDescription("Teleport to the spawn.") + .withArgument("player", "Player Name", false) + .permissions(OP_ONLY, AdminPermission.SPAWN) + .executableCommand(new SpawnCommand()) + .build(); // Register the setspawn command CommandDescription.builder() - .executableCommand(new SetSpawnCommand()) - .parent(AUTHME_BASE) - .labels("setspawn", "chgspawn") - .description("Change the spawn") - .detailedDescription("Change the player's spawn to your current position.") - .permissions(OP_ONLY, AdminPermission.SET_SPAWN) - .build(); + .parent(AUTHME_BASE) + .labels("setspawn", "chgspawn") + .description("Change the spawn") + .detailedDescription("Change the player's spawn to your current position.") + .permissions(OP_ONLY, AdminPermission.SET_SPAWN) + .executableCommand(new SetSpawnCommand()) + .build(); // Register the firstspawn command CommandDescription.builder() - .executableCommand(new FirstSpawnCommand()) - .parent(AUTHME_BASE) - .labels("firstspawn", "firsthome") - .description("Teleport to first spawn") - .detailedDescription("Teleport to the first spawn.") - .permissions(OP_ONLY, AdminPermission.FIRST_SPAWN) - .build(); + .parent(AUTHME_BASE) + .labels("firstspawn", "firsthome") + .description("Teleport to first spawn") + .detailedDescription("Teleport to the first spawn.") + .permissions(OP_ONLY, AdminPermission.FIRST_SPAWN) + .executableCommand(new FirstSpawnCommand()) + .build(); // Register the setfirstspawn command CommandDescription.builder() - .executableCommand(new SetFirstSpawnCommand()) - .parent(AUTHME_BASE) - .labels("setfirstspawn", "chgfirstspawn") - .description("Change the first spawn") - .detailedDescription("Change the first player's spawn to your current position.") - .permissions(OP_ONLY, AdminPermission.SET_FIRST_SPAWN) - .build(); + .parent(AUTHME_BASE) + .labels("setfirstspawn", "chgfirstspawn") + .description("Change the first spawn") + .detailedDescription("Change the first player's spawn to your current position.") + .permissions(OP_ONLY, AdminPermission.SET_FIRST_SPAWN) + .executableCommand(new SetFirstSpawnCommand()) + .build(); // Register the purge command CommandDescription.builder() - .executableCommand(new PurgeCommand()) - .parent(AUTHME_BASE) - .labels("purge", "delete") - .description("Purge old data") - .detailedDescription("Purge old AuthMeReloaded data longer than the specified amount of days ago.") - .permissions(OP_ONLY, AdminPermission.PURGE) - .withArgument("days", "Number of days", false) - .build(); + .parent(AUTHME_BASE) + .labels("purge", "delete") + .description("Purge old data") + .detailedDescription("Purge old AuthMeReloaded data longer than the specified amount of days ago.") + .withArgument("days", "Number of days", false) + .permissions(OP_ONLY, AdminPermission.PURGE) + .executableCommand(new PurgeCommand()) + .build(); // Register the purgelastposition command CommandDescription.builder() - .executableCommand(new PurgeLastPositionCommand()) - .parent(AUTHME_BASE) - .labels("resetpos", "purgelastposition", "purgelastpos", "resetposition", - "resetlastposition", "resetlastpos") - .description("Purge player's last position") - .detailedDescription("Purge the last know position of the specified player.") - .permissions(OP_ONLY, AdminPermission.PURGE_LAST_POSITION) - .withArgument("player", "Player name", false) - .build(); + .parent(AUTHME_BASE) + .labels("resetpos", "purgelastposition", "purgelastpos", "resetposition", + "resetlastposition", "resetlastpos") + .description("Purge player's last position") + .detailedDescription("Purge the last know position of the specified player.") + .withArgument("player", "Player name", false) + .permissions(OP_ONLY, AdminPermission.PURGE_LAST_POSITION) + .executableCommand(new PurgeLastPositionCommand()) + .build(); // Register the purgebannedplayers command CommandDescription.builder() - .executableCommand(new PurgeBannedPlayersCommand()) - .parent(AUTHME_BASE) - .labels("purgebannedplayers", "purgebannedplayer", "deletebannedplayers", "deletebannedplayer") - .description("Purge banned players data") - .detailedDescription("Purge all AuthMeReloaded data for banned players.") - .permissions(OP_ONLY, AdminPermission.PURGE_BANNED_PLAYERS) - .build(); + .parent(AUTHME_BASE) + .labels("purgebannedplayers", "purgebannedplayer", "deletebannedplayers", "deletebannedplayer") + .description("Purge banned players data") + .detailedDescription("Purge all AuthMeReloaded data for banned players.") + .permissions(OP_ONLY, AdminPermission.PURGE_BANNED_PLAYERS) + .executableCommand(new PurgeBannedPlayersCommand()) + .build(); // Register the switchantibot command CommandDescription.builder() - .executableCommand(new SwitchAntiBotCommand()) - .parent(AUTHME_BASE) - .labels("switchantibot", "toggleantibot", "antibot") - .description("Switch AntiBot mode") - .detailedDescription("Switch or toggle the AntiBot mode to the specified state.") - .permissions(OP_ONLY, AdminPermission.SWITCH_ANTIBOT) - .withArgument("mode", "ON / OFF", true) - .build(); + .parent(AUTHME_BASE) + .labels("switchantibot", "toggleantibot", "antibot") + .description("Switch AntiBot mode") + .detailedDescription("Switch or toggle the AntiBot mode to the specified state.") + .withArgument("mode", "ON / OFF", true) + .permissions(OP_ONLY, AdminPermission.SWITCH_ANTIBOT) + .executableCommand(new SwitchAntiBotCommand()) + .build(); // Register the reload command CommandDescription.builder() - .executableCommand(new ReloadCommand()) - .parent(AUTHME_BASE) - .labels("reload", "rld") - .description("Reload plugin") - .detailedDescription("Reload the AuthMeReloaded plugin.") - .permissions(OP_ONLY, AdminPermission.RELOAD) - .build(); + .parent(AUTHME_BASE) + .labels("reload", "rld") + .description("Reload plugin") + .detailedDescription("Reload the AuthMeReloaded plugin.") + .permissions(OP_ONLY, AdminPermission.RELOAD) + .executableCommand(new ReloadCommand()) + .build(); // Register the version command CommandDescription.builder() .parent(AUTHME_BASE) .labels("version", "ver", "v", "about", "info") .description("Version info") - .detailedDescription("Show detailed information about the installed AuthMeReloaded version, and shows the " - + "developers, contributors, license and other information.") + .detailedDescription("Show detailed information about the installed AuthMeReloaded version, the " + + "developers, contributors, and license.") .executableCommand(new VersionCommand()) .build(); // Register the base login command final CommandDescription LOGIN_BASE = CommandDescription.builder() - .executableCommand(new LoginCommand()) + .parent(null) .labels("login", "l") .description("Login command") .detailedDescription("Command to log in using AuthMeReloaded.") - .parent(null) - .permissions(ALLOWED, PlayerPermission.LOGIN) .withArgument("password", "Login password", false) + .permissions(ALLOWED, PlayerPermission.LOGIN) + .executableCommand(new LoginCommand()) .build(); // Register the help command CommandDescription.builder() - .executableCommand(helpCommandExecutable) - .parent(LOGIN_BASE) - .labels(helpCommandLabels) - .description("View Help") - .detailedDescription("View detailed help pages about AuthMeReloaded login commands.") - .withArgument("query", "The command or query to view help for.", true) - .build(); + .parent(LOGIN_BASE) + .labels(helpCommandLabels) + .description("View Help") + .detailedDescription("View detailed help pages about AuthMeReloaded login commands.") + .withArgument("query", "The command or query to view help for.", true) + .executableCommand(helpCommandExecutable) + .build(); // Register the base logout command CommandDescription LOGOUT_BASE = CommandDescription.builder() - .executableCommand(new LogoutCommand()) - .parent(null) - .labels("logout") - .description("Logout command") - .detailedDescription("Command to logout using AuthMeReloaded.") - .permissions(ALLOWED, PlayerPermission.LOGOUT) - .build(); + .parent(null) + .labels("logout") + .description("Logout command") + .detailedDescription("Command to logout using AuthMeReloaded.") + .permissions(ALLOWED, PlayerPermission.LOGOUT) + .executableCommand(new LogoutCommand()) + .build(); // Register the help command CommandDescription.builder() - .executableCommand(helpCommandExecutable) - .parent(LOGOUT_BASE) - .labels(helpCommandLabels) - .description("View help") - .detailedDescription("View detailed help pages about AuthMeReloaded logout commands.") - .withArgument("query", "The command or query to view help for.", true) - .build(); + .parent(LOGOUT_BASE) + .labels(helpCommandLabels) + .description("View help") + .detailedDescription("View detailed help pages about AuthMeReloaded logout commands.") + .withArgument("query", "The command or query to view help for.", true) + .executableCommand(helpCommandExecutable) + .build(); // Register the base register command final CommandDescription REGISTER_BASE = CommandDescription.builder() @@ -344,158 +345,157 @@ public final class CommandInitializer { // Register the help command CommandDescription.builder() - .executableCommand(helpCommandExecutable) - .parent(REGISTER_BASE) - .labels(helpCommandLabels) - .description("View help") - .detailedDescription("View detailed help pages about AuthMeReloaded register commands.") - .withArgument("query", "The command or query to view help for.", true) - .build(); + .parent(REGISTER_BASE) + .labels(helpCommandLabels) + .description("View help") + .detailedDescription("View detailed help pages about AuthMeReloaded register commands.") + .withArgument("query", "The command or query to view help for.", true) + .executableCommand(helpCommandExecutable) + .build(); // Register the base unregister command CommandDescription UNREGISTER_BASE = CommandDescription.builder() - .executableCommand(new UnregisterCommand()) - .parent(null) - .labels("unreg", "unregister") - .description("Unregistration Command") - .detailedDescription("Command to unregister using AuthMeReloaded.") - .permissions(ALLOWED, PlayerPermission.UNREGISTER) - .withArgument("password", "Password", false) - .build(); + .parent(null) + .labels("unreg", "unregister") + .description("Unregistration Command") + .detailedDescription("Command to unregister using AuthMeReloaded.") + .withArgument("password", "Password", false) + .permissions(ALLOWED, PlayerPermission.UNREGISTER) + .executableCommand(new UnregisterCommand()) + .build(); // Register the help command CommandDescription.builder() - .executableCommand(helpCommandExecutable) - .parent(UNREGISTER_BASE) - .labels(helpCommandLabels) - .description("View help") - .detailedDescription("View detailed help pages about AuthMeReloaded unregister commands.") - .withArgument("query", "The command or query to view help for.", true) - .build(); + .parent(UNREGISTER_BASE) + .labels(helpCommandLabels) + .description("View help") + .detailedDescription("View detailed help pages about AuthMeReloaded unregister commands.") + .withArgument("query", "The command or query to view help for.", true) + .executableCommand(helpCommandExecutable) + .build(); // Register the base changepassword command final CommandDescription CHANGE_PASSWORD_BASE = CommandDescription.builder() - .executableCommand(new ChangePasswordCommand()) - .parent(null) - .labels("changepassword", "changepass", "cp") - .description("Change password Command") - .detailedDescription("Command to change your password using AuthMeReloaded.") - .permissions(ALLOWED, PlayerPermission.CHANGE_PASSWORD) - .withArgument("password", "Password", false) - .withArgument("verifyPassword", "Verify password.", false) - .build(); + .parent(null) + .labels("changepassword", "changepass", "cp") + .description("Change password Command") + .detailedDescription("Command to change your password using AuthMeReloaded.") + .withArgument("password", "Password", false) + .withArgument("verifyPassword", "Verify password.", false) + .permissions(ALLOWED, PlayerPermission.CHANGE_PASSWORD) + .executableCommand(new ChangePasswordCommand()) + .build(); // Register the help command CommandDescription.builder() - .executableCommand(helpCommandExecutable) - .parent(CHANGE_PASSWORD_BASE) - .labels(helpCommandLabels) - .description("View help") - .detailedDescription("View detailed help pages about AuthMeReloaded changepassword commands.") - .withArgument("query", "The command or query to view help for.", true) - .build(); + .parent(CHANGE_PASSWORD_BASE) + .labels(helpCommandLabels) + .description("View help") + .detailedDescription("View detailed help pages about AuthMeReloaded changepassword commands.") + .withArgument("query", "The command or query to view help for.", true) + .executableCommand(helpCommandExecutable) + .build(); // Register the base Email command CommandDescription EMAIL_BASE = CommandDescription.builder() - .executableCommand(helpCommandExecutable) - .parent(null) - .labels("email", "mail") - .description("Email command") - .detailedDescription("The AuthMeReloaded Email command base.") - .build(); + .parent(null) + .labels("email", "mail") + .description("Email command") + .detailedDescription("The AuthMeReloaded Email command base.") + .executableCommand(helpCommandExecutable) + .build(); // Register the help command CommandDescription.builder() - .executableCommand(helpCommandExecutable) - .parent(EMAIL_BASE) - .labels(helpCommandLabels) - .description("View help") - .detailedDescription("View detailed help pages about AuthMeReloaded email commands.") - .withArgument("query", "The command or query to view help for.", true) - .build(); + .parent(EMAIL_BASE) + .labels(helpCommandLabels) + .description("View help") + .detailedDescription("View detailed help pages about AuthMeReloaded email commands.") + .withArgument("query", "The command or query to view help for.", true) + .executableCommand(helpCommandExecutable) + .build(); // Register the add command CommandDescription.builder() - .executableCommand(new AddEmailCommand()) - .parent(EMAIL_BASE) - .labels("add", "addemail", "addmail") - .description("Add Email") - .detailedDescription("Add a new email address to your account.") - .permissions(ALLOWED, PlayerPermission.ADD_EMAIL) - .withArgument("email", "Email address", false) - .withArgument("verifyEmail", "Email address verification", false) - .build(); + .parent(EMAIL_BASE) + .labels("add", "addemail", "addmail") + .description("Add Email") + .detailedDescription("Add a new email address to your account.") + .withArgument("email", "Email address", false) + .withArgument("verifyEmail", "Email address verification", false) + .permissions(ALLOWED, PlayerPermission.ADD_EMAIL) + .executableCommand(new AddEmailCommand()) + .build(); // Register the change command CommandDescription.builder() - .executableCommand(new ChangeEmailCommand()) - .parent(EMAIL_BASE) - .labels("change", "changeemail", "changemail") - .description("Change Email") - .detailedDescription("Change an email address of your account.") - .permissions(ALLOWED, PlayerPermission.CHANGE_EMAIL) - .withArgument("oldEmail", "Old email address", false) - .withArgument("newEmail", "New email address", false) - .build(); - + .parent(EMAIL_BASE) + .labels("change", "changeemail", "changemail") + .description("Change Email") + .detailedDescription("Change an email address of your account.") + .withArgument("oldEmail", "Old email address", false) + .withArgument("newEmail", "New email address", false) + .permissions(ALLOWED, PlayerPermission.CHANGE_EMAIL) + .executableCommand(new ChangeEmailCommand()) + .build(); // Register the recover command CommandDescription.builder() - .executableCommand(new RecoverEmailCommand()) - .parent(EMAIL_BASE) - .labels("recover", "recovery", "recoveremail", "recovermail") - .description("Recover password using Email") - .detailedDescription("Recover your account using an Email address by sending a mail containing " + - "a new password.") - .permissions(ALLOWED, PlayerPermission.RECOVER_EMAIL) - .withArgument("email", "Email address", false) - .build(); + .parent(EMAIL_BASE) + .labels("recover", "recovery", "recoveremail", "recovermail") + .description("Recover password using Email") + .detailedDescription("Recover your account using an Email address by sending a mail containing " + + "a new password.") + .withArgument("email", "Email address", false) + .permissions(ALLOWED, PlayerPermission.RECOVER_EMAIL) + .executableCommand(new RecoverEmailCommand()) + .build(); // Register the base captcha command CommandDescription CAPTCHA_BASE = CommandDescription.builder() - .executableCommand(new CaptchaCommand()) - .parent(null) - .labels("captcha", "capt") - .description("Captcha Command") - .detailedDescription("Captcha command for AuthMeReloaded.") - .permissions(ALLOWED, PlayerPermission.CAPTCHA) - .withArgument("captcha", "The Captcha", false) - .build(); + .parent(null) + .labels("captcha", "capt") + .description("Captcha Command") + .detailedDescription("Captcha command for AuthMeReloaded.") + .withArgument("captcha", "The Captcha", false) + .permissions(ALLOWED, PlayerPermission.CAPTCHA) + .executableCommand(new CaptchaCommand()) + .build(); // Register the help command CommandDescription.builder() - .executableCommand(helpCommandExecutable) - .parent(CAPTCHA_BASE) - .labels(helpCommandLabels) - .description("View help") - .detailedDescription("View detailed help pages about AuthMeReloaded captcha commands.") - .withArgument("query", "The command or query to view help for.", true) - .build(); + .parent(CAPTCHA_BASE) + .labels(helpCommandLabels) + .description("View help") + .detailedDescription("View detailed help pages about AuthMeReloaded captcha commands.") + .withArgument("query", "The command or query to view help for.", true) + .executableCommand(helpCommandExecutable) + .build(); // Register the base converter command CommandDescription CONVERTER_BASE = CommandDescription.builder() - .executableCommand(new ConverterCommand()) - .parent(null) - .labels("converter", "convert", "conv") - .description("Converter Command") - .detailedDescription("Converter command for AuthMeReloaded.") - .permissions(OP_ONLY, AdminPermission.CONVERTER) - .withArgument("job", "Conversion job: flattosql / flattosqlite /| xauth / crazylogin / rakamak / " + - "royalauth / vauth / sqltoflat", false) - .build(); + .parent(null) + .labels("converter", "convert", "conv") + .description("Converter Command") + .detailedDescription("Converter command for AuthMeReloaded.") + .withArgument("job", "Conversion job: flattosql / flattosqlite /| xauth / crazylogin / rakamak / " + + "royalauth / vauth / sqltoflat", false) + .permissions(OP_ONLY, AdminPermission.CONVERTER) + .executableCommand(new ConverterCommand()) + .build(); // Register the help command CommandDescription.builder() - .executableCommand(helpCommandExecutable) - .parent(CONVERTER_BASE) - .labels(helpCommandLabels) - .description("View help") - .detailedDescription("View detailed help pages about AuthMeReloaded converter commands.") - .withArgument("query", "The command or query to view help for.", true) - .build(); + .parent(CONVERTER_BASE) + .labels(helpCommandLabels) + .description("View help") + .detailedDescription("View detailed help pages about AuthMeReloaded converter commands.") + .withArgument("query", "The command or query to view help for.", true) + .executableCommand(helpCommandExecutable) + .build(); // Add the base commands to the commands array - baseCommands = new HashSet<>(Arrays.asList( + baseCommands = ImmutableSet.of( AUTHME_BASE, LOGIN_BASE, LOGOUT_BASE, @@ -504,6 +504,6 @@ public final class CommandInitializer { CHANGE_PASSWORD_BASE, EMAIL_BASE, CAPTCHA_BASE, - CONVERTER_BASE)); + CONVERTER_BASE); } } diff --git a/src/main/java/fr/xephi/authme/command/CommandParts.java b/src/main/java/fr/xephi/authme/command/CommandParts.java deleted file mode 100644 index eb6299db..00000000 --- a/src/main/java/fr/xephi/authme/command/CommandParts.java +++ /dev/null @@ -1,78 +0,0 @@ -package fr.xephi.authme.command; - -import fr.xephi.authme.util.StringUtils; - -import java.util.ArrayList; -import java.util.List; - -/** - */ -public class CommandParts { - - /** - * The list of parts for this command. - */ - private final List parts = new ArrayList<>(); - - /** - * Constructor. - * - * @param part The part to add. - */ - public CommandParts(String part) { - this.parts.add(part); - } - - /** - * Constructor. - * - * @param parts The list of parts. - */ - public CommandParts(List parts) { - this.parts.addAll(parts); - } - - /** - * Get the command parts. - * - * @return Command parts. - */ - public List getList() { - return this.parts; - } - - /** - * Get the number of parts. - * - * @return Part count. - */ - public int getCount() { - return this.parts.size(); - } - - /** - * Get a part by its index. - * - * @param i Part index. - * - * @return The part. - */ - public String get(int i) { - // Make sure the index is in-bound - if (i < 0 || i >= getCount()) - return null; - - // Get and return the argument - return this.parts.get(i); - } - - /** - * Convert the parts to a string. - * - * @return The part as a string. - */ - @Override - public String toString() { - return StringUtils.join(" ", this.parts); - } -} diff --git a/src/main/java/fr/xephi/authme/command/CommandPermissions.java b/src/main/java/fr/xephi/authme/command/CommandPermissions.java index 2c52f85a..0082b858 100644 --- a/src/main/java/fr/xephi/authme/command/CommandPermissions.java +++ b/src/main/java/fr/xephi/authme/command/CommandPermissions.java @@ -1,11 +1,7 @@ package fr.xephi.authme.command; -import fr.xephi.authme.AuthMe; import fr.xephi.authme.permission.DefaultPermission; -import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PermissionNode; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; import java.util.List; @@ -42,38 +38,6 @@ public class CommandPermissions { return this.permissionNodes; } - /** - * Check whether this command requires any permission to be executed. This is based on the getPermission() method. - * - * @param sender CommandSender - * - * @return True if this command requires any permission to be executed by a player. - */ - public boolean hasPermission(CommandSender sender) { - // Make sure any permission node is set - if (permissionNodes.isEmpty()) { - return true; - } - - PermissionsManager permissionsManager = AuthMe.getInstance().getPermissionsManager(); - final boolean defaultPermission = getDefaultPermissionCommandSender(sender); - - // Make sure the command sender is a player, if not use the default - if (!(sender instanceof Player)) { - return defaultPermission; - } - - // Get the player instance - Player player = (Player) sender; - - // Get the permissions manager, and make sure it's instance is valid - - if (permissionsManager == null) - return false; - - // Check whether the player has permission, return the result - return permissionsManager.hasPermission(player, this.permissionNodes, defaultPermission); - } /** * Get the default permission if the permission nodes couldn't be used. @@ -85,24 +49,4 @@ public class CommandPermissions { } - /** - * Get the default permission for a specified command sender. - * - * @param sender The command sender to get the default permission for. - * - * @return True if the command sender has permission by default, false otherwise. - */ - public boolean getDefaultPermissionCommandSender(CommandSender sender) { - switch (getDefaultPermission()) { - case ALLOWED: - return true; - - case OP_ONLY: - return sender.isOp(); - - case NOT_ALLOWED: - default: - return false; - } - } } diff --git a/src/main/java/fr/xephi/authme/command/CommandUtils.java b/src/main/java/fr/xephi/authme/command/CommandUtils.java index 11445999..905e8922 100644 --- a/src/main/java/fr/xephi/authme/command/CommandUtils.java +++ b/src/main/java/fr/xephi/authme/command/CommandUtils.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command; import com.google.common.collect.Lists; -import fr.xephi.authme.util.CollectionUtils; import fr.xephi.authme.util.StringUtils; import java.util.ArrayList; @@ -25,9 +24,10 @@ public final class CommandUtils { /** * Provide a textual representation of a list of labels to show it as a command. For example, a list containing - * the items ["authme", "register", "player"] it will return "authme register player". + * the items ["authme", "register", "player"] will return "authme register player". * * @param labels The labels to format + * * @return The space-separated labels */ public static String labelsToString(Iterable labels) { @@ -35,35 +35,22 @@ public final class CommandUtils { } public static String constructCommandPath(CommandDescription command) { - List labels = new ArrayList<>(); + StringBuilder sb = new StringBuilder(); + String prefix = "/"; + for (CommandDescription ancestor : constructParentList(command)) { + sb.append(prefix).append(ancestor.getLabels().get(0)); + prefix = " "; + } + return sb.toString(); + } + + public static List constructParentList(CommandDescription command) { + List commands = new ArrayList<>(); CommandDescription currentCommand = command; while (currentCommand != null) { - labels.add(currentCommand.getLabels().get(0)); + commands.add(currentCommand); currentCommand = currentCommand.getParent(); } - return "/" + labelsToString(Lists.reverse(labels)); + return Lists.reverse(commands); } - - public static double getDifference(List labels1, List labels2, boolean fullCompare) { - // Make sure the other reference is correct - if (labels1 == null || labels2 == null) { - return -1; - } - - // Get the range to use - int range = Math.min(labels1.size(), labels2.size()); - - // Get and the difference - if (fullCompare) { - return StringUtils.getDifference(CommandUtils.labelsToString(labels1), CommandUtils.labelsToString(labels2)); - } - return StringUtils.getDifference( - labelsToString(CollectionUtils.getRange(labels1, range - 1, 1)), - labelsToString(CollectionUtils.getRange(labels2, range - 1, 1))); - } - - - - - } diff --git a/src/main/java/fr/xephi/authme/command/ExecutableCommand.java b/src/main/java/fr/xephi/authme/command/ExecutableCommand.java index 78db5ecf..cffe25b7 100644 --- a/src/main/java/fr/xephi/authme/command/ExecutableCommand.java +++ b/src/main/java/fr/xephi/authme/command/ExecutableCommand.java @@ -2,19 +2,18 @@ package fr.xephi.authme.command; import org.bukkit.command.CommandSender; +import java.util.List; + /** * Base class for AuthMe commands that can be executed. */ public abstract class ExecutableCommand { /** - * Execute the command. + * Execute the command with the given arguments. * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. + * @param sender The command sender. + * @param arguments The arguments. */ - public abstract boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments); + public abstract void executeCommand(CommandSender sender, List arguments); } diff --git a/src/main/java/fr/xephi/authme/command/FoundCommandResult.java b/src/main/java/fr/xephi/authme/command/FoundCommandResult.java index 91551650..f9fcce7b 100644 --- a/src/main/java/fr/xephi/authme/command/FoundCommandResult.java +++ b/src/main/java/fr/xephi/authme/command/FoundCommandResult.java @@ -1,149 +1,88 @@ package fr.xephi.authme.command; -import org.bukkit.command.CommandSender; +import java.util.List; /** + * Result of a command mapping by {@link CommandHandler}. An object of this class represents a successful mapping + * as well as erroneous ones, as communicated with {@link FoundResultStatus}. + *

+ * Fields other than {@link FoundResultStatus} are available depending, among other factors, on the status: + *

    + *
  • {@link FoundResultStatus#SUCCESS} entails that mapping the input to a command was successful. Therefore, + * the command description, labels and arguments are set. The difference is 0.0.
  • + *
  • {@link FoundResultStatus#INCORRECT_ARGUMENTS}: The received parts could be mapped to a command but the argument + * count doesn't match. Guarantees that the command description field is not null; difference is 0.0
  • + *
  • {@link FoundResultStatus#UNKNOWN_LABEL}: The labels could not be mapped to a command. The command description + * may be set to the most similar command, or it may be null. Difference is above 0.0.
  • + *
  • {@link FoundResultStatus#MISSING_BASE_COMMAND} should never occur. All other fields may be null and any further + * processing of the object should be aborted.
  • + *
*/ public class FoundCommandResult { /** * The command description instance. */ - private CommandDescription commandDescription; + private final CommandDescription commandDescription; /** - * The command reference. + * The labels used to invoke the command. This may be different for the same {@link ExecutableCommand} instance + * if multiple labels have been defined, e.g. "/authme register" and "/authme reg". */ - private final CommandParts commandReference; - /** - * The command arguments. - */ - private final CommandParts commandArguments; - /** - * The original search query reference. - */ - private final CommandParts queryReference; + private final List labels; + /** The command arguments. */ + private final List arguments; + /** The difference between the matched command and the supplied labels. */ + private final double difference; + /** The status of the result (see class description). */ + private final FoundResultStatus resultStatus; /** * Constructor. * * @param commandDescription The command description. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * @param queryReference The original query reference. + * @param labels The labels used to access the command. + * @param arguments The command arguments. + * @param difference The difference between the supplied labels and the matched command. + * @param resultStatus The status of the result. */ - public FoundCommandResult(CommandDescription commandDescription, CommandParts commandReference, CommandParts commandArguments, CommandParts queryReference) { + public FoundCommandResult(CommandDescription commandDescription, List labels, List arguments, + double difference, FoundResultStatus resultStatus) { this.commandDescription = commandDescription; - this.commandReference = commandReference; - this.commandArguments = commandArguments; - this.queryReference = queryReference; + this.labels = labels; + this.arguments = arguments; + this.difference = difference; + this.resultStatus = resultStatus; } /** - * Check whether the command was suitable. + * Constructor for a fully successfully matched command. * - * @return True if the command was suitable, false otherwise. + * @param commandDescription The matched command description. + * @param labels The labels used to access the command. + * @param arguments The command arguments. */ - public boolean hasProperArguments() { - // Make sure the command description is set - if (this.commandDescription == null) - return false; - - // Get and return the result - return getCommandDescription().getSuitableArgumentsDifference(this.queryReference) == 0; + public FoundCommandResult(CommandDescription commandDescription, List labels, List arguments) { + this(commandDescription, labels, arguments, 0.0, FoundResultStatus.SUCCESS); } - /** - * Get the command description. - * - * @return Command description. - */ public CommandDescription getCommandDescription() { return this.commandDescription; } - /** - * Check whether the command is executable. - * - * @return True if the command is executable, false otherwise. - */ - public boolean isExecutable() { - return commandDescription != null; + public List getArguments() { + return this.arguments; } - /** - * Execute the command. - * - * @param sender The command sender that executed the command. - * - * @return True on success, false on failure. - */ - public boolean executeCommand(CommandSender sender) { - // Make sure the command description is valid - if (this.commandDescription == null) - return false; - - // Execute the command - return this.commandDescription.execute(sender, this.commandReference, this.commandArguments); + public List getLabels() { + return this.labels; } - /** - * Check whether a command sender has permission to execute the command. - * - * @param sender The command sender. - * - * @return True if the command sender has permission, false otherwise. - */ - public boolean hasPermission(CommandSender sender) { - if (commandDescription == null) { - return false; - } else if (commandDescription.getCommandPermissions() == null) { - return true; - } - - // TODO: Move permissions check to the permission package; command package should not define permission-checking - // API - return commandDescription.getCommandPermissions().hasPermission(sender); - } - - /** - * Get the command reference. - * - * @return The command reference. - */ - public CommandParts getCommandReference() { - return this.commandReference; - } - - /** - * Get the command arguments. - * - * @return The command arguments. - */ - public CommandParts getCommandArguments() { - return this.commandArguments; - } - - /** - * Get the original query reference. - * - * @return Original query reference. - */ - public CommandParts getQueryReference() { - return this.queryReference; - } - - /** - * Get the difference value between the original query and the result reference. - * - * @return The difference value. - */ public double getDifference() { - // Get the difference through the command found - if (this.commandDescription != null) { - return this.commandDescription.getCommandDifference(this.queryReference); - } - - // Get the difference from the query reference - return CommandUtils.getDifference(queryReference.getList(), commandReference.getList(), true); + return difference; } + + public FoundResultStatus getResultStatus() { + return resultStatus; + } + } diff --git a/src/main/java/fr/xephi/authme/command/FoundResultStatus.java b/src/main/java/fr/xephi/authme/command/FoundResultStatus.java new file mode 100644 index 00000000..080a3447 --- /dev/null +++ b/src/main/java/fr/xephi/authme/command/FoundResultStatus.java @@ -0,0 +1,16 @@ +package fr.xephi.authme.command; + +/** + * Result status for mapping command parts. See {@link FoundCommandResult} for a detailed description of the states. + */ +public enum FoundResultStatus { + + SUCCESS, + + INCORRECT_ARGUMENTS, + + UNKNOWN_LABEL, + + MISSING_BASE_COMMAND + +} diff --git a/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java b/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java index 49aa82e8..793803e5 100644 --- a/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java @@ -1,27 +1,56 @@ package fr.xephi.authme.command.executable; -import fr.xephi.authme.command.CommandParts; +import fr.xephi.authme.command.CommandHandler; +import fr.xephi.authme.command.CommandUtils; import fr.xephi.authme.command.ExecutableCommand; +import fr.xephi.authme.command.FoundCommandResult; +import fr.xephi.authme.command.FoundResultStatus; import fr.xephi.authme.command.help.HelpProvider; +import fr.xephi.authme.permission.PermissionsManager; +import fr.xephi.authme.util.Wrapper; +import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; -/** - */ +import java.util.List; + +import static fr.xephi.authme.command.FoundResultStatus.MISSING_BASE_COMMAND; +import static fr.xephi.authme.command.FoundResultStatus.UNKNOWN_LABEL; + public class HelpCommand extends ExecutableCommand { + // Convention: arguments is not the actual invoked arguments but the command that was invoked, + // e.g. "/authme help register" would typically be arguments = [register], but here we pass [authme, register] @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // Check whether quick help should be shown - boolean quickHelp = commandArguments.getCount() == 0; + public void executeCommand(CommandSender sender, List arguments) { + // TODO #306 ljacqu 20151213: Get command handler from non-static context + CommandHandler commandHandler = Wrapper.getInstance().getAuthMe().getCommandHandler(); + FoundCommandResult foundCommandResult = commandHandler.mapPartsToCommand(arguments); - // Set the proper command arguments for the quick help and show it - if (quickHelp) { - commandArguments = new CommandParts(commandReference.get(0)); - HelpProvider.showHelp(sender, commandReference, commandArguments, false, false, false, false, false, true); - } else { - HelpProvider.showHelp(sender, commandReference, commandArguments); + // TODO ljacqu 20151213: This is essentially the same logic as in CommandHandler and we'd like to have the same + // messages. Maybe we can have another method in CommandHandler where the end command isn't executed upon + // success. + FoundResultStatus resultStatus = foundCommandResult.getResultStatus(); + if (MISSING_BASE_COMMAND.equals(resultStatus)) { + sender.sendMessage(ChatColor.DARK_RED + "Could not get base command"); + return; + } else if (UNKNOWN_LABEL.equals(resultStatus)) { + if (foundCommandResult.getCommandDescription() == null) { + sender.sendMessage(ChatColor.DARK_RED + "Unknown command"); + return; + } else { + sender.sendMessage(ChatColor.GOLD + "Assuming " + ChatColor.WHITE + + CommandUtils.constructCommandPath(foundCommandResult.getCommandDescription())); + } + } + + PermissionsManager permissionsManager = Wrapper.getInstance().getAuthMe().getPermissionsManager(); + List lines = arguments.size() == 1 + ? HelpProvider.printHelp(foundCommandResult, HelpProvider.SHOW_CHILDREN) + : HelpProvider.printHelp(foundCommandResult, sender, permissionsManager, HelpProvider.ALL_OPTIONS); + for (String line : lines) { + sender.sendMessage(line); } - return true; } + } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java index 2c629ca2..2fc63e0d 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java @@ -2,7 +2,6 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; @@ -10,31 +9,21 @@ import org.bukkit.command.CommandSender; import java.util.List; -/** - */ public class AccountsCommand extends ExecutableCommand { @Override - public boolean executeCommand(final CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // AuthMe plugin instance + public void executeCommand(final CommandSender sender, List arguments) { final AuthMe plugin = AuthMe.getInstance(); - - // Messages instance final Messages m = plugin.getMessages(); - // Get the player query - String playerQuery = sender.getName(); - if (commandArguments.getCount() >= 1) { - playerQuery = commandArguments.get(0); - } - final String playerQueryFinal = playerQuery; + final String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0); // Command logic - if (!playerQueryFinal.contains(".")) { + if (!playerName.contains(".")) { plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() { @Override public void run() { - PlayerAuth auth = plugin.database.getAuth(playerQueryFinal.toLowerCase()); + PlayerAuth auth = plugin.database.getAuth(playerName.toLowerCase()); if (auth == null) { m.send(sender, MessageKey.UNKNOWN_USER); return; @@ -46,7 +35,7 @@ public class AccountsCommand extends ExecutableCommand { return; } if (accountList.size() == 1) { - sender.sendMessage("[AuthMe] " + playerQueryFinal + " is a single account player"); + sender.sendMessage("[AuthMe] " + playerName + " is a single account player"); return; } int i = 0; @@ -59,24 +48,24 @@ public class AccountsCommand extends ExecutableCommand { message.append('.'); } } - sender.sendMessage("[AuthMe] " + playerQueryFinal + " has " + sender.sendMessage("[AuthMe] " + playerName + " has " + String.valueOf(accountList.size()) + " accounts."); sender.sendMessage(message.toString()); } }); - return true; + return; } else { plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() { @Override public void run() { - List accountList = plugin.database.getAllAuthsByIp(playerQueryFinal); + List accountList = plugin.database.getAllAuthsByIp(playerName); StringBuilder message = new StringBuilder("[AuthMe] "); if (accountList.isEmpty()) { sender.sendMessage("[AuthMe] This IP does not exist in the database."); return; } if (accountList.size() == 1) { - sender.sendMessage("[AuthMe] " + playerQueryFinal + " is a single account player"); + sender.sendMessage("[AuthMe] " + playerName + " is a single account player"); return; } int i = 0; @@ -89,12 +78,11 @@ public class AccountsCommand extends ExecutableCommand { message.append('.'); } } - sender.sendMessage("[AuthMe] " + playerQueryFinal + " has " + sender.sendMessage("[AuthMe] " + playerName + " has " + String.valueOf(accountList.size()) + " accounts."); sender.sendMessage(message.toString()); } }); - return true; } } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java index f00ea916..3cd42839 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java @@ -1,21 +1,24 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; +import java.util.List; + /** + * AuthMe base command; shows the version and some command pointers. */ public class AuthMeCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // Show some version info - sender.sendMessage(ChatColor.GREEN + "This server is running " + AuthMe.getPluginName() + " v" + AuthMe.getPluginVersion() + " b" + AuthMe.getPluginBuildNumber()+ "! " + ChatColor.RED + "<3"); - sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + commandReference.get(0) + " help" + ChatColor.YELLOW + " to view help."); - sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + commandReference.get(0) + " about" + ChatColor.YELLOW + " to view about."); - return true; + public void executeCommand(CommandSender sender, List arguments) { + sender.sendMessage(ChatColor.GREEN + "This server is running " + AuthMe.getPluginName() + " v" + + AuthMe.getPluginVersion() + " b" + AuthMe.getPluginBuildNumber()+ "! " + ChatColor.RED + "<3"); + sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/authme help" + ChatColor.YELLOW + + " to view help."); + sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/authme about" + ChatColor.YELLOW + + " to view about."); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommand.java index d9889915..3bd48c6f 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommand.java @@ -4,16 +4,16 @@ import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; -import fr.xephi.authme.security.PasswordSecurity; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; +import fr.xephi.authme.security.PasswordSecurity; import fr.xephi.authme.settings.Settings; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import java.security.NoSuchAlgorithmException; +import java.util.List; /** * Admin command for changing a player's password. @@ -21,14 +21,13 @@ import java.security.NoSuchAlgorithmException; public class ChangePasswordAdminCommand extends ExecutableCommand { @Override - public boolean executeCommand(final CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(final CommandSender sender, List arguments) { final AuthMe plugin = AuthMe.getInstance(); - // Messages instance final Messages m = plugin.getMessages(); // Get the player and password - String playerName = commandArguments.get(0); - final String playerPass = commandArguments.get(1); + String playerName = arguments.get(0); + final String playerPass = arguments.get(1); // Validate the password String playerPassLowerCase = playerPass.toLowerCase(); @@ -38,20 +37,20 @@ public class ChangePasswordAdminCommand extends ExecutableCommand { || playerPassLowerCase.contains(";") || playerPassLowerCase.contains("null") || !playerPassLowerCase.matches(Settings.getPassRegex)) { m.send(sender, MessageKey.PASSWORD_MATCH_ERROR); - return true; + return; } if (playerPassLowerCase.equalsIgnoreCase(playerName)) { m.send(sender, MessageKey.PASSWORD_IS_USERNAME_ERROR); - return true; + return; } if (playerPassLowerCase.length() < Settings.getPasswordMinLen || playerPassLowerCase.length() > Settings.passwordMaxLength) { m.send(sender, MessageKey.INVALID_PASSWORD_LENGTH); - return true; + return; } if (!Settings.unsafePasswords.isEmpty() && Settings.unsafePasswords.contains(playerPassLowerCase)) { m.send(sender, MessageKey.PASSWORD_UNSAFE_ERROR); - return true; + return; } // Set the password final String playerNameLowerCase = playerName.toLowerCase(); @@ -90,6 +89,5 @@ public class ChangePasswordAdminCommand extends ExecutableCommand { } }); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java index 2399a432..73a56a8a 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java @@ -1,18 +1,17 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.ConsoleLogger; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.settings.Spawn; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class FirstSpawnCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the command executor is a player try { if (sender instanceof Player) { @@ -26,6 +25,5 @@ public class FirstSpawnCommand extends ExecutableCommand { // TODO ljacqu 20151119: Catching NullPointerException is never a good idea. Find what can cause one instead ConsoleLogger.showError(ex.getMessage()); } - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java index f6f3efef..b4f8dd31 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java @@ -1,45 +1,45 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.permission.PlayerPermission; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.util.List; + /** */ public class ForceLoginCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // AuthMe plugin instance final AuthMe plugin = AuthMe.getInstance(); // Get the player query String playerName = sender.getName(); - if (commandArguments.getCount() >= 1) - playerName = commandArguments.get(0); + if (arguments.size() >= 1) { + playerName = arguments.get(0); + } // Command logic try { - @SuppressWarnings("deprecation") + // TODO ljacqu 20151212: Retrieve player via Utils method instead Player player = Bukkit.getPlayer(playerName); if (player == null || !player.isOnline()) { sender.sendMessage("Player needs to be online!"); - return true; + return; } if (!plugin.getPermissionsManager().hasPermission(player, PlayerPermission.CAN_LOGIN_BE_FORCED)) { sender.sendMessage("You cannot force login for the player " + playerName + "!"); - return true; + return; } plugin.getManagement().performLogin(player, "dontneed", true); sender.sendMessage("Force Login for " + playerName + " performed!"); } catch (Exception e) { sender.sendMessage("An error occurred while trying to get that player!"); } - - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java index cc0ac9b8..10ec96d3 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java @@ -2,31 +2,18 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; import org.bukkit.command.CommandSender; -/** - */ +import java.util.List; + public class GetEmailCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // Get the player name - String playerName = sender.getName(); - if (commandArguments.getCount() >= 1) - playerName = commandArguments.get(0); + public void executeCommand(CommandSender sender, List arguments) { + String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0); // Get the authenticated user AuthMe plugin = AuthMe.getInstance(); @@ -34,11 +21,10 @@ public class GetEmailCommand extends ExecutableCommand { PlayerAuth auth = plugin.database.getAuth(playerName.toLowerCase()); if (auth == null) { m.send(sender, MessageKey.UNKNOWN_USER); - return true; + return; } // Show the email address sender.sendMessage("[AuthMe] " + playerName + "'s email: " + auth.getEmail()); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java index f311a41d..a4c0cec5 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java @@ -1,34 +1,32 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class GetIpCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // AuthMe plugin instance + public void executeCommand(CommandSender sender, List arguments) { final AuthMe plugin = AuthMe.getInstance(); // Get the player query - String playerName = sender.getName(); - if (commandArguments.getCount() >= 1) - playerName = commandArguments.get(0); + String playerName = (arguments.size() >= 1) ? arguments.get(0) : sender.getName(); - @SuppressWarnings("deprecation") + // TODO ljacqu 20151212: Use the Utils function instead Player player = Bukkit.getPlayer(playerName); if (player == null) { - sender.sendMessage("This player is not actually online"); - return true; + sender.sendMessage("The player is not online"); + return; } - sender.sendMessage(player.getName() + "'s actual IP is : " + player.getAddress().getAddress().getHostAddress() + ":" + player.getAddress().getPort()); + + // TODO ljacqu 20151212: Revise the messages (actual IP vs. real IP...?) + sender.sendMessage(player.getName() + "'s actual IP is : " + player.getAddress().getAddress().getHostAddress() + + ":" + player.getAddress().getPort()); sender.sendMessage(player.getName() + "'s real IP is : " + plugin.getIP(player)); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java index ecae052b..3696187c 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java @@ -2,24 +2,22 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; import org.bukkit.command.CommandSender; import java.util.Date; +import java.util.List; /** */ public class LastLoginCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Get the player - String playerName = sender.getName(); - if (commandArguments.getCount() >= 1) - playerName = commandArguments.get(0); + String playerName = (arguments.size() >= 1) ? arguments.get(0) : sender.getName(); // Validate the player AuthMe plugin = AuthMe.getInstance(); @@ -30,11 +28,11 @@ public class LastLoginCommand extends ExecutableCommand { auth = plugin.database.getAuth(playerName.toLowerCase()); } catch (NullPointerException e) { m.send(sender, MessageKey.UNKNOWN_USER); - return true; + return; } if (auth == null) { m.send(sender, MessageKey.USER_NOT_REGISTERED); - return true; + return; } // Get the last login date @@ -45,7 +43,8 @@ public class LastLoginCommand extends ExecutableCommand { final long diff = System.currentTimeMillis() - lastLogin; // Build the message - final String msg = (int) (diff / 86400000) + " days " + (int) (diff / 3600000 % 24) + " hours " + (int) (diff / 60000 % 60) + " mins " + (int) (diff / 1000 % 60) + " secs."; + final String msg = (int) (diff / 86400000) + " days " + (int) (diff / 3600000 % 24) + " hours " + + (int) (diff / 60000 % 60) + " mins " + (int) (diff / 1000 % 60) + " secs."; // Get the player's last IP String lastIP = auth.getIp(); @@ -54,6 +53,5 @@ public class LastLoginCommand extends ExecutableCommand { sender.sendMessage("[AuthMe] " + playerName + " last login : " + date.toString()); sender.sendMessage("[AuthMe] The player " + auth.getNickname() + " is unlogged since " + msg); sender.sendMessage("[AuthMe] Last Player's IP: " + lastIP); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeBannedPlayersCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeBannedPlayersCommand.java index 5ecaad8c..6293ef7a 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeBannedPlayersCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeBannedPlayersCommand.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.settings.Settings; import org.bukkit.OfflinePlayer; @@ -10,21 +9,10 @@ import org.bukkit.command.CommandSender; import java.util.ArrayList; import java.util.List; -/** - */ public class PurgeBannedPlayersCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // AuthMe plugin instance final AuthMe plugin = AuthMe.getInstance(); @@ -47,6 +35,5 @@ public class PurgeBannedPlayersCommand extends ExecutableCommand { // Show a status message sender.sendMessage("[AuthMe] Database has been purged correctly"); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java index 69dd80d3..696e045d 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.settings.Settings; import org.bukkit.ChatColor; @@ -10,40 +9,29 @@ import org.bukkit.command.CommandSender; import java.util.Calendar; import java.util.List; -/** - */ public class PurgeCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // AuthMe plugin instance AuthMe plugin = AuthMe.getInstance(); // Get the days parameter - String daysStr = commandArguments.get(0); + String daysStr = arguments.get(0); // Convert the days string to an integer value, and make sure it's valid int days; try { - days = Integer.valueOf(daysStr); - } catch (Exception ex) { + days = Integer.parseInt(daysStr); + } catch (NumberFormatException ex) { sender.sendMessage(ChatColor.RED + "The value you've entered is invalid!"); - return true; + return; } // Validate the value if (days < 30) { sender.sendMessage(ChatColor.RED + "You can only purge data older than 30 days"); - return true; + return; } // Create a calender instance to determine the date @@ -69,6 +57,5 @@ public class PurgeCommand extends ExecutableCommand { // Show a status message sender.sendMessage(ChatColor.GREEN + "[AuthMe] Database has been purged correctly"); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java index e9e3c9ad..844b7897 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java @@ -3,38 +3,24 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class PurgeLastPositionCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(final CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // AuthMe plugin instance + public void executeCommand(final CommandSender sender, List arguments) { final AuthMe plugin = AuthMe.getInstance(); - - // Messages instance final Messages m = plugin.getMessages(); + String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0); + // Get the player - String playerName = sender.getName(); - if (commandArguments.getCount() >= 1) - playerName = commandArguments.get(0); String playerNameLowerCase = playerName.toLowerCase(); // Purge the last position of the player @@ -43,7 +29,7 @@ public class PurgeLastPositionCommand extends ExecutableCommand { PlayerAuth auth = plugin.database.getAuth(playerNameLowerCase); if (auth == null) { m.send(sender, MessageKey.UNKNOWN_USER); - return true; + return; } // Set the last position @@ -62,6 +48,5 @@ public class PurgeLastPositionCommand extends ExecutableCommand { if (sender instanceof Player) sender.sendMessage("An error occurred while trying to reset location or player do not exist, please see logs"); } - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java index 1d7302d1..590db3d8 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java @@ -3,33 +3,24 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; -import fr.xephi.authme.security.PasswordSecurity; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; +import fr.xephi.authme.security.PasswordSecurity; import fr.xephi.authme.settings.Settings; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import java.security.NoSuchAlgorithmException; +import java.util.List; /** * Admin command to register a user. */ public class RegisterAdminCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(final CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(final CommandSender sender, List arguments) { // AuthMe plugin instance final AuthMe plugin = AuthMe.getInstance(); @@ -37,8 +28,8 @@ public class RegisterAdminCommand extends ExecutableCommand { final Messages m = plugin.getMessages(); // Get the player name and password - final String playerName = commandArguments.get(0); - final String playerPass = commandArguments.get(1); + final String playerName = arguments.get(0); + final String playerPass = arguments.get(1); final String playerNameLowerCase = playerName.toLowerCase(); final String playerPassLowerCase = playerPass.toLowerCase(); @@ -49,20 +40,20 @@ public class RegisterAdminCommand extends ExecutableCommand { || playerPassLowerCase.contains(";") || playerPassLowerCase.contains("null") || !playerPassLowerCase.matches(Settings.getPassRegex)) { m.send(sender, MessageKey.PASSWORD_MATCH_ERROR); - return true; + return; } if (playerPassLowerCase.equalsIgnoreCase(playerName)) { m.send(sender, MessageKey.PASSWORD_IS_USERNAME_ERROR); - return true; + return; } if (playerPassLowerCase.length() < Settings.getPasswordMinLen || playerPassLowerCase.length() > Settings.passwordMaxLength) { m.send(sender, MessageKey.INVALID_PASSWORD_LENGTH); - return true; + return; } if (!Settings.unsafePasswords.isEmpty()) { if (Settings.unsafePasswords.contains(playerPassLowerCase)) { m.send(sender, MessageKey.PASSWORD_UNSAFE_ERROR); - return true; + return; } } plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() { @@ -95,6 +86,5 @@ public class RegisterAdminCommand extends ExecutableCommand { } }); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java index 1eaf3717..1da59f7d 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java @@ -1,10 +1,7 @@ package fr.xephi.authme.command.executable.authme; -//import org.bukkit.ChatColor; - import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; @@ -12,21 +9,12 @@ import fr.xephi.authme.settings.Settings; import fr.xephi.authme.util.Profiler; import org.bukkit.command.CommandSender; -/** - */ +import java.util.List; + public class ReloadCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Profile the reload process Profiler p = new Profiler(true); @@ -48,7 +36,6 @@ public class ReloadCommand extends ExecutableCommand { ConsoleLogger.showError("Fatal error occurred! AuthMe instance ABORTED!"); ConsoleLogger.writeStackTrace(e); plugin.stopOrUnload(); - return false; } // Show a status message @@ -57,6 +44,5 @@ public class ReloadCommand extends ExecutableCommand { // AuthMeReloaded reloaded, show a status message // sender.sendMessage(ChatColor.GREEN + "AuthMeReloaded has been reloaded successfully, took " + p.getTimeFormatted() + "!"); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ResetNameCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ResetNameCommand.java deleted file mode 100644 index dc884997..00000000 --- a/src/main/java/fr/xephi/authme/command/executable/authme/ResetNameCommand.java +++ /dev/null @@ -1,44 +0,0 @@ -package fr.xephi.authme.command.executable.authme; - -import fr.xephi.authme.AuthMe; -import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.command.CommandParts; -import fr.xephi.authme.command.ExecutableCommand; -import org.bukkit.command.CommandSender; - -import java.util.List; - -/** - */ -// TODO: remove if not used -public class ResetNameCommand extends ExecutableCommand { - - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ - @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // AuthMe plugin instance - final AuthMe plugin = AuthMe.getInstance(); - - // Command logic - plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() { - @Override - public void run() { - List authentications = plugin.database.getAllAuths(); - for (PlayerAuth auth : authentications) { - auth.setRealName("Player"); - plugin.database.updateSession(auth); - } - } - }); - - return true; - } -} diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java index 813443f4..b52a07eb 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java @@ -3,28 +3,18 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; import fr.xephi.authme.settings.Settings; import org.bukkit.command.CommandSender; -/** - */ +import java.util.List; + public class SetEmailCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(final CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(final CommandSender sender, List arguments) { // AuthMe plugin instance final AuthMe plugin = AuthMe.getInstance(); @@ -32,13 +22,13 @@ public class SetEmailCommand extends ExecutableCommand { final Messages m = plugin.getMessages(); // Get the player name and email address - final String playerName = commandArguments.get(0); - final String playerEmail = commandArguments.get(1); + final String playerName = arguments.get(0); + final String playerEmail = arguments.get(1); // Validate the email address if (!Settings.isEmailCorrect(playerEmail)) { m.send(sender, MessageKey.INVALID_EMAIL); - return true; + return; } plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() { @@ -69,6 +59,5 @@ public class SetEmailCommand extends ExecutableCommand { } }); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommand.java index 279941d7..d1cea3de 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommand.java @@ -1,27 +1,17 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.ConsoleLogger; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.settings.Spawn; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class SetFirstSpawnCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { try { if (sender instanceof Player) { if (Spawn.getInstance().setFirstSpawn(((Player) sender).getLocation())) @@ -33,6 +23,5 @@ public class SetFirstSpawnCommand extends ExecutableCommand { } catch (NullPointerException ex) { ConsoleLogger.showError(ex.getMessage()); } - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SetSpawnCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SetSpawnCommand.java index 35576356..63029db0 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SetSpawnCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SetSpawnCommand.java @@ -1,27 +1,17 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.ConsoleLogger; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.settings.Spawn; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class SetSpawnCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the command executor is a player try { if (sender instanceof Player) { @@ -36,6 +26,5 @@ public class SetSpawnCommand extends ExecutableCommand { } catch (NullPointerException ex) { ConsoleLogger.showError(ex.getMessage()); } - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SpawnCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SpawnCommand.java index 67854f87..93272658 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SpawnCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SpawnCommand.java @@ -1,27 +1,17 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.ConsoleLogger; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.settings.Spawn; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class SpawnCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the command executor is a player try { if (sender instanceof Player) { @@ -29,11 +19,10 @@ public class SpawnCommand extends ExecutableCommand { ((Player) sender).teleport(Spawn.getInstance().getSpawn()); else sender.sendMessage("[AuthMe] Spawn has failed, please try to define the spawn"); } else { - sender.sendMessage("[AuthMe] Please use that command in game"); + sender.sendMessage("[AuthMe] Please use the command in game"); } } catch (NullPointerException ex) { ConsoleLogger.showError(ex.getMessage()); } - return true; } } 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 3c047867..73fac3fb 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,64 +1,43 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AntiBot; -import fr.xephi.authme.command.CommandParts; -import fr.xephi.authme.command.CommandUtils; +import fr.xephi.authme.AuthMe; +import fr.xephi.authme.command.CommandHandler; import fr.xephi.authme.command.ExecutableCommand; +import fr.xephi.authme.command.FoundCommandResult; import fr.xephi.authme.command.help.HelpProvider; -import fr.xephi.authme.util.CollectionUtils; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; +import java.util.Arrays; import java.util.List; -/** - */ public class SwitchAntiBotCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(final CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // Get the new state - String newState = null; - if (commandArguments.getCount() == 1) { - newState = commandArguments.get(0); - } else if(commandArguments.getCount() == 0) { + public void executeCommand(final CommandSender sender, List arguments) { + if (arguments.isEmpty()) { sender.sendMessage("[AuthMe] AntiBot status: " + AntiBot.getAntiBotStatus().name()); - return true; + return; } - // Enable the mod + String newState = arguments.get(0); + + // Enable or disable the mod if ("ON".equalsIgnoreCase(newState)) { AntiBot.overrideAntiBotStatus(true); sender.sendMessage("[AuthMe] AntiBot Manual Override: enabled!"); - return true; - } - - // Disable the mod - if ("OFF".equalsIgnoreCase(newState)) { + } else if ("OFF".equalsIgnoreCase(newState)) { AntiBot.overrideAntiBotStatus(false); sender.sendMessage("[AuthMe] AntiBotMod Manual Override: disabled!"); - return true; + } else { + sender.sendMessage(ChatColor.DARK_RED + "Invalid AntiBot mode!"); + // TODO ljacqu 20151213: Fix static retrieval of command handler + CommandHandler commandHandler = AuthMe.getInstance().getCommandHandler(); + FoundCommandResult foundCommandResult = + commandHandler.mapPartsToCommand(Arrays.asList("authme", "antibot")); + HelpProvider.printHelp(foundCommandResult, HelpProvider.SHOW_ARGUMENTS); + sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/authme help antibot"); } - - // Show the invalid arguments warning - sender.sendMessage(ChatColor.DARK_RED + "Invalid AntiBot mode!"); - - // Show the command argument help - HelpProvider.showHelp(sender, commandReference, commandReference, true, false, true, false, false, false); - - // Show the command to use for detailed help - List helpCommandReference = CollectionUtils.getRange(commandReference.getList(), 1); - sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/" - + commandReference.get(0) + " help " + CommandUtils.labelsToString(helpCommandReference)); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java index 5615061f..84ffdb24 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java @@ -4,7 +4,6 @@ import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.limbo.LimboCache; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; @@ -19,22 +18,16 @@ import org.bukkit.potion.PotionEffectType; import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitTask; +import java.util.List; + /** * Admin command to unregister a player. */ public class UnregisterAdminCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ + @Override - public boolean executeCommand(final CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(final CommandSender sender, List arguments) { // AuthMe plugin instance final AuthMe plugin = AuthMe.getInstance(); @@ -42,19 +35,19 @@ public class UnregisterAdminCommand extends ExecutableCommand { final Messages m = plugin.getMessages(); // Get the player name - String playerName = commandArguments.get(0); + String playerName = arguments.get(0); String playerNameLowerCase = playerName.toLowerCase(); // Make sure the user is valid if (!plugin.database.isAuthAvailable(playerNameLowerCase)) { m.send(sender, MessageKey.UNKNOWN_USER); - return true; + return; } // Remove the player if (!plugin.database.removeAuth(playerNameLowerCase)) { m.send(sender, MessageKey.ERROR); - return true; + return; } // Unregister the player @@ -85,6 +78,5 @@ public class UnregisterAdminCommand extends ExecutableCommand { // Show a status message m.send(sender, MessageKey.UNREGISTERED_SUCCESS); ConsoleLogger.info(playerName + " unregistered"); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java index fc92ac8f..9e728f20 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java @@ -1,30 +1,19 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.settings.Settings; - import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class VersionCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Show some version info sender.sendMessage(ChatColor.GOLD + "==========[ " + Settings.helpHeader.toUpperCase() + " ABOUT ]=========="); sender.sendMessage(ChatColor.GOLD + "Version: " + ChatColor.WHITE + AuthMe.getPluginName() + " v" + AuthMe.getPluginVersion() + ChatColor.GRAY + " (build: " + AuthMe.getPluginBuildNumber() + ")"); @@ -37,7 +26,6 @@ public class VersionCommand extends ExecutableCommand { sender.sendMessage(ChatColor.GOLD + "Website: " + ChatColor.WHITE + "http://dev.bukkit.org/bukkit-plugins/authme-reloaded/"); sender.sendMessage(ChatColor.GOLD + "License: " + ChatColor.WHITE + "GNU GPL v3.0" + ChatColor.GRAY + ChatColor.ITALIC + " (See LICENSE file)"); sender.sendMessage(ChatColor.GOLD + "Copyright: " + ChatColor.WHITE + "Copyright (c) Xephi 2015. All rights reserved."); - return true; } /** diff --git a/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java b/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java index be07e33a..2373f773 100644 --- a/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java @@ -2,25 +2,24 @@ package fr.xephi.authme.command.executable.captcha; import fr.xephi.authme.AuthMe; import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; -import fr.xephi.authme.security.RandomString; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; +import fr.xephi.authme.security.RandomString; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.util.Wrapper; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class CaptchaCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the current command executor is a player if (!(sender instanceof Player)) { - return true; + return; } // Get the player instance and name @@ -28,7 +27,7 @@ public class CaptchaCommand extends ExecutableCommand { final String playerNameLowerCase = player.getName().toLowerCase(); // Get the parameter values - String captcha = commandArguments.get(0); + String captcha = arguments.get(0); // AuthMe plugin instance final Wrapper wrapper = Wrapper.getInstance(); @@ -40,18 +39,18 @@ public class CaptchaCommand extends ExecutableCommand { // Command logic if (PlayerCache.getInstance().isAuthenticated(playerNameLowerCase)) { m.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR); - return true; + return; } if (!Settings.useCaptcha) { m.send(player, MessageKey.USAGE_LOGIN); - return true; + return; } if (!plugin.cap.containsKey(playerNameLowerCase)) { m.send(player, MessageKey.USAGE_LOGIN); - return true; + return; } if (Settings.useCaptcha && !captcha.equals(plugin.cap.get(playerNameLowerCase))) { @@ -59,7 +58,7 @@ public class CaptchaCommand extends ExecutableCommand { String randStr = new RandomString(Settings.captchaLength).nextString(); plugin.cap.put(playerNameLowerCase, randStr); m.send(player, MessageKey.CAPTCHA_WRONG_ERROR, plugin.cap.get(playerNameLowerCase)); - return true; + return; } plugin.captcha.remove(playerNameLowerCase); @@ -68,6 +67,5 @@ public class CaptchaCommand extends ExecutableCommand { // Show a status message m.send(player, MessageKey.CAPTCHA_SUCCESS); m.send(player, MessageKey.LOGIN_MESSAGE); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommand.java b/src/main/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommand.java index f9219aba..67fd1180 100644 --- a/src/main/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommand.java @@ -2,7 +2,6 @@ package fr.xephi.authme.command.executable.changepassword; import fr.xephi.authme.AuthMe; import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; @@ -12,24 +11,26 @@ import fr.xephi.authme.util.Wrapper; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.util.List; + /** * The command for a player to change his password with. */ public class ChangePasswordCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the current command executor is a player if (!(sender instanceof Player)) { - return true; + return; } final Wrapper wrapper = Wrapper.getInstance(); final Messages m = wrapper.getMessages(); // Get the passwords - String oldPassword = commandArguments.get(0); - String newPassword = commandArguments.get(1); + String oldPassword = arguments.get(0); + String newPassword = arguments.get(1); // Get the player instance and make sure he's authenticated Player player = (Player) sender; @@ -37,7 +38,7 @@ public class ChangePasswordCommand extends ExecutableCommand { final PlayerCache playerCache = wrapper.getPlayerCache(); if (!playerCache.isAuthenticated(name)) { m.send(player, MessageKey.NOT_LOGGED_IN); - return true; + return; } // Make sure the password is allowed @@ -48,26 +49,25 @@ public class ChangePasswordCommand extends ExecutableCommand { || playerPassLowerCase.contains(";") || playerPassLowerCase.contains("null") || !playerPassLowerCase.matches(Settings.getPassRegex)) { m.send(player, MessageKey.PASSWORD_MATCH_ERROR); - return true; + return; } if (playerPassLowerCase.equalsIgnoreCase(name)) { m.send(player, MessageKey.PASSWORD_IS_USERNAME_ERROR); - return true; + return; } if (playerPassLowerCase.length() < Settings.getPasswordMinLen || playerPassLowerCase.length() > Settings.passwordMaxLength) { m.send(player, MessageKey.INVALID_PASSWORD_LENGTH); - return true; + return; } if (!Settings.unsafePasswords.isEmpty() && Settings.unsafePasswords.contains(playerPassLowerCase)) { m.send(player, MessageKey.PASSWORD_UNSAFE_ERROR); - return true; + return; } // Set the password final AuthMe plugin = wrapper.getAuthMe(); wrapper.getScheduler().runTaskAsynchronously(plugin, new ChangePasswordTask(plugin, player, oldPassword, newPassword)); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/converter/ConverterCommand.java b/src/main/java/fr/xephi/authme/command/executable/converter/ConverterCommand.java index 88314997..b877e301 100644 --- a/src/main/java/fr/xephi/authme/command/executable/converter/ConverterCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/converter/ConverterCommand.java @@ -1,29 +1,27 @@ package fr.xephi.authme.command.executable.converter; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; -import fr.xephi.authme.converter.*; +import fr.xephi.authme.converter.Converter; +import fr.xephi.authme.converter.CrazyLoginConverter; +import fr.xephi.authme.converter.FlatToSql; +import fr.xephi.authme.converter.FlatToSqlite; +import fr.xephi.authme.converter.RakamakConverter; +import fr.xephi.authme.converter.RoyalAuthConverter; +import fr.xephi.authme.converter.SqlToFlat; +import fr.xephi.authme.converter.vAuthConverter; +import fr.xephi.authme.converter.xAuthConverter; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; -/** - */ +import java.util.List; + public class ConverterCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // AuthMe plugin instance final AuthMe plugin = AuthMe.getInstance(); @@ -31,40 +29,40 @@ public class ConverterCommand extends ExecutableCommand { final Messages m = plugin.getMessages(); // Get the conversion job - String job = commandArguments.get(0); + String job = arguments.get(0); // Determine the job type ConvertType jobType = ConvertType.fromName(job); if (jobType == null) { m.send(sender, MessageKey.ERROR); - return true; + return; } // Get the proper converter instance Converter converter = null; switch (jobType) { - case ftsql: + case FTSQL: converter = new FlatToSql(); break; - case ftsqlite: + case FTSQLITE: converter = new FlatToSqlite(sender); break; - case xauth: + case XAUTH: converter = new xAuthConverter(plugin, sender); break; - case crazylogin: + case CRAZYLOGIN: converter = new CrazyLoginConverter(plugin, sender); break; - case rakamak: + case RAKAMAK: converter = new RakamakConverter(plugin, sender); break; - case royalauth: + case ROYALAUTH: converter = new RoyalAuthConverter(plugin); break; - case vauth: + case VAUTH: converter = new vAuthConverter(plugin, sender); break; - case sqltoflat: + case SQLTOFLAT: converter = new SqlToFlat(plugin, sender); break; default: @@ -76,52 +74,33 @@ public class ConverterCommand extends ExecutableCommand { // Show a status message sender.sendMessage("[AuthMe] Successfully converted from " + jobType.getName()); - return true; } - /** - */ public enum ConvertType { - ftsql("flattosql"), - ftsqlite("flattosqlite"), - xauth("xauth"), - crazylogin("crazylogin"), - rakamak("rakamak"), - royalauth("royalauth"), - vauth("vauth"), - sqltoflat("sqltoflat"); + FTSQL("flattosql"), + FTSQLITE("flattosqlite"), + XAUTH("xauth"), + CRAZYLOGIN("crazylogin"), + RAKAMAK("rakamak"), + ROYALAUTH("royalauth"), + VAUTH("vauth"), + SQLTOFLAT("sqltoflat"); final String name; - /** - * Constructor for ConvertType. - * - * @param name String - */ ConvertType(String name) { this.name = name; } - /** - * Method fromName. - * - * @param name String - * - * @return ConvertType - */ public static ConvertType fromName(String name) { for (ConvertType type : ConvertType.values()) { - if (type.getName().equalsIgnoreCase(name)) + if (type.getName().equalsIgnoreCase(name)) { return type; + } } return null; } - /** - * Method getName. - * - * @return String - */ String getName() { return this.name; } diff --git a/src/main/java/fr/xephi/authme/command/executable/email/AddEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/email/AddEmailCommand.java index 6e724db1..b94e3f28 100644 --- a/src/main/java/fr/xephi/authme/command/executable/email/AddEmailCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/email/AddEmailCommand.java @@ -1,31 +1,29 @@ package fr.xephi.authme.command.executable.email; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.util.Wrapper; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class AddEmailCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the current command executor is a player if (!(sender instanceof Player)) { - return true; + return; } // Get the parameter values - String playerMail = commandArguments.get(0); - String playerMailVerify = commandArguments.get(1); + String playerMail = arguments.get(0); + String playerMailVerify = arguments.get(1); // Get the player and perform email addition final AuthMe plugin = Wrapper.getInstance().getAuthMe(); final Player player = (Player) sender; plugin.getManagement().performAddEmail(player, playerMail, playerMailVerify); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/email/ChangeEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/email/ChangeEmailCommand.java index f78910e7..31dc9046 100644 --- a/src/main/java/fr/xephi/authme/command/executable/email/ChangeEmailCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/email/ChangeEmailCommand.java @@ -1,31 +1,31 @@ package fr.xephi.authme.command.executable.email; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.util.Wrapper; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.util.List; + /** */ public class ChangeEmailCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the current command executor is a player if (!(sender instanceof Player)) { - return true; + return; } // Get the parameter values - String playerMailOld = commandArguments.get(0); - String playerMailNew = commandArguments.get(1); + String playerMailOld = arguments.get(0); + String playerMailNew = arguments.get(1); // Get the player instance and execute action final AuthMe plugin = Wrapper.getInstance().getAuthMe(); final Player player = (Player) sender; plugin.getManagement().performChangeEmail(player, playerMailOld, playerMailNew); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/email/RecoverEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/email/RecoverEmailCommand.java index 2af4f65a..09815c42 100644 --- a/src/main/java/fr/xephi/authme/command/executable/email/RecoverEmailCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/email/RecoverEmailCommand.java @@ -4,32 +4,30 @@ import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; -import fr.xephi.authme.security.PasswordSecurity; -import fr.xephi.authme.security.RandomString; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; +import fr.xephi.authme.security.PasswordSecurity; +import fr.xephi.authme.security.RandomString; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.util.Wrapper; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.security.NoSuchAlgorithmException; +import java.util.List; -/** - */ public class RecoverEmailCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the current command executor is a player if (!(sender instanceof Player)) { - return true; + return; } // Get the parameter values - String playerMail = commandArguments.get(0); + String playerMail = arguments.get(0); // Get the player instance and name final Player player = (Player) sender; @@ -42,12 +40,12 @@ public class RecoverEmailCommand extends ExecutableCommand { if (plugin.mail == null) { m.send(player, MessageKey.ERROR); - return true; + return; } if (plugin.database.isAuthAvailable(playerName)) { if (PlayerCache.getInstance().isAuthenticated(playerName)) { m.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR); - return true; + return; } try { RandomString rand = new RandomString(Settings.getRecoveryPassLength); @@ -60,16 +58,17 @@ public class RecoverEmailCommand extends ExecutableCommand { auth = plugin.database.getAuth(playerName); } else { m.send(player, MessageKey.UNKNOWN_USER); - return true; + return; } if (Settings.getmailAccount.equals("") || Settings.getmailAccount.isEmpty()) { m.send(player, MessageKey.ERROR); - return true; + return; } - if (!playerMail.equalsIgnoreCase(auth.getEmail()) || playerMail.equalsIgnoreCase("your@email.com") || auth.getEmail().equalsIgnoreCase("your@email.com")) { + if (!playerMail.equalsIgnoreCase(auth.getEmail()) || playerMail.equalsIgnoreCase("your@email.com") + || auth.getEmail().equalsIgnoreCase("your@email.com")) { m.send(player, MessageKey.INVALID_EMAIL); - return true; + return; } auth.setHash(hashNew); plugin.database.updatePassword(auth); @@ -83,7 +82,5 @@ public class RecoverEmailCommand extends ExecutableCommand { } else { m.send(player, MessageKey.REGISTER_EMAIL_MESSAGE); } - - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/login/LoginCommand.java b/src/main/java/fr/xephi/authme/command/executable/login/LoginCommand.java index b57b0bdc..21e8dc79 100644 --- a/src/main/java/fr/xephi/authme/command/executable/login/LoginCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/login/LoginCommand.java @@ -1,30 +1,28 @@ package fr.xephi.authme.command.executable.login; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.util.Wrapper; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class LoginCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the current command executor is a player if (!(sender instanceof Player)) { - return true; + return; } // Get the necessary objects final AuthMe plugin = Wrapper.getInstance().getAuthMe(); final Player player = (Player) sender; - final String password = commandArguments.get(0); + final String password = arguments.get(0); // Log the player in plugin.getManagement().performLogin(player, password, false); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/logout/LogoutCommand.java b/src/main/java/fr/xephi/authme/command/executable/logout/LogoutCommand.java index e1918d07..5adba4dc 100644 --- a/src/main/java/fr/xephi/authme/command/executable/logout/LogoutCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/logout/LogoutCommand.java @@ -1,21 +1,22 @@ package fr.xephi.authme.command.executable.logout; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.util.Wrapper; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.util.List; + /** */ public class LogoutCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the current command executor is a player if (!(sender instanceof Player)) { - return true; + return; } // Get the player instance @@ -24,6 +25,5 @@ public class LogoutCommand extends ExecutableCommand { // Logout the player plugin.getManagement().performLogout(player); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java b/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java index 1f366dea..0aa3e31b 100644 --- a/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java @@ -1,28 +1,26 @@ package fr.xephi.authme.command.executable.register; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; -import fr.xephi.authme.process.Management; -import fr.xephi.authme.security.RandomString; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; +import fr.xephi.authme.process.Management; +import fr.xephi.authme.security.RandomString; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.util.Wrapper; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class RegisterCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - + public void executeCommand(CommandSender sender, List arguments) { // Make sure the sender is a player if (!(sender instanceof Player)) { sender.sendMessage("Player Only! Use 'authme register ' instead"); - return true; + return; } final Wrapper wrapper = Wrapper.getInstance(); @@ -31,35 +29,32 @@ public class RegisterCommand extends ExecutableCommand { // Make sure the command arguments are valid final Player player = (Player) sender; - if (commandArguments.getCount() == 0 || (Settings.getEnablePasswordVerifier && commandArguments.getCount() < 2)) { + if (arguments.isEmpty() || (Settings.getEnablePasswordVerifier && arguments.size() < 2)) { m.send(player, MessageKey.USAGE_REGISTER); - return true; + return; } final Management management = plugin.getManagement(); if (Settings.emailRegistration && !Settings.getmailAccount.isEmpty()) { - if (Settings.doubleEmailCheck) { - if (commandArguments.getCount() < 2 || !commandArguments.get(0).equals(commandArguments.get(1))) { - m.send(player, MessageKey.USAGE_REGISTER); - return true; - } + if (Settings.doubleEmailCheck && arguments.size() < 2 || !arguments.get(0).equals(arguments.get(1))) { + m.send(player, MessageKey.USAGE_REGISTER); + return; } - final String email = commandArguments.get(0); + final String email = arguments.get(0); if (!Settings.isEmailCorrect(email)) { m.send(player, MessageKey.INVALID_EMAIL); - return true; + return; } final String thePass = new RandomString(Settings.getRecoveryPassLength).nextString(); management.performRegister(player, thePass, email); - return true; + return; } - if (commandArguments.getCount() > 1 && Settings.getEnablePasswordVerifier) { - if (!commandArguments.get(0).equals(commandArguments.get(1))) { + if (arguments.size() > 1 && Settings.getEnablePasswordVerifier) { + if (!arguments.get(0).equals(arguments.get(1))) { m.send(player, MessageKey.PASSWORD_MATCH_ERROR); - return true; + return; } } - management.performRegister(player, commandArguments.get(0), ""); - return true; + management.performRegister(player, arguments.get(0), ""); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/unregister/UnregisterCommand.java b/src/main/java/fr/xephi/authme/command/executable/unregister/UnregisterCommand.java index 8ff40ed3..472d4743 100644 --- a/src/main/java/fr/xephi/authme/command/executable/unregister/UnregisterCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/unregister/UnregisterCommand.java @@ -2,41 +2,28 @@ package fr.xephi.authme.command.executable.unregister; import fr.xephi.authme.AuthMe; import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class UnregisterCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // AuthMe plugin instance - final AuthMe plugin = AuthMe.getInstance(); - - // Messages instance - final Messages m = plugin.getMessages(); - + public void executeCommand(CommandSender sender, List arguments) { // Make sure the current command executor is a player if (!(sender instanceof Player)) { - return true; + return; } + final AuthMe plugin = AuthMe.getInstance(); + final Messages m = plugin.getMessages(); + // Get the password - String playerPass = commandArguments.get(0); + String playerPass = arguments.get(0); // Get the player instance and name final Player player = (Player) sender; @@ -45,11 +32,10 @@ public class UnregisterCommand extends ExecutableCommand { // Make sure the player is authenticated if (!PlayerCache.getInstance().isAuthenticated(playerNameLowerCase)) { m.send(player, MessageKey.NOT_LOGGED_IN); - return true; + return; } // Unregister the player plugin.getManagement().performUnregister(player, playerPass, false); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/help/CommandSyntaxHelper.java b/src/main/java/fr/xephi/authme/command/help/CommandSyntaxHelper.java new file mode 100644 index 00000000..40bb2185 --- /dev/null +++ b/src/main/java/fr/xephi/authme/command/help/CommandSyntaxHelper.java @@ -0,0 +1,36 @@ +package fr.xephi.authme.command.help; + +import fr.xephi.authme.command.CommandArgumentDescription; +import fr.xephi.authme.command.CommandDescription; +import org.bukkit.ChatColor; + +import java.util.List; + +/** + * Helper class for displaying the syntax of a command properly to a user. + */ +class CommandSyntaxHelper { + + private CommandSyntaxHelper() { + } + + public static String getSyntax(CommandDescription command, List correctLabels) { + String commandSyntax = ChatColor.WHITE + "/" + correctLabels.get(0) + ChatColor.YELLOW; + for (int i = 1; i < correctLabels.size(); ++i) { + commandSyntax += " " + correctLabels.get(i); + } + for (CommandArgumentDescription argument : command.getArguments()) { + commandSyntax += " " + formatArgument(argument); + } + return commandSyntax; + } + + /** Format a command argument with the proper type of brackets. */ + private static String formatArgument(CommandArgumentDescription argument) { + if (argument.isOptional()) { + return "[" + argument.getName() + "]"; + } + return "<" + argument.getName() + ">"; + } + +} diff --git a/src/main/java/fr/xephi/authme/command/help/HelpPrinter.java b/src/main/java/fr/xephi/authme/command/help/HelpPrinter.java deleted file mode 100644 index a4426cb4..00000000 --- a/src/main/java/fr/xephi/authme/command/help/HelpPrinter.java +++ /dev/null @@ -1,194 +0,0 @@ -package fr.xephi.authme.command.help; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandArgumentDescription; -import fr.xephi.authme.command.CommandDescription; -import fr.xephi.authme.command.CommandParts; -import fr.xephi.authme.command.CommandPermissions; -import fr.xephi.authme.permission.PermissionNode; -import fr.xephi.authme.util.CollectionUtils; -import fr.xephi.authme.util.StringUtils; - -/** - */ -public class HelpPrinter { - - /** - * Print the command help information. - * - * @param sender The command sender to print the help to. - * @param command The command to print. - * @param commandReference The command reference used. - */ - public static void printCommand(CommandSender sender, CommandDescription command, CommandParts commandReference) { - // Print the proper command syntax - sender.sendMessage(ChatColor.GOLD + "Command: " + HelpSyntaxHelper.getCommandSyntax(command, commandReference, null, true)); - } - - /** - * Print the command help description information. This will print both the short, as the detailed description if available. - * - * @param sender The command sender to print the help to. - * @param command The command to print the description help for. - */ - public static void printCommandDescription(CommandSender sender, CommandDescription command) { - sender.sendMessage(ChatColor.GOLD + "Short Description: " + ChatColor.WHITE + command.getDescription()); - - // Print the detailed description, if available - if (!StringUtils.isEmpty(command.getDetailedDescription())) { - sender.sendMessage(ChatColor.GOLD + "Detailed Description:"); - sender.sendMessage(ChatColor.WHITE + " " + command.getDetailedDescription()); - } - } - - /** - * Print the command help arguments information if available. - * - * @param sender The command sender to print the help to. - * @param command The command to print the argument help for. - */ - @SuppressWarnings("StringConcatenationInsideStringBufferAppend") - public static void printArguments(CommandSender sender, CommandDescription command) { - // Make sure there are any commands to print - if (!command.hasArguments()) - return; - - // Print the header - sender.sendMessage(ChatColor.GOLD + "Arguments:"); - - // Print each argument - for (CommandArgumentDescription arg : command.getArguments()) { - // Create a string builder to build the syntax in - StringBuilder argString = new StringBuilder(); - argString.append(" " + ChatColor.YELLOW + ChatColor.ITALIC + arg.getLabel() + " : " + ChatColor.WHITE + arg.getDescription()); - - // Suffix a note if the command is optional - if (arg.isOptional()) - argString.append(ChatColor.GRAY + "" + ChatColor.ITALIC + " (Optional)"); - - // Print the syntax - sender.sendMessage(argString.toString()); - } - } - - /** - * Print the command help permissions information if available. - * - * @param sender The command sender to print the help to. - * @param command The command to print the permissions help for. - */ - public static void printPermissions(CommandSender sender, CommandDescription command) { - // Get the permissions and make sure they aren't missing - CommandPermissions permissions = command.getCommandPermissions(); - if (permissions == null || CollectionUtils.isEmpty(permissions.getPermissionNodes())) { - return; - } - - // Print the header - sender.sendMessage(ChatColor.GOLD + "Permissions:"); - - // Print each node - for (PermissionNode node : permissions.getPermissionNodes()) { - boolean nodePermission = true; - if (sender instanceof Player) - nodePermission = AuthMe.getInstance().getPermissionsManager().hasPermission((Player) sender, node); - final String nodePermsString = ChatColor.GRAY + (nodePermission ? ChatColor.ITALIC + " (Permission!)" : ChatColor.ITALIC + " (No Permission!)"); - sender.sendMessage(" " + ChatColor.YELLOW + ChatColor.ITALIC + node.getNode() + nodePermsString); - } - - // Print the default permission - // TODO ljacqu 20151205: This is duplicating the logic in PermissionsManager#evaluateDefaultPermission - // Either use the command manager here, or if that's too heavy, look into moving certain permissions logic - // into a Utils class - switch (permissions.getDefaultPermission()) { - case ALLOWED: - sender.sendMessage(ChatColor.GOLD + " Default: " + ChatColor.GRAY + ChatColor.ITALIC + "Permission!"); - break; - - case OP_ONLY: - final String defaultPermsString = ChatColor.GRAY + (sender.isOp() ? ChatColor.ITALIC + " (Permission!)" : ChatColor.ITALIC + " (No Permission!)"); - sender.sendMessage(ChatColor.GOLD + " Default: " + ChatColor.YELLOW + ChatColor.ITALIC + "OP's Only!" + defaultPermsString); - break; - - case NOT_ALLOWED: - default: - sender.sendMessage(ChatColor.GOLD + " Default: " + ChatColor.GRAY + ChatColor.ITALIC + "No Permission!"); - break; - } - - // Print the permission result - if (permissions.hasPermission(sender)) - sender.sendMessage(ChatColor.GOLD + " Result: " + ChatColor.GREEN + ChatColor.ITALIC + "Permission!"); - else - sender.sendMessage(ChatColor.GOLD + " Result: " + ChatColor.DARK_RED + ChatColor.ITALIC + "No Permission!"); - } - - /** - * Print the command help alternatives information if available. - * - * @param sender The command sender to print the help to. - * @param command The command used. - * @param commandReference The original command reference used for this command. - */ - public static void printAlternatives(CommandSender sender, CommandDescription command, CommandParts commandReference) { - // Make sure there are any alternatives - if (command.getLabels().size() <= 1) - return; - - // Print the header - sender.sendMessage(ChatColor.GOLD + "Alternatives:"); - - // Get the label used - final String usedLabel = commandReference.get(command.getParentCount()); - - // Create a list of alternatives - List alternatives = new ArrayList<>(); - for (String entry : command.getLabels()) { - // Exclude the proper argument - if (entry.equalsIgnoreCase(usedLabel)) - continue; - alternatives.add(entry); - } - - // Sort the alternatives - Collections.sort(alternatives, new Comparator() { - @Override - public int compare(String o1, String o2) { - return Double.compare(StringUtils.getDifference(usedLabel, o1), StringUtils.getDifference(usedLabel, o2)); - } - }); - - // Print each alternative with proper syntax - for (String alternative : alternatives) - sender.sendMessage(" " + HelpSyntaxHelper.getCommandSyntax(command, commandReference, alternative, true)); - } - - /** - * Print the command help child's information if available. - * - * @param sender The command sender to print the help to. - * @param command The command to print the help for. - * @param commandReference The original command reference used for this command. - */ - public static void printChildren(CommandSender sender, CommandDescription command, CommandParts commandReference) { - // Make sure there are child's - if (command.getChildren().size() <= 0) - return; - - // Print the header - sender.sendMessage(ChatColor.GOLD + "Commands:"); - - // Loop through each child - for (CommandDescription child : command.getChildren()) - sender.sendMessage(" " + HelpSyntaxHelper.getCommandSyntax(child, commandReference, null, false) + ChatColor.GRAY + ChatColor.ITALIC + " : " + child.getDescription()); - } -} diff --git a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java index 7f088acf..37bbb9e5 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java @@ -1,12 +1,16 @@ package fr.xephi.authme.command.help; -import fr.xephi.authme.AuthMe; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableList; +import fr.xephi.authme.command.CommandArgumentDescription; import fr.xephi.authme.command.CommandDescription; -import fr.xephi.authme.command.CommandParts; +import fr.xephi.authme.command.CommandPermissions; import fr.xephi.authme.command.CommandUtils; import fr.xephi.authme.command.FoundCommandResult; +import fr.xephi.authme.permission.DefaultPermission; +import fr.xephi.authme.permission.PermissionNode; +import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.settings.Settings; - import fr.xephi.authme.util.CollectionUtils; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; @@ -14,120 +18,182 @@ import org.bukkit.command.CommandSender; import java.util.ArrayList; import java.util.List; +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; + /** + * Help syntax generator for AuthMe commands. */ -public class HelpProvider { +public final class HelpProvider { - /** - * Show help for a specific command. - * - * @param sender The command sender the help needs to be shown to. - * @param reference The command reference to the help command. - * @param helpQuery The query to show help for. - */ - public static void showHelp(CommandSender sender, CommandParts reference, CommandParts helpQuery) { - showHelp(sender, reference, helpQuery, true, true, true, true, true, true); + // --- Bit flags --- + /** Set to not show the command. */ + public static final int HIDE_COMMAND = 0x001; + /** Set to show the detailed description of a command. */ + public static final int SHOW_LONG_DESCRIPTION = 0x002; + /** Set to include the arguments the command takes. */ + public static final int SHOW_ARGUMENTS = 0x004; + /** Set to show the permissions required to execute the command. */ + public static final int SHOW_PERMISSIONS = 0x008; + /** Set to show alternative labels for the command. */ + public static final int SHOW_ALTERNATIVES = 0x010; + /** Set to show the child commands of the command. */ + public static final int SHOW_CHILDREN = 0x020; + + /** Shortcut for setting all options apart from {@link HelpProvider#HIDE_COMMAND}. */ + public static final int ALL_OPTIONS = ~HIDE_COMMAND; + + private HelpProvider() { } - /** - * Show help for a specific command. - * - * @param sender The command sender the help needs to be shown to. - * @param reference The command reference to the help command. - * @param helpQuery The query to show help for. - * @param showCommand True to show the command. - * @param showDescription True to show the command description, both the short and detailed description. - * @param showArguments True to show the command argument help. - * @param showPermissions True to show the command permission help. - * @param showAlternatives True to show the command alternatives. - * @param showCommands True to show the child commands. - */ - public static void showHelp(CommandSender sender, CommandParts reference, CommandParts helpQuery, boolean showCommand, boolean showDescription, boolean showArguments, boolean showPermissions, boolean showAlternatives, boolean showCommands) { - // Find the command for this help query, one with and one without a prefixed base command - FoundCommandResult result = AuthMe.getInstance().getCommandHandler().findCommand(new CommandParts(helpQuery.getList())); + public static List printHelp(FoundCommandResult foundCommand, int options) { + return printHelp(foundCommand, null, null, options); + } - // TODO ljacqu 20151204 Fix me to nicer code - List parts = new ArrayList<>(helpQuery.getList()); - parts.add(0, reference.get(0)); - CommandParts commandReferenceOther = new CommandParts(parts); - - FoundCommandResult resultOther = AuthMe.getInstance().getCommandHandler().findCommand(commandReferenceOther); - if (resultOther != null) { - if (result == null) - result = resultOther; - - else if (result.getDifference() > resultOther.getDifference()) - result = resultOther; + // sender and permissions manager may be null if SHOW_PERMISSIONS is not set + public static List printHelp(FoundCommandResult foundCommand, CommandSender sender, + PermissionsManager permissionsManager, int options) { + if (foundCommand.getCommandDescription() == null) { + return singletonList(ChatColor.DARK_RED + "Failed to retrieve any help information!"); } - // Make sure a result was found - if (result == null) { - // Show a warning message - sender.sendMessage(ChatColor.DARK_RED + "" + ChatColor.ITALIC + helpQuery); - sender.sendMessage(ChatColor.DARK_RED + "Couldn't show any help information for this help query."); + List lines = new ArrayList<>(); + lines.add(ChatColor.GOLD + "==========[ " + Settings.helpHeader + " HELP ]=========="); + + CommandDescription command = foundCommand.getCommandDescription(); + List labels = ImmutableList.copyOf(foundCommand.getLabels()); + List correctLabels = ImmutableList.copyOf(filterCorrectLabels(command, labels)); + + if (!hasFlag(HIDE_COMMAND, options)) { + lines.add(ChatColor.GOLD + "Command: " + CommandSyntaxHelper.getSyntax(command, correctLabels)); + } + if (hasFlag(SHOW_LONG_DESCRIPTION, options)) { + printDetailedDescription(command, lines); + } + if (hasFlag(SHOW_ARGUMENTS, options)) { + printArguments(command, lines); + } + if (hasFlag(SHOW_PERMISSIONS, options) && sender != null && permissionsManager != null) { + printPermissions(command, sender, permissionsManager, lines); + } + if (hasFlag(SHOW_ALTERNATIVES, options)) { + printAlternatives(command, correctLabels, lines); + } + if (hasFlag(SHOW_CHILDREN, options)) { + printChildren(command, labels, lines); + } + + return lines; + } + + private static void printDetailedDescription(CommandDescription command, List lines) { + lines.add(ChatColor.GOLD + "Short Description: " + ChatColor.WHITE + command.getDescription()); + lines.add(ChatColor.GOLD + "Detailed Description:"); + lines.add(ChatColor.WHITE + " " + command.getDetailedDescription()); + } + + private static void printArguments(CommandDescription command, List lines) { + if (command.getArguments().isEmpty()) { return; } - // Get the command description, and make sure it's valid - CommandDescription command = result.getCommandDescription(); - if (command == null) { - // Show a warning message - sender.sendMessage(ChatColor.DARK_RED + "Failed to retrieve any help information!"); - return; - } + lines.add(ChatColor.GOLD + "Arguments:"); + for (CommandArgumentDescription argument : command.getArguments()) { + StringBuilder argString = new StringBuilder(); + argString.append(" ").append(ChatColor.YELLOW).append(ChatColor.ITALIC).append(argument.getName()) + .append(": ").append(ChatColor.WHITE).append(argument.getDescription()); - // Get the proper command reference to use for the help page - CommandParts commandReference = command.getCommandReference(result.getQueryReference()); - - // Get the base command - String baseCommand = commandReference.get(0); - - // Make sure the difference between the command reference and the actual command isn't too big - final double commandDifference = result.getDifference(); - if (commandDifference > 0.20) { - // Show the unknown command warning - sender.sendMessage(ChatColor.DARK_RED + "No help found for '" + helpQuery + "'!"); - - // Show a command suggestion if available and the difference isn't too big - if (commandDifference < 0.75 && result.getCommandDescription() != null) { - // Get the suggested command - List suggestedCommandParts = CollectionUtils.getRange( - result.getCommandDescription().getCommandReference(commandReference).getList(), 1); - sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD + "/" + baseCommand - + " help " + CommandUtils.labelsToString(suggestedCommandParts) + ChatColor.YELLOW + "?"); + if (argument.isOptional()) { + argString.append(ChatColor.GRAY).append(ChatColor.ITALIC).append(" (Optional)"); } + lines.add(argString.toString()); + } + } - // Show the help command - sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + baseCommand + " help" + ChatColor.YELLOW + " to view help."); + private static void printAlternatives(CommandDescription command, List correctLabels, List lines) { + // TODO ljacqu 20151219: Need to show alternatives for base labels too? E.g. /r for /register + if (command.getLabels().size() <= 1) { return; } - // Show a message when the command handler is assuming a command - if (commandDifference > 0) { - // Get the suggested command - List suggestedCommandParts = CollectionUtils.getRange( - result.getCommandDescription().getCommandReference(commandReference).getList(), 1); + lines.add(ChatColor.GOLD + "Alternatives:"); + // Get the label used + final String parentLabel = correctLabels.get(0); + final String childLabel = correctLabels.get(1); - // Show the suggested command - sender.sendMessage(ChatColor.DARK_RED + "No help found, assuming '" + ChatColor.GOLD - + CommandUtils.labelsToString(suggestedCommandParts) + ChatColor.DARK_RED + "'!"); + // Create a list of alternatives + for (String entry : command.getLabels()) { + if (!entry.equalsIgnoreCase(childLabel)) { + lines.add(" " + CommandSyntaxHelper.getSyntax(command, asList(parentLabel, entry))); + } + } + } + + private static void printPermissions(CommandDescription command, CommandSender sender, + PermissionsManager permissionsManager, List lines) { + CommandPermissions permissions = command.getCommandPermissions(); + if (permissions == null || CollectionUtils.isEmpty(permissions.getPermissionNodes())) { + return; + } + lines.add(ChatColor.GOLD + "Permissions:"); + + for (PermissionNode node : permissions.getPermissionNodes()) { + boolean hasPermission = permissionsManager.hasPermission(sender, node); + final String nodePermsString = "" + ChatColor.GRAY + ChatColor.ITALIC + + (hasPermission ? " (You have permission)" : " (No permission)"); + lines.add(" " + ChatColor.YELLOW + ChatColor.ITALIC + node.getNode() + nodePermsString); } - // Print the help header - sender.sendMessage(ChatColor.GOLD + "==========[ " + Settings.helpHeader.toUpperCase() + " HELP ]=========="); + // Addendum to the line to specify whether the sender has permission or not when default is OP_ONLY + final DefaultPermission defaultPermission = permissions.getDefaultPermission(); + String addendum = ""; + if (DefaultPermission.OP_ONLY.equals(defaultPermission)) { + addendum = PermissionsManager.evaluateDefaultPermission(defaultPermission, sender) + ? " (You have permission)" + : " (No permission)"; + } + lines.add(ChatColor.GOLD + "Default: " + ChatColor.GRAY + ChatColor.ITALIC + + defaultPermission.getTitle() + addendum); - // Print the command help information - if (showCommand) - HelpPrinter.printCommand(sender, command, commandReference); - if (showDescription) - HelpPrinter.printCommandDescription(sender, command); - if (showArguments) - HelpPrinter.printArguments(sender, command); - if (showPermissions) - HelpPrinter.printPermissions(sender, command); - if (showAlternatives) - HelpPrinter.printAlternatives(sender, command, commandReference); - if (showCommands) - HelpPrinter.printChildren(sender, command, commandReference); + // Evaluate if the sender has permission to the command + if (permissionsManager.hasPermission(sender, command)) { + lines.add(ChatColor.GOLD + " Result: " + ChatColor.GREEN + ChatColor.ITALIC + "You have permission"); + } else { + lines.add(ChatColor.GOLD + " Result: " + ChatColor.DARK_RED + ChatColor.ITALIC + "No permission"); + } } + + private static void printChildren(CommandDescription command, List parentLabels, List lines) { + if (command.getChildren().isEmpty()) { + return; + } + + lines.add(ChatColor.GOLD + "Commands:"); + String parentCommandPath = CommandUtils.labelsToString(parentLabels); + for (CommandDescription child : command.getChildren()) { + lines.add(" /" + parentCommandPath + " " + child.getLabels().get(0) + + ChatColor.GRAY + ChatColor.ITALIC + ": " + child.getDescription()); + } + } + + private static boolean hasFlag(int flag, int options) { + return (flag & options) != 0; + } + + @VisibleForTesting + protected static List filterCorrectLabels(CommandDescription command, List labels) { + List commands = CommandUtils.constructParentList(command); + List correctLabels = new ArrayList<>(); + boolean foundIncorrectLabel = false; + for (int i = 0; i < commands.size(); ++i) { + if (!foundIncorrectLabel && i < labels.size() && commands.get(i).hasLabel(labels.get(i))) { + correctLabels.add(labels.get(i)); + } else { + foundIncorrectLabel = true; + correctLabels.add(commands.get(i).getLabels().get(0)); + } + } + return correctLabels; + } + } diff --git a/src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java b/src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java deleted file mode 100644 index 5fa3f5e0..00000000 --- a/src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java +++ /dev/null @@ -1,76 +0,0 @@ -package fr.xephi.authme.command.help; - -import fr.xephi.authme.command.CommandArgumentDescription; -import fr.xephi.authme.command.CommandDescription; -import fr.xephi.authme.command.CommandParts; -import fr.xephi.authme.command.CommandUtils; -import fr.xephi.authme.util.CollectionUtils; -import fr.xephi.authme.util.StringUtils; -import org.bukkit.ChatColor; - -/** - * Helper class for formatting a command's structure (name and arguments) - * for a Minecraft user. - */ -public final class HelpSyntaxHelper { - - private HelpSyntaxHelper() { - // Helper class - } - - /** - * Get the formatted syntax for a command. - * - * @param commandDescription The command to build the syntax for. - * @param commandReference The reference of the command. - * @param alternativeLabel The alternative label to use for this command syntax. - * @param highlight True to highlight the important parts of this command. - * - * @return The command with proper syntax. - */ - public static String getCommandSyntax(CommandDescription commandDescription, CommandParts commandReference, - String alternativeLabel, boolean highlight) { - // Create a string builder with white color and prefixed slash - StringBuilder sb = new StringBuilder() - .append(ChatColor.WHITE) - .append("/"); - - // Get the help command reference, and the command label - CommandParts helpCommandReference = commandDescription.getCommandReference(commandReference); - final String parentCommand = CommandUtils.labelsToString( - CollectionUtils.getRange(helpCommandReference.getList(), 0, helpCommandReference.getCount() - 1)); - - // Check whether the alternative label should be used - String commandLabel; - if (StringUtils.isEmpty(alternativeLabel)) { - commandLabel = helpCommandReference.get(helpCommandReference.getCount() - 1); - } else { - commandLabel = alternativeLabel; - } - - // Show the important bit of the command, highlight this part if required - sb.append(parentCommand) - .append(" ") - .append(highlight ? ChatColor.YELLOW.toString() + ChatColor.BOLD : "") - .append(commandLabel); - - if (highlight) { - sb.append(ChatColor.YELLOW); - } - - // Add each command argument - for (CommandArgumentDescription arg : commandDescription.getArguments()) { - sb.append(ChatColor.ITALIC).append(formatArgument(arg)); - } - - // Return the build command syntax - return sb.toString(); - } - - private static String formatArgument(CommandArgumentDescription argument) { - if (argument.isOptional()) { - return " [" + argument.getLabel() + "]"; - } - return " <" + argument.getLabel() + ">"; - } -} diff --git a/src/main/java/fr/xephi/authme/permission/DefaultPermission.java b/src/main/java/fr/xephi/authme/permission/DefaultPermission.java index 09f0856a..f09de526 100644 --- a/src/main/java/fr/xephi/authme/permission/DefaultPermission.java +++ b/src/main/java/fr/xephi/authme/permission/DefaultPermission.java @@ -6,11 +6,28 @@ package fr.xephi.authme.permission; public enum DefaultPermission { /** No one can execute the command. */ - NOT_ALLOWED, + NOT_ALLOWED("No permission"), /** Only players with the OP status may execute the command. */ - OP_ONLY, + OP_ONLY("OP's only"), /** The command can be executed by anyone. */ - ALLOWED + ALLOWED("Everyone allowed"); + + /** Textual representation of the default permission. */ + private final String title; + + /** + * Constructor. + * @param title The textual representation + */ + DefaultPermission(String title) { + this.title = title; + } + + /** Return the textual representation. */ + public String getTitle() { + return title; + } + } diff --git a/src/main/java/fr/xephi/authme/permission/PermissionsManager.java b/src/main/java/fr/xephi/authme/permission/PermissionsManager.java index a70230c1..4bc7f464 100644 --- a/src/main/java/fr/xephi/authme/permission/PermissionsManager.java +++ b/src/main/java/fr/xephi/authme/permission/PermissionsManager.java @@ -280,19 +280,24 @@ public class PermissionsManager implements PermissionsService { /** - * Check if the player has permission for the given permissions node. If no permissions system is used, - * the player has to be OP in order to have the permission. + * Check if the command sender has permission for the given permissions node. If no permissions system is used or + * if the sender is not a player (e.g. console user), the player has to be OP in order to have the permission. * - * @param player The player. + * @param sender The command sender. * @param permissionNode The permissions node to verify. * - * @return True if the player has the permission, false otherwise. + * @return True if the sender has the permission, false otherwise. */ - public boolean hasPermission(Player player, PermissionNode permissionNode) { - return hasPermission(player, permissionNode, player.isOp()); + public boolean hasPermission(CommandSender sender, PermissionNode permissionNode) { + return hasPermission(sender, permissionNode, sender.isOp()); } - public boolean hasPermission(Player player, PermissionNode permissionNode, boolean def) { + public boolean hasPermission(CommandSender sender, PermissionNode permissionNode, boolean def) { + if (!(sender instanceof Player)) { + return def; + } + + Player player = (Player) sender; return hasPermission(player, permissionNode.getNode(), def) || hasPermission(player, permissionNode.getWildcardNode().getNode(), def); } @@ -306,15 +311,17 @@ public class PermissionsManager implements PermissionsService { return true; } - public boolean hasPermission(Player player, CommandDescription command) { + public boolean hasPermission(CommandSender sender, CommandDescription command) { if (command.getCommandPermissions() == null || CollectionUtils.isEmpty(command.getCommandPermissions().getPermissionNodes())) { return true; } DefaultPermission defaultPermission = command.getCommandPermissions().getDefaultPermission(); - boolean def = evaluateDefaultPermission(defaultPermission, player); - return hasPermission(player, command.getCommandPermissions().getPermissionNodes(), def); + boolean def = evaluateDefaultPermission(defaultPermission, sender); + return (sender instanceof Player) + ? hasPermission((Player) sender, command.getCommandPermissions().getPermissionNodes(), def) + : def; } public static boolean evaluateDefaultPermission(DefaultPermission defaultPermission, CommandSender sender) { diff --git a/src/main/java/fr/xephi/authme/permission/PermissionsService.java b/src/main/java/fr/xephi/authme/permission/PermissionsService.java index 4c630c56..82f24ea0 100644 --- a/src/main/java/fr/xephi/authme/permission/PermissionsService.java +++ b/src/main/java/fr/xephi/authme/permission/PermissionsService.java @@ -1,6 +1,7 @@ package fr.xephi.authme.permission; import fr.xephi.authme.command.CommandDescription; +import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; /** @@ -11,23 +12,23 @@ public interface PermissionsService { /** * Check if the player has the given permission. * - * @param player The player + * @param sender The command sender * @param permission The permission node to check * @param def Default returned if no permissions system is used * * @return True if the player has permission */ - boolean hasPermission(Player player, PermissionNode permission, boolean def); + boolean hasPermission(CommandSender sender, PermissionNode permission, boolean def); /** * Check if the player has the permissions for the given command. * - * @param player The player + * @param sender The command sender * @param command The command whose permissions should be checked * * @return True if the player may execute the command */ - boolean hasPermission(Player player, CommandDescription command); + boolean hasPermission(CommandSender sender, CommandDescription command); /** * Return the permission system the service is working with. diff --git a/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java b/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java index 02e65f50..b333b164 100644 --- a/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java +++ b/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java @@ -1,27 +1,33 @@ package fr.xephi.authme.command; +import fr.xephi.authme.command.executable.HelpCommand; import fr.xephi.authme.permission.DefaultPermission; +import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PlayerPermission; -import fr.xephi.authme.util.WrapperMock; import org.bukkit.command.CommandSender; +import org.junit.Before; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; +import java.util.Arrays; import java.util.Collection; -import java.util.HashSet; import java.util.List; import java.util.Set; +import static com.google.common.collect.Sets.newHashSet; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.stringContainsInOrder; import static org.mockito.BDDMockito.given; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyListOf; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; @@ -35,70 +41,316 @@ public class CommandHandlerTest { private static Set commands; private static CommandHandler handler; + private static PermissionsManager permissionsManagerMock; @BeforeClass public static void setUpCommandHandler() { - WrapperMock.createInstance(); - + // Register /authme CommandDescription authMeBase = createCommand(null, null, singletonList("authme")); + // Register /authme login createCommand(PlayerPermission.LOGIN, authMeBase, singletonList("login"), newArgument("password", false)); + // Register /authme register , alias: /authme reg createCommand(PlayerPermission.LOGIN, authMeBase, asList("register", "reg"), newArgument("password", false), newArgument("confirmation", false)); - CommandDescription testBase = createCommand(null, null, singletonList("test"), newArgument("test", true)); - commands = new HashSet<>(asList(authMeBase, testBase)); - handler = new CommandHandler(commands); + // Register /email [player] + CommandDescription emailBase = createCommand(null, null, singletonList("email")); + // Register /email helptest -- use only to test for help command arguments special case + CommandDescription.builder().parent(emailBase).labels("helptest").executableCommand(mock(HelpCommand.class)) + .description("test").detailedDescription("Test.").withArgument("Query", "", false).build(); + + // Register /unregister , alias: /unreg + CommandDescription unregisterBase = createCommand(null, null, asList("unregister", "unreg"), + newArgument("player", false)); + + commands = newHashSet(authMeBase, emailBase, unregisterBase); } + @Before + public void setUpMocks() { + permissionsManagerMock = mock(PermissionsManager.class); + handler = new CommandHandler(commands, permissionsManagerMock); + } + + // ----------- + // mapPartsToCommand() tests + // ----------- @Test - @Ignore - public void shouldForwardCommandToExecutable() { + public void shouldMapPartsToLoginChildCommand() { // given - CommandSender sender = Mockito.mock(CommandSender.class); - given(sender.isOp()).willReturn(true); - String bukkitLabel = "authme"; - String[] args = {"login", "password"}; + List parts = Arrays.asList("authme", "login", "test1"); // when - handler.processCommand(sender, bukkitLabel, args); + FoundCommandResult result = handler.mapPartsToCommand(parts); // then - final CommandDescription loginCmd = getChildWithLabel("login", getCommandWithLabel("authme", commands)); - verify(sender, never()).sendMessage(anyString()); - verify(loginCmd.getExecutableCommand()).executeCommand( - eq(sender), any(CommandParts.class), any(CommandParts.class)); + assertThat(result.getCommandDescription(), equalTo(getChildWithLabel("login", "authme"))); + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.SUCCESS)); + assertThat(result.getArguments(), contains("test1")); + assertThat(result.getDifference(), equalTo(0.0)); + assertThat(result.getLabels(), equalTo(parts.subList(0, 2))); + assertThat(result.getArguments(), contains(parts.get(2))); + } + + @Test + public void shouldMapPartsToCommandWithNoCaseSensitivity() { + // given + List parts = Arrays.asList("Authme", "REG", "arg1", "arg2"); + + // when + FoundCommandResult result = handler.mapPartsToCommand(parts); + + // then + assertThat(result.getCommandDescription(), equalTo(getChildWithLabel("register", "authme"))); + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.SUCCESS)); + assertThat(result.getLabels(), equalTo(parts.subList(0, 2))); + assertThat(result.getArguments(), contains("arg1", "arg2")); + assertThat(result.getDifference(), equalTo(0.0)); } @Test - @Ignore // TODO ljacqu Fix test --> command classes too tightly coupled at the moment public void shouldRejectCommandWithTooManyArguments() { // given - CommandSender sender = Mockito.mock(CommandSender.class); - given(sender.isOp()).willReturn(true); - String bukkitLabel = "authme"; - String[] args = {"login", "password", "__unneededArgument__"}; + List parts = Arrays.asList("authme", "register", "pass123", "pass123", "pass123"); // when - boolean result = handler.processCommand(sender, bukkitLabel, args); + FoundCommandResult result = handler.mapPartsToCommand(parts); // then - assertThat(result, equalTo(true)); - assertSenderGotMessageContaining("help", sender); + assertThat(result.getCommandDescription(), equalTo(getChildWithLabel("register", "authme"))); + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.INCORRECT_ARGUMENTS)); + assertThat(result.getDifference(), equalTo(0.0)); + assertThat(result.getLabels(), equalTo(parts.subList(0, 2))); + assertThat(result.getArguments(), equalTo(parts.subList(2, 5))); } + @Test + public void shouldRejectCommandWithTooFewArguments() { + // given + List parts = Arrays.asList("authme", "Reg"); + + // when + FoundCommandResult result = handler.mapPartsToCommand(parts); + + // then + assertThat(result.getCommandDescription(), equalTo(getChildWithLabel("register", "authme"))); + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.INCORRECT_ARGUMENTS)); + assertThat(result.getDifference(), equalTo(0.0)); + assertThat(result.getLabels(), equalTo(parts)); + assertThat(result.getArguments(), empty()); + } + + @Test + public void shouldSuggestCommandWithSimilarLabel() { + // given + List parts = Arrays.asList("authme", "reh", "pass123", "pass123"); + + // when + FoundCommandResult result = handler.mapPartsToCommand(parts); + + // then + assertThat(result.getCommandDescription(), equalTo(getChildWithLabel("register", "authme"))); + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.UNKNOWN_LABEL)); + assertThat(result.getDifference() < 0.75, equalTo(true)); + assertThat(result.getLabels(), equalTo(parts.subList(0, 2))); + assertThat(result.getArguments(), contains("pass123", "pass123")); + } + + /** In contrast to the previous test, we test a command request with a very apart label. */ + @Test + public void shouldSuggestMostSimilarCommand() { + // given + List parts = Arrays.asList("authme", "asdfawetawty4asdca"); + + // when + FoundCommandResult result = handler.mapPartsToCommand(parts); + + // then + assertThat(result.getCommandDescription(), not(nullValue())); + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.UNKNOWN_LABEL)); + assertThat(result.getDifference() > 0.75, equalTo(true)); + assertThat(result.getLabels(), equalTo(parts)); + assertThat(result.getArguments(), empty()); + } + + @Test + public void shouldHandleBaseWithWrongArguments() { + // given + List parts = singletonList("unregister"); + + // when + FoundCommandResult result = handler.mapPartsToCommand(parts); + + // then + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.INCORRECT_ARGUMENTS)); + assertThat(result.getCommandDescription(), equalTo(getCommandWithLabel("unregister", commands))); + assertThat(result.getDifference(), equalTo(0.0)); + assertThat(result.getArguments(), empty()); + assertThat(result.getLabels(), equalTo(parts)); + } + + @Test + public void shouldHandleUnknownBase() { + // given + List parts = asList("bogus", "label1", "arg1"); + + // when + FoundCommandResult result = handler.mapPartsToCommand(parts); + + // then + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.MISSING_BASE_COMMAND)); + assertThat(result.getCommandDescription(), nullValue()); + } + + @Test + public void shouldHandleNullInput() { + // given / when + FoundCommandResult result = handler.mapPartsToCommand(null); + + // then + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.MISSING_BASE_COMMAND)); + assertThat(result.getCommandDescription(), nullValue()); + } + + @Test + public void shouldMapToBaseWithProperArguments() { + // given + List parts = asList("Unreg", "player1"); + + // when + FoundCommandResult result = handler.mapPartsToCommand(parts); + + // then + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.SUCCESS)); + assertThat(result.getCommandDescription(), equalTo(getCommandWithLabel("unregister", commands))); + assertThat(result.getDifference(), equalTo(0.0)); + assertThat(result.getArguments(), contains("player1")); + assertThat(result.getLabels(), contains("Unreg")); + } + + @Test + public void shouldReturnChildlessBaseCommandWithArgCountError() { + // given + List parts = asList("unregistER", "player1", "wrongArg"); + + // when + FoundCommandResult result = handler.mapPartsToCommand(parts); + + // then + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.INCORRECT_ARGUMENTS)); + assertThat(result.getCommandDescription(), equalTo(getCommandWithLabel("unregister", commands))); + assertThat(result.getDifference(), equalTo(0.0)); + assertThat(result.getArguments(), contains("player1", "wrongArg")); + assertThat(result.getLabels(), contains("unregistER")); + } + + // ---------- + // processCommand() tests + // ---------- + @Test + public void shouldCallMappedCommandWithArgs() { + // given + String bukkitLabel = "Authme"; + String[] bukkitArgs = {"Login", "myPass"}; + CommandSender sender = mock(CommandSender.class); + + CommandDescription command = getChildWithLabel("login", "authme"); + given(permissionsManagerMock.hasPermission(sender, command)).willReturn(true); + + // when + handler.processCommand(sender, bukkitLabel, bukkitArgs); + + // then + ArgumentCaptor argsCaptor = ArgumentCaptor.forClass(List.class); + verify(command.getExecutableCommand()).executeCommand(eq(sender), argsCaptor.capture()); + List argument = argsCaptor.getValue(); + assertThat(argument, contains("myPass")); + // Ensure that no error message was issued to the command sender + verify(sender, never()).sendMessage(anyString()); + } + + @Test + public void shouldNotCallExecutableCommandIfNoPermission() { + // given + String bukkitLabel = "unreg"; + String[] bukkitArgs = {"testPlayer"}; + CommandSender sender = mock(CommandSender.class); + given(permissionsManagerMock.hasPermission(any(CommandSender.class), any(CommandDescription.class))) + .willReturn(false); + + // when + handler.processCommand(sender, bukkitLabel, bukkitArgs); + + // then + CommandDescription command = getCommandWithLabel("unregister", commands); + verify(permissionsManagerMock).hasPermission(sender, command); + verify(command.getExecutableCommand(), never()) + .executeCommand(any(CommandSender.class), anyListOf(String.class)); + + ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(String.class); + verify(sender).sendMessage(messageCaptor.capture()); + String message = messageCaptor.getValue(); + assertThat(message, stringContainsInOrder("You don't have permission")); + } + + @Test + public void shouldStripWhitespace() { + // given + String bukkitLabel = "AuthMe"; + String[] bukkitArgs = {" ", "", "LOGIN", " ", "testArg", " "}; + CommandSender sender = mock(CommandSender.class); + + CommandDescription command = getChildWithLabel("login", "authme"); + given(permissionsManagerMock.hasPermission(sender, command)).willReturn(true); + + // when + handler.processCommand(sender, bukkitLabel, bukkitArgs); + + // then + ArgumentCaptor argsCaptor = ArgumentCaptor.forClass(List.class); + verify(command.getExecutableCommand()).executeCommand(eq(sender), argsCaptor.capture()); + List arguments = argsCaptor.getValue(); + assertThat(arguments, contains("testArg")); + verify(sender, never()).sendMessage(anyString()); + } + + @Test + public void shouldPassCommandPathAsArgumentsToHelpCommand() { + // given + String bukkitLabel = "email"; + String[] bukkitArgs = {"helptest", "arg1"}; + CommandSender sender = mock(CommandSender.class); + + CommandDescription command = getChildWithLabel("helptest", "email"); + given(permissionsManagerMock.hasPermission(sender, command)).willReturn(true); + + // when + handler.processCommand(sender, bukkitLabel, bukkitArgs); + + // then + ArgumentCaptor argsCaptor = ArgumentCaptor.forClass(List.class); + verify(command.getExecutableCommand()).executeCommand(eq(sender), argsCaptor.capture()); + List arguments = argsCaptor.getValue(); + assertThat(arguments, contains("email", "arg1")); + } + + + // ---------- + // Helper methods + // ---------- private static CommandDescription createCommand(PlayerPermission permission, CommandDescription parent, List labels, CommandArgumentDescription... arguments) { CommandDescription.CommandBuilder command = CommandDescription.builder() .labels(labels) .parent(parent) .permissions(DefaultPermission.OP_ONLY, permission) - .description("Test") - .detailedDescription("Test command") + .description(labels.get(0)) + .detailedDescription("'" + labels.get(0) + "' test command") .executableCommand(mock(ExecutableCommand.class)); if (arguments != null && arguments.length > 0) { for (CommandArgumentDescription argument : arguments) { - command.withArgument(argument.getLabel(), "Test description", argument.isOptional()); + command.withArgument(argument.getName(), "Test description", argument.isOptional()); } } @@ -109,27 +361,17 @@ public class CommandHandlerTest { return new CommandArgumentDescription(label, "Test description", isOptional); } - private void assertSenderGotMessageContaining(String text, CommandSender sender) { - ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - verify(sender).sendMessage(captor.capture()); - assertThat(captor.getValue(), stringContainsInOrder(text)); + private static CommandDescription getChildWithLabel(String childLabel, String parentLabel) { + CommandDescription parent = getCommandWithLabel(parentLabel, commands); + return getCommandWithLabel(childLabel, parent.getChildren()); } private static CommandDescription getCommandWithLabel(String label, Collection commands) { - for (CommandDescription command : commands) { - if (command.getLabels().contains(label)) { - return command; - } - } - return null; - } - - private static CommandDescription getChildWithLabel(String label, CommandDescription command) { - for (CommandDescription child : command.getChildren()) { - if (child.getLabels().contains(label)) { + for (CommandDescription child : commands) { + if (child.hasLabel(label)) { return child; } } - return null; + throw new RuntimeException("Could not find command with label '" + label + "'"); } } diff --git a/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java b/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java index 821e2c83..3df6cd13 100644 --- a/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java +++ b/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java @@ -77,7 +77,7 @@ public class CommandInitializerTest { BiConsumer connectionTester = new BiConsumer() { @Override public void accept(CommandDescription command, int depth) { - if (command.hasChildren()) { + if (!command.getChildren().isEmpty()) { for (CommandDescription child : command.getChildren()) { assertThat(command.equals(child.getParent()), equalTo(true)); } @@ -223,7 +223,7 @@ public class CommandInitializerTest { public void accept(CommandDescription command, int depth) { // Fail if the command has children and has arguments at the same time // Exception: If the parent only has one child defining the help label, it is acceptable - if (command.hasChildren() && command.hasArguments() + if (!command.getChildren().isEmpty() && !command.getArguments().isEmpty() && (command.getChildren().size() != 1 || !command.getChildren().get(0).hasLabel("help"))) { fail("Parent command (labels='" + command.getLabels() + "') should not have any arguments"); } @@ -317,7 +317,7 @@ public class CommandInitializerTest { private static void walkThroughCommands(Collection commands, BiConsumer consumer, int depth) { for (CommandDescription command : commands) { consumer.accept(command, depth); - if (command.hasChildren()) { + if (!command.getChildren().isEmpty()) { walkThroughCommands(command.getChildren(), consumer, depth + 1); } } diff --git a/src/test/java/fr/xephi/authme/command/CommandPartsTest.java b/src/test/java/fr/xephi/authme/command/CommandPartsTest.java deleted file mode 100644 index 163f52d4..00000000 --- a/src/test/java/fr/xephi/authme/command/CommandPartsTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package fr.xephi.authme.command; - -import org.junit.Test; - -import java.util.Arrays; -import java.util.Collections; - -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; - -/** - * Test for {@link CommandParts}. - */ -public class CommandPartsTest { - - @Test - public void shouldPrintPartsForStringRepresentation() { - // given - CommandParts parts = new CommandParts(Arrays.asList("some", "parts", "for", "test")); - - // when - String str = parts.toString(); - - // then - assertThat(str, equalTo("some parts for test")); - } - - @Test - public void shouldPrintEmptyStringForNoArguments() { - // given - CommandParts parts = new CommandParts(Collections.EMPTY_LIST); - - // when - String str = parts.toString(); - - // then - assertThat(str, equalTo("")); - } -} diff --git a/src/test/java/fr/xephi/authme/command/CommandUtilsTest.java b/src/test/java/fr/xephi/authme/command/CommandUtilsTest.java index 14dc8f7f..0f4dff18 100644 --- a/src/test/java/fr/xephi/authme/command/CommandUtilsTest.java +++ b/src/test/java/fr/xephi/authme/command/CommandUtilsTest.java @@ -3,6 +3,7 @@ package fr.xephi.authme.command; import org.junit.Test; import java.util.Arrays; +import java.util.Collections; import java.util.List; import static org.hamcrest.Matchers.equalTo; @@ -14,6 +15,30 @@ import static org.mockito.Mockito.mock; */ public class CommandUtilsTest { + @Test + public void shouldPrintPartsForStringRepresentation() { + // given + Iterable parts = Arrays.asList("some", "parts", "for", "test"); + + // when + String str = CommandUtils.labelsToString(parts); + + // then + assertThat(str, equalTo("some parts for test")); + } + + @Test + public void shouldPrintEmptyStringForNoArguments() { + // given + List parts = Collections.EMPTY_LIST; + + // when + String str = CommandUtils.labelsToString(parts); + + // then + assertThat(str, equalTo("")); + } + @Test public void shouldPrintLabels() { // given diff --git a/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java index 6b183e35..d076fd03 100644 --- a/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command.executable.captcha; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; @@ -15,7 +14,7 @@ import org.junit.Ignore; import org.junit.Test; import org.mockito.Mockito; -import java.util.Collections; +import java.util.ArrayList; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; @@ -42,10 +41,9 @@ public class CaptchaCommandTest { ExecutableCommand command = new CaptchaCommand(); // when - boolean result = command.executeCommand(sender, new CommandParts(Collections.EMPTY_LIST), new CommandParts(Collections.EMPTY_LIST)); + command.executeCommand(sender, new ArrayList()); // then - assertThat(result, equalTo(true)); assertThat(wrapperMock.wasMockCalled(AuthMe.class), equalTo(false)); assertThat(wrapperMock.wasMockCalled(Messages.class), equalTo(false)); } @@ -58,10 +56,9 @@ public class CaptchaCommandTest { ExecutableCommand command = new CaptchaCommand(); // when - boolean result = command.executeCommand(player, new CommandParts(Collections.EMPTY_LIST), new CommandParts(Collections.EMPTY_LIST)); + command.executeCommand(player, new ArrayList()); // then - assertThat(result, equalTo(true)); verify(wrapperMock.getMessages()).send(player, MessageKey.USAGE_LOGIN); } diff --git a/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java index 5c9c295c..a55ffeb3 100644 --- a/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java @@ -3,7 +3,6 @@ package fr.xephi.authme.command.executable.changepassword; import fr.xephi.authme.AuthMe; import fr.xephi.authme.ReflectionTestUtils; import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; import fr.xephi.authme.settings.Settings; @@ -17,14 +16,19 @@ import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import static java.util.Arrays.asList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; /** * Test for {@link ChangePasswordCommand}. @@ -53,13 +57,11 @@ public class ChangePasswordCommandTest { // given CommandSender sender = mock(BlockCommandSender.class); ChangePasswordCommand command = new ChangePasswordCommand(); - CommandParts arguments = mock(CommandParts.class); // when - command.executeCommand(sender, newParts(), arguments); + command.executeCommand(sender, new ArrayList()); // then - verify(arguments, never()).get(anyInt()); assertThat(wrapperMock.wasMockCalled(Server.class), equalTo(false)); } @@ -70,7 +72,7 @@ public class ChangePasswordCommandTest { ChangePasswordCommand command = new ChangePasswordCommand(); // when - command.executeCommand(sender, newParts(), new CommandParts("pass")); + command.executeCommand(sender, Arrays.asList("pass", "pass")); // then verify(messagesMock).send(sender, MessageKey.NOT_LOGGED_IN); @@ -84,7 +86,7 @@ public class ChangePasswordCommandTest { ChangePasswordCommand command = new ChangePasswordCommand(); // when - command.executeCommand(sender, newParts(), newParts("old123", "!pass")); + command.executeCommand(sender, Arrays.asList("old123", "!pass")); // then verify(messagesMock).send(sender, MessageKey.PASSWORD_MATCH_ERROR); @@ -99,7 +101,7 @@ public class ChangePasswordCommandTest { ChangePasswordCommand command = new ChangePasswordCommand(); // when - command.executeCommand(sender, newParts(), newParts("old_", "Tester")); + command.executeCommand(sender, Arrays.asList("old_", "Tester")); // then verify(messagesMock).send(sender, MessageKey.PASSWORD_IS_USERNAME_ERROR); @@ -114,7 +116,7 @@ public class ChangePasswordCommandTest { Settings.passwordMaxLength = 3; // when - command.executeCommand(sender, newParts(), newParts("12", "test")); + command.executeCommand(sender, Arrays.asList("12", "test")); // then verify(messagesMock).send(sender, MessageKey.INVALID_PASSWORD_LENGTH); @@ -129,7 +131,7 @@ public class ChangePasswordCommandTest { Settings.getPasswordMinLen = 7; // when - command.executeCommand(sender, newParts(), newParts("oldverylongpassword", "tester")); + command.executeCommand(sender, Arrays.asList("oldverylongpassword", "tester")); // then verify(messagesMock).send(sender, MessageKey.INVALID_PASSWORD_LENGTH); @@ -144,7 +146,7 @@ public class ChangePasswordCommandTest { Settings.unsafePasswords = asList("test", "abc123"); // when - command.executeCommand(sender, newParts(), newParts("oldpw", "abc123")); + command.executeCommand(sender, Arrays.asList("oldpw", "abc123")); // then verify(messagesMock).send(sender, MessageKey.PASSWORD_UNSAFE_ERROR); @@ -158,7 +160,7 @@ public class ChangePasswordCommandTest { ChangePasswordCommand command = new ChangePasswordCommand(); // when - command.executeCommand(sender, newParts(), newParts("abc123", "abc123")); + command.executeCommand(sender, Arrays.asList("abc123", "abc123")); // then verify(messagesMock, never()).send(eq(sender), any(MessageKey.class)); @@ -176,8 +178,4 @@ public class ChangePasswordCommandTest { return player; } - private static CommandParts newParts(String... parts) { - return new CommandParts(Arrays.asList(parts)); - } - } diff --git a/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java index d377fc0f..1a9c5a12 100644 --- a/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command.executable.email; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.process.Management; import fr.xephi.authme.util.WrapperMock; import org.bukkit.command.BlockCommandSender; @@ -41,7 +40,7 @@ public class AddEmailCommandTest { AddEmailCommand command = new AddEmailCommand(); // when - command.executeCommand(sender, newParts(), newParts()); + command.executeCommand(sender, new ArrayList()); // then verify(authMeMock, never()).getManagement(); @@ -54,15 +53,11 @@ public class AddEmailCommandTest { AddEmailCommand command = new AddEmailCommand(); // when - command.executeCommand(sender, newParts(), - new CommandParts(Arrays.asList("mail@example", "other_example"))); + command.executeCommand(sender, Arrays.asList("mail@example", "other_example")); // then verify(authMeMock).getManagement(); verify(managementMock).performAddEmail(sender, "mail@example", "other_example"); } - private static CommandParts newParts() { - return new CommandParts(new ArrayList()); - } } diff --git a/src/test/java/fr/xephi/authme/command/executable/email/ChangeEmailCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/email/ChangeEmailCommandTest.java index 2dc25c96..f4ecd4f8 100644 --- a/src/test/java/fr/xephi/authme/command/executable/email/ChangeEmailCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/email/ChangeEmailCommandTest.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command.executable.email; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.process.Management; import fr.xephi.authme.util.WrapperMock; import org.bukkit.command.BlockCommandSender; @@ -41,7 +40,7 @@ public class ChangeEmailCommandTest { ChangeEmailCommand command = new ChangeEmailCommand(); // when - command.executeCommand(sender, newParts(), newParts()); + command.executeCommand(sender, new ArrayList()); // then verify(authMeMock, never()).getManagement(); @@ -54,15 +53,11 @@ public class ChangeEmailCommandTest { ChangeEmailCommand command = new ChangeEmailCommand(); // when - command.executeCommand(sender, newParts(), - new CommandParts(Arrays.asList("new.mail@example.org", "old_mail@example.org"))); + command.executeCommand(sender, Arrays.asList("new.mail@example.org", "old_mail@example.org")); // then verify(authMeMock).getManagement(); verify(managementMock).performChangeEmail(sender, "new.mail@example.org", "old_mail@example.org"); } - private static CommandParts newParts() { - return new CommandParts(new ArrayList()); - } } diff --git a/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java index a1403c5a..eecfaa67 100644 --- a/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java @@ -1,6 +1,5 @@ package fr.xephi.authme.command.executable.email; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.util.WrapperMock; import org.bukkit.command.BlockCommandSender; import org.bukkit.command.CommandSender; @@ -9,7 +8,7 @@ import org.junit.Ignore; import org.junit.Test; import org.mockito.Mockito; -import java.util.Collections; +import java.util.ArrayList; /** * Test for {@link RecoverEmailCommand}. @@ -29,7 +28,7 @@ public class RecoverEmailCommandTest { RecoverEmailCommand command = new RecoverEmailCommand(); // when - command.executeCommand(sender, new CommandParts(Collections.EMPTY_LIST), new CommandParts(Collections.EMPTY_LIST)); + command.executeCommand(sender, new ArrayList()); // then } diff --git a/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java index 52a71891..27de64a8 100644 --- a/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java @@ -1,6 +1,5 @@ package fr.xephi.authme.command.executable.login; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.process.Management; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.util.WrapperMock; @@ -12,6 +11,7 @@ import org.junit.Test; import org.mockito.Mockito; import java.util.ArrayList; +import java.util.Collections; import static org.mockito.Matchers.*; import static org.mockito.Mockito.mock; @@ -40,7 +40,7 @@ public class LoginCommandTest { LoginCommand command = new LoginCommand(); // when - command.executeCommand(sender, newParts(), newParts()); + command.executeCommand(sender, new ArrayList()); // then Mockito.verify(managementMock, never()).performLogin(any(Player.class), anyString(), anyBoolean()); @@ -53,28 +53,10 @@ public class LoginCommandTest { LoginCommand command = new LoginCommand(); // when - command.executeCommand(sender, newParts(), new CommandParts("password")); + command.executeCommand(sender, Collections.singletonList("password")); // then Mockito.verify(managementMock).performLogin(eq(sender), eq("password"), eq(false)); } - @Test - public void shouldHandleMissingPassword() { - // given - Player sender = mock(Player.class); - LoginCommand command = new LoginCommand(); - - // when - command.executeCommand(sender, newParts(), newParts()); - - // then - // TODO ljacqu 20151121: May make sense to handle null password in LoginCommand instead of forwarding the call - String password = null; - Mockito.verify(managementMock).performLogin(eq(sender), eq(password), eq(false)); - } - - private static CommandParts newParts() { - return new CommandParts(new ArrayList()); - } } diff --git a/src/test/java/fr/xephi/authme/command/executable/logout/LogoutCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/logout/LogoutCommandTest.java index 65f24639..a5dce4d9 100644 --- a/src/test/java/fr/xephi/authme/command/executable/logout/LogoutCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/logout/LogoutCommandTest.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command.executable.logout; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.process.Management; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.util.WrapperMock; @@ -13,6 +12,7 @@ import org.junit.Test; import org.mockito.Mockito; import java.util.ArrayList; +import java.util.Collections; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; @@ -42,7 +42,7 @@ public class LogoutCommandTest { LogoutCommand command = new LogoutCommand(); // when - command.executeCommand(sender, new CommandParts(new ArrayList()), new CommandParts(new ArrayList())); + command.executeCommand(sender, new ArrayList()); // then Mockito.verify(managementMock, never()).performLogout(any(Player.class)); @@ -55,7 +55,7 @@ public class LogoutCommandTest { LogoutCommand command = new LogoutCommand(); // when - command.executeCommand(sender, new CommandParts(new ArrayList()), new CommandParts("password")); + command.executeCommand(sender, Collections.singletonList("password")); // then Mockito.verify(managementMock).performLogout(sender); diff --git a/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java index 6dd19eb2..b6bc992c 100644 --- a/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java @@ -1,6 +1,5 @@ package fr.xephi.authme.command.executable.register; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.process.Management; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; @@ -15,6 +14,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import java.util.ArrayList; +import java.util.Collections; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; @@ -50,7 +50,7 @@ public class RegisterCommandTest { ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(String.class); // when - command.executeCommand(sender, newParts(), newParts()); + command.executeCommand(sender, new ArrayList()); // then verify(sender).sendMessage(messageCaptor.capture()); @@ -65,7 +65,7 @@ public class RegisterCommandTest { RegisterCommand command = new RegisterCommand(); // when - command.executeCommand(sender, newParts(), newParts()); + command.executeCommand(sender, new ArrayList()); // then verify(messagesMock).send(sender, MessageKey.USAGE_REGISTER); @@ -79,13 +79,10 @@ public class RegisterCommandTest { RegisterCommand command = new RegisterCommand(); // when - command.executeCommand(sender, newParts(), new CommandParts("password")); + command.executeCommand(sender, Collections.singletonList("password")); // then verify(managementMock).performRegister(sender, "password", ""); } - private static CommandParts newParts() { - return new CommandParts(new ArrayList()); - } } diff --git a/src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java b/src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java new file mode 100644 index 00000000..dbc62dc8 --- /dev/null +++ b/src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java @@ -0,0 +1,65 @@ +package fr.xephi.authme.command.help; + +import fr.xephi.authme.command.CommandDescription; +import fr.xephi.authme.command.ExecutableCommand; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.hamcrest.Matchers.contains; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; + +/** + * Test for {@link HelpProvider}. + */ +public class HelpProviderTest { + + private static CommandDescription parent; + private static CommandDescription child; + + @BeforeClass + public static void setUpCommands() { + parent = CommandDescription.builder() + .executableCommand(mock(ExecutableCommand.class)) + .labels("base", "b") + .description("Parent") + .detailedDescription("Test base command.") + .build(); + child = CommandDescription.builder() + .executableCommand(mock(ExecutableCommand.class)) + .parent(parent) + .labels("child", "c") + .description("Child") + .detailedDescription("Child test command.") + .withArgument("Argument", "The argument", false) + .build(); + } + + @Test + public void shouldRetainCorrectLabels() { + // given + List labels = Arrays.asList("b", "child"); + + // when + List result = HelpProvider.filterCorrectLabels(child, labels); + + // then + assertThat(result, contains("b", "child")); + } + + @Test + public void shouldReplaceIncorrectLabels() { + // given + List labels = Arrays.asList("base", "wrong"); + + // when + List result = HelpProvider.filterCorrectLabels(child, labels); + + // then + assertThat(result, contains("base", "child")); + } + +} diff --git a/src/test/java/fr/xephi/authme/command/help/HelpSyntaxHelperTest.java b/src/test/java/fr/xephi/authme/command/help/HelpSyntaxHelperTest.java deleted file mode 100644 index 3ca665f4..00000000 --- a/src/test/java/fr/xephi/authme/command/help/HelpSyntaxHelperTest.java +++ /dev/null @@ -1,132 +0,0 @@ -package fr.xephi.authme.command.help; - -import fr.xephi.authme.command.CommandDescription; -import fr.xephi.authme.command.CommandParts; -import fr.xephi.authme.command.ExecutableCommand; -import fr.xephi.authme.command.executable.authme.RegisterAdminCommand; -import org.junit.Test; -import org.mockito.Mockito; - -import java.util.ArrayList; - -import static org.bukkit.ChatColor.BOLD; -import static org.bukkit.ChatColor.ITALIC; -import static org.bukkit.ChatColor.WHITE; -import static org.bukkit.ChatColor.YELLOW; -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; - -/** - * Test for {@link HelpSyntaxHelper}. - */ -public class HelpSyntaxHelperTest { - - @Test - public void shouldFormatSimpleCommand() { - // given - CommandDescription description = getDescriptionBuilder() - .withArgument("name", "The name", true) - .build(); - - // when - String result = HelpSyntaxHelper.getCommandSyntax(description, newParts(), "", false); - - // then - assertThat(result, equalTo(WHITE + "/authme register" + ITALIC + " [name]")); - } - - @Test - public void shouldFormatSimpleCommandWithOptionalParam() { - // given - CommandDescription description = getDescriptionBuilder() - .withArgument("test", "", false) - .build(); - - // when - String result = HelpSyntaxHelper.getCommandSyntax(description, newParts(), null, false); - - // then - assertThat(result, equalTo(WHITE + "/authme register" + ITALIC + " ")); - } - - @Test - public void shouldFormatCommandWithMultipleParams() { - // given - CommandDescription description = getDescriptionBuilder() - .withArgument("name", "", true) - .withArgument("test", "", false) - .build(); - - // when - String result = HelpSyntaxHelper.getCommandSyntax(description, newParts(), "", false); - - // then - assertThat(result, equalTo(WHITE + "/authme register" + ITALIC + " [name]" + ITALIC + " ")); - } - - @Test - public void shouldHighlightCommandWithMultipleParams() { - // given - CommandDescription description = getDescriptionBuilder() - .withArgument("name", "", true) - .withArgument("test", "", false) - .build(); - - // when - String result = HelpSyntaxHelper.getCommandSyntax(description, newParts(), "", true); - - // then - assertThat(result, equalTo(WHITE + "/authme " - + YELLOW + BOLD + "register" - + YELLOW + ITALIC + " [name]" + ITALIC + " ")); - } - - @Test - public void shouldHighlightCommandWithNoParams() { - // given - CommandDescription description = getDescriptionBuilder().build(); - - // when - String result = HelpSyntaxHelper.getCommandSyntax(description, newParts(), null, true); - - // then - assertThat(result, equalTo(WHITE + "/authme " + YELLOW + BOLD + "register" + YELLOW)); - } - - @Test - public void shouldFormatSimpleCommandWithAlternativeLabel() { - // given - CommandDescription description = getDescriptionBuilder() - .withArgument("name", "The name", true) - .build(); - - // when - String result = HelpSyntaxHelper.getCommandSyntax(description, newParts(), "alt", false); - - // then - assertThat(result, equalTo(WHITE + "/authme alt" + ITALIC + " [name]")); - } - - private static CommandParts newParts() { - // TODO ljacqu 20151204: Remove this method once CommandParts has been removed - return new CommandParts(new ArrayList()); - } - - private static CommandDescription.CommandBuilder getDescriptionBuilder() { - CommandDescription base = CommandDescription.builder() - .labels("authme") - .description("Base command") - .detailedDescription("AuthMe base command") - .parent(null) - .executableCommand(Mockito.mock(ExecutableCommand.class)) - .build(); - - return CommandDescription.builder() - .executableCommand(Mockito.mock(RegisterAdminCommand.class)) - .labels("register", "r") - .description("Register a player") - .detailedDescription("Register the specified player with the specified password.") - .parent(base) - .executableCommand(Mockito.mock(ExecutableCommand.class)); - } -}