Check permissions in command suggestions and Dispatcher.

This commit is contained in:
sk89q 2014-06-28 16:57:11 -07:00
parent 205fee3c36
commit 10c45fcb22
6 changed files with 42 additions and 33 deletions

View File

@ -126,6 +126,7 @@ public class BukkitServerInterface extends ServerInterface {
public void registerCommands(Dispatcher dispatcher) { public void registerCommands(Dispatcher dispatcher) {
List<CommandInfo> toRegister = new ArrayList<CommandInfo>(); List<CommandInfo> toRegister = new ArrayList<CommandInfo>();
BukkitCommandInspector inspector = new BukkitCommandInspector(plugin, dispatcher); BukkitCommandInspector inspector = new BukkitCommandInspector(plugin, dispatcher);
for (CommandMapping command : dispatcher.getCommands()) { for (CommandMapping command : dispatcher.getCommands()) {
Description description = command.getDescription(); Description description = command.getDescription();
List<String> permissions = description.getPermissions(); List<String> permissions = description.getPermissions();

View File

@ -258,7 +258,9 @@ public final class CommandManager {
@Subscribe @Subscribe
public void handleCommandSuggestion(CommandSuggestionEvent event) { public void handleCommandSuggestion(CommandSuggestionEvent event) {
try { try {
event.setSuggestions(dispatcher.getSuggestions(event.getArguments())); CommandLocals locals = new CommandLocals();
locals.put(Actor.class, event.getActor());
event.setSuggestions(dispatcher.getSuggestions(event.getArguments(), locals));
} catch (CommandException e) { } catch (CommandException e) {
event.getActor().printError(e.getMessage()); event.getActor().printError(e.getMessage());
} }

View File

@ -56,10 +56,11 @@ public interface CommandCallable {
* Get a list of suggestions based on input. * Get a list of suggestions based on input.
* *
* @param arguments the arguments entered up to this point * @param arguments the arguments entered up to this point
* @param locals the locals
* @return a list of suggestions * @return a list of suggestions
* @throws CommandException thrown if there was a parsing error * @throws CommandException thrown if there was a parsing error
*/ */
List<String> getSuggestions(String arguments) throws CommandException; List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException;
/** /**
* Get an object describing this command. * Get an object describing this command.

View File

@ -21,6 +21,7 @@ package com.sk89q.worldedit.util.command;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Collection; import java.util.Collection;
import java.util.Set;
/** /**
* Executes a command based on user input. * Executes a command based on user input.
@ -36,13 +37,14 @@ public interface Dispatcher extends CommandCallable {
void registerCommand(CommandCallable callable, String... alias); void registerCommand(CommandCallable callable, String... alias);
/** /**
* Get a list of command registrations. * Get a list of commands. Each command, regardless of how many aliases
* it may have, will only appear once in the returned set.
* *
* <p>The returned collection cannot be modified.</p> * <p>The returned collection cannot be modified.</p>
* *
* @return a list of registrations * @return a list of registrations
*/ */
Collection<CommandMapping> getCommands(); Set<CommandMapping> getCommands();
/** /**
* Get a list of primary aliases. * Get a list of primary aliases.

View File

@ -20,10 +20,7 @@
package com.sk89q.worldedit.util.command; package com.sk89q.worldedit.util.command;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.*;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.minecraft.util.commands.WrappedCommandException;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.*; import java.util.*;
@ -56,8 +53,8 @@ public class SimpleDispatcher implements Dispatcher {
} }
@Override @Override
public Collection<CommandMapping> getCommands() { public Set<CommandMapping> getCommands() {
return Collections.unmodifiableCollection(commands.values()); return Collections.unmodifiableSet(new HashSet<CommandMapping>(commands.values()));
} }
@Override @Override
@ -91,6 +88,11 @@ public class SimpleDispatcher implements Dispatcher {
@Override @Override
public boolean call(@Nullable String alias, String arguments, CommandLocals locals) throws CommandException { public boolean call(@Nullable String alias, String arguments, CommandLocals locals) throws CommandException {
// We have permission for this command if we have permissions for subcommands
if (!testPermission(locals)) {
throw new CommandPermissionsException();
}
String[] split = CommandContext.split(arguments); String[] split = CommandContext.split(arguments);
Set<String> aliases = getPrimaryAliases(); Set<String> aliases = getPrimaryAliases();
@ -116,37 +118,37 @@ public class SimpleDispatcher implements Dispatcher {
} }
throw new InvalidUsageException(getSubcommandList(), getDescription()); throw new InvalidUsageException(getSubcommandList(locals), getDescription());
} }
@Override @Override
public List<String> getSuggestions(String arguments) throws CommandException { public List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException {
String[] split = CommandContext.split(arguments); String[] split = CommandContext.split(arguments);
if (split.length == 0) { if (split.length <= 1) {
return new ArrayList<String>(getAliases()); String prefix = split.length > 0 ? split[0] : "";
} else if (split.length == 1) {
String prefix = split[0];
if (!prefix.isEmpty()) {
List<String> suggestions = new ArrayList<String>();
for (String alias : getAliases()) { List<String> suggestions = new ArrayList<String>();
if (alias.startsWith(prefix)) {
suggestions.add(alias); for (CommandMapping mapping : getCommands()) {
if (mapping.getCallable().testPermission(locals)) {
for (String alias : mapping.getAllAliases()) {
if (prefix.isEmpty() || alias.startsWith(arguments)) {
suggestions.add(mapping.getPrimaryAlias());
break;
}
} }
} }
return suggestions;
} else {
return new ArrayList<String>(getAliases());
} }
return suggestions;
} else { } else {
String subCommand = split[0]; String subCommand = split[0];
CommandMapping mapping = get(subCommand); CommandMapping mapping = get(subCommand);
String passedArguments = Joiner.on(" ").join(Arrays.copyOfRange(split, 1, split.length)); String passedArguments = Joiner.on(" ").join(Arrays.copyOfRange(split, 1, split.length));
if (mapping != null) { if (mapping != null) {
return mapping.getCallable().getSuggestions(passedArguments); return mapping.getCallable().getSuggestions(passedArguments, locals);
} else { } else {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -174,16 +176,17 @@ public class SimpleDispatcher implements Dispatcher {
* *
* @return a string * @return a string
*/ */
private String getSubcommandList() { private String getSubcommandList(CommandLocals locals) {
Set<String> aliases = getPrimaryAliases(); Set<String> aliases = getPrimaryAliases();
StringBuilder builder = new StringBuilder("Subcommands: "); StringBuilder builder = new StringBuilder("Subcommands: ");
for (String alias : getPrimaryAliases()) {
builder.append("\n- ").append(alias);
}
if (aliases.size() == 1) { for (CommandMapping mapping : getCommands()) {
builder.append(" (there is only one)"); if (mapping.getCallable().testPermission(locals)) {
for (String alias : mapping.getAllAliases()) {
builder.append("\n- ").append(alias);
}
}
} }
return builder.toString(); return builder.toString();

View File

@ -252,7 +252,7 @@ class ParametricCallable implements CommandCallable {
} }
@Override @Override
public List<String> getSuggestions(String stringArguments) throws CommandException { public List<String> getSuggestions(String stringArguments, CommandLocals locals) throws CommandException {
String[] split = CommandContext.split(stringArguments); String[] split = CommandContext.split(stringArguments);
CommandContext context = new CommandContext(split, getValueFlags()); CommandContext context = new CommandContext(split, getValueFlags());