Add '/lp verbose command <command>' for easy testing of command permissions

This commit is contained in:
Luck 2020-06-03 22:32:24 +01:00
parent 11998b2dd6
commit e37c77a1be
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
15 changed files with 136 additions and 45 deletions

View File

@ -25,7 +25,6 @@
package me.lucko.luckperms.bukkit;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.sender.SenderFactory;
import me.lucko.luckperms.common.util.TextUtils;
@ -41,9 +40,8 @@ import org.bukkit.entity.Player;
import java.util.UUID;
public class BukkitSenderFactory extends SenderFactory<CommandSender> {
public BukkitSenderFactory(LuckPermsPlugin plugin) {
public class BukkitSenderFactory extends SenderFactory<LPBukkitPlugin, CommandSender> {
public BukkitSenderFactory(LPBukkitPlugin plugin) {
super(plugin);
}
@ -102,6 +100,11 @@ public class BukkitSenderFactory extends SenderFactory<CommandSender> {
return sender.hasPermission(node);
}
@Override
protected void performCommand(CommandSender sender, String command) {
getPlugin().getBootstrap().getServer().dispatchCommand(sender, command);
}
private static final class SyncMessengerAgent implements Runnable {
private final CommandSender sender;
private final String message;

View File

@ -16,6 +16,9 @@ luckperms {
record {
filter brigadier:string greedy_phrase;
}
command {
command brigadier:string greedy_phrase;
}
}
tree {
scope brigadier:string single_word {

View File

@ -26,7 +26,6 @@
package me.lucko.luckperms.bungee;
import me.lucko.luckperms.bungee.event.TristateCheckEvent;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.sender.SenderFactory;
import me.lucko.luckperms.common.util.TextUtils;
@ -39,8 +38,8 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.UUID;
public class BungeeSenderFactory extends SenderFactory<CommandSender> {
public BungeeSenderFactory(LuckPermsPlugin plugin) {
public class BungeeSenderFactory extends SenderFactory<LPBungeePlugin, CommandSender> {
public BungeeSenderFactory(LPBungeePlugin plugin) {
super(plugin);
}
@ -79,4 +78,9 @@ public class BungeeSenderFactory extends SenderFactory<CommandSender> {
protected boolean hasPermission(CommandSender sender, String node) {
return sender.hasPermission(node);
}
@Override
protected void performCommand(CommandSender sender, String command) {
getPlugin().getBootstrap().getProxy().getPluginManager().dispatchCommand(sender, command);
}
}

View File

@ -25,11 +25,11 @@
package me.lucko.luckperms.common.commands.misc;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.command.CommandResult;
import me.lucko.luckperms.common.command.abstraction.SingleCommand;
import me.lucko.luckperms.common.command.access.CommandPermission;
import me.lucko.luckperms.common.command.tabcomplete.CompletionSupplier;
import me.lucko.luckperms.common.command.tabcomplete.TabCompleter;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.locale.command.CommandSpec;
@ -39,6 +39,7 @@ import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.util.Predicates;
import me.lucko.luckperms.common.verbose.InvalidFilterException;
import me.lucko.luckperms.common.verbose.VerboseFilter;
import me.lucko.luckperms.common.verbose.VerboseHandler;
import me.lucko.luckperms.common.verbose.VerboseListener;
import me.lucko.luckperms.common.web.UnsuccessfulRequestException;
@ -50,10 +51,8 @@ import net.kyori.text.format.TextColor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.concurrent.Executor;
public class VerboseCommand extends SingleCommand {
public VerboseCommand(LocaleManager locale) {
@ -67,8 +66,32 @@ public class VerboseCommand extends SingleCommand {
return CommandResult.INVALID_ARGS;
}
VerboseHandler verboseHandler = plugin.getVerboseHandler();
String mode = args.get(0).toLowerCase();
if (mode.equals("command") || mode.equals("cmd")) {
if (args.size() == 1) {
sendDetailedUsage(sender, label);
return CommandResult.INVALID_ARGS;
}
String commandWithSlash = String.join(" ", args.subList(1, args.size()));
String command = commandWithSlash.charAt(0) == '/' ? commandWithSlash.substring(1) : commandWithSlash;
Executor syncExecutor = plugin.getBootstrap().getScheduler().sync();
syncExecutor.execute(() -> {
Message.VERBOSE_ON_COMMAND.send(sender, sender.getName(), command);
verboseHandler.registerListener(sender, VerboseFilter.acceptAll(), true);
sender.performCommand(command);
verboseHandler.unregisterListener(sender);
Message.VERBOSE_OFF_COMMAND.send(sender);
});
return CommandResult.SUCCESS;
}
if (mode.equals("on") || mode.equals("true") || mode.equals("record")) {
List<String> filters = new ArrayList<>();
if (args.size() != 1) {
@ -79,7 +102,7 @@ public class VerboseCommand extends SingleCommand {
VerboseFilter compiledFilter;
try {
compiledFilter = new VerboseFilter(filter);
compiledFilter = VerboseFilter.compile(filter);
} catch (InvalidFilterException e) {
Message.VERBOSE_INVALID_FILTER.send(sender, filter, e.getCause().getMessage());
return CommandResult.FAILURE;
@ -87,7 +110,7 @@ public class VerboseCommand extends SingleCommand {
boolean notify = !mode.equals("record");
plugin.getVerboseHandler().registerListener(sender, compiledFilter, notify);
verboseHandler.registerListener(sender, compiledFilter, notify);
if (notify) {
if (!filter.equals("")) {
@ -107,7 +130,7 @@ public class VerboseCommand extends SingleCommand {
}
if (mode.equals("off") || mode.equals("false") || mode.equals("paste") || mode.equals("upload")) {
VerboseListener listener = plugin.getVerboseHandler().unregisterListener(sender.getUniqueId());
VerboseListener listener = verboseHandler.unregisterListener(sender);
if (mode.equals("paste") || mode.equals("upload")) {
if (listener == null) {
@ -152,14 +175,8 @@ public class VerboseCommand extends SingleCommand {
@Override
public List<String> tabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
if (args.isEmpty()) {
return ImmutableList.of("on", "record", "off", "upload");
}
if (args.size() == 1) {
return Stream.of("on", "record", "off", "upload").filter(s -> s.toLowerCase().startsWith(args.get(0).toLowerCase())).collect(Collectors.toList());
}
return Collections.emptyList();
return TabCompleter.create()
.at(0, CompletionSupplier.startsWith("on", "record", "off", "upload", "command"))
.complete(args);
}
}

View File

@ -65,7 +65,7 @@ public enum CommandSpec {
DEBUG("Produces a set of internal debugging output", "/%s debug"),
VERBOSE("Controls the plugins verbose permission check monitoring system.", "/%s verbose <on|record|off|upload> [filter]",
Argument.list(
Argument.create("on|record|off|upload", true, "whether to enable/disable logging, or to upload the logged output"),
Argument.create("on|record|off|upload|command", true, "whether to enable/disable logging, or to upload the logged output"),
Argument.create("filter", false, "the filter to match entries against")
)
),

View File

@ -131,7 +131,9 @@ public enum Message {
VERBOSE_INVALID_FILTER("&4{}&c is not a valid verbose filter. &7({})", true),
VERBOSE_ON("&bVerbose logging &aenabled &bfor checks matching &aANY&b.", true),
VERBOSE_ON_QUERY("&bVerbose logging &aenabled &bfor checks matching &a{}&b.", true),
VERBOSE_ON_COMMAND("&bForcing &a{}&b to execute command &a/{}&b and reporting all checks made...", true),
VERBOSE_OFF("&bVerbose logging &cdisabled&b.", true),
VERBOSE_OFF_COMMAND("&bCommand execution complete.", true),
VERBOSE_RECORDING_ON("&bVerbose recording &aenabled &bfor checks matching &aANY&b.", true),
VERBOSE_RECORDING_ON_QUERY("&bVerbose recording &aenabled &bfor checks matching &a{}&b.", true),

View File

@ -45,13 +45,13 @@ public final class AbstractSender<T> implements Sender {
private static final Splitter NEW_LINE_SPLITTER = Splitter.on("\n");
private final LuckPermsPlugin platform;
private final SenderFactory<T> factory;
private final SenderFactory<?, T> factory;
private final WeakReference<T> sender;
private final UUID uniqueId;
private final String name;
AbstractSender(LuckPermsPlugin platform, SenderFactory<T> factory, T t) {
AbstractSender(LuckPermsPlugin platform, SenderFactory<?, T> factory, T t) {
this.platform = platform;
this.factory = factory;
this.sender = new WeakReference<>(t);
@ -125,6 +125,14 @@ public final class AbstractSender<T> implements Sender {
return isConsole();
}
@Override
public void performCommand(String commandLine) {
T sender = this.sender.get();
if (sender != null) {
this.factory.performCommand(sender, commandLine);
}
}
@Override
public boolean isValid() {
return this.sender.get() != null;

View File

@ -67,6 +67,11 @@ public abstract class DummySender implements Sender {
return true;
}
@Override
public void performCommand(String commandLine) {
}
@Override
public LuckPermsPlugin getPlugin() {
return this.platform;

View File

@ -96,6 +96,18 @@ public interface Sender {
return name + "@" + location;
}
/**
* Gets the name used to identify this sender in verbose events.
*
* @return the verbose check target name
*/
default String getVerboseCheckTarget() {
if (isConsole()) {
return "internal/console";
}
return getName();
}
/**
* Gets the sender's unique id.
*
@ -147,6 +159,13 @@ public interface Sender {
return hasPermission(permission.getPermission());
}
/**
* Makes the sender perform a command.
*
* @param commandLine the command
*/
void performCommand(String commandLine);
/**
* Gets whether this sender is the console
*

View File

@ -36,17 +36,17 @@ import java.util.UUID;
/**
* Factory class to make a thread-safe sender instance
*
* @param <P> the plugin type
* @param <T> the command sender type
*/
public abstract class SenderFactory<T> {
public abstract class SenderFactory<P extends LuckPermsPlugin, T> {
private final P plugin;
private final LuckPermsPlugin plugin;
public SenderFactory(LuckPermsPlugin plugin) {
public SenderFactory(P plugin) {
this.plugin = plugin;
}
protected LuckPermsPlugin getPlugin() {
protected P getPlugin() {
return this.plugin;
}
@ -62,6 +62,8 @@ public abstract class SenderFactory<T> {
protected abstract boolean hasPermission(T sender, String node);
protected abstract void performCommand(T sender, String command);
public final Sender wrap(T sender) {
Objects.requireNonNull(sender, "sender");
return new AbstractSender<>(this.plugin, this, sender);

View File

@ -41,7 +41,15 @@ public final class VerboseFilter {
private final String expression;
private final AST ast;
public VerboseFilter(String expression) throws InvalidFilterException {
public static VerboseFilter acceptAll() {
return new VerboseFilter();
}
public static VerboseFilter compile(String expression) throws InvalidFilterException {
return new VerboseFilter(expression);
}
private VerboseFilter(String expression) throws InvalidFilterException {
this.expression = expression;
if (expression.isEmpty()) {
this.ast = AST.ALWAYS_TRUE;
@ -54,6 +62,11 @@ public final class VerboseFilter {
}
}
private VerboseFilter() {
this.expression = "";
this.ast = AST.ALWAYS_TRUE;
}
/**
* Evaluates whether the check data passes the filter
*

View File

@ -122,6 +122,9 @@ public class VerboseHandler implements AutoCloseable {
* @param notify if the sender should be notified in chat on each check
*/
public void registerListener(Sender sender, VerboseFilter filter, boolean notify) {
// flush out anything before this listener was added
flush();
this.listeners.put(sender.getUniqueId(), new VerboseListener(sender, filter, notify));
this.listening = true;
}
@ -129,14 +132,14 @@ public class VerboseHandler implements AutoCloseable {
/**
* Removes a listener for a given player
*
* @param uuid the players uuid
* @param sender the sender
* @return the existing listener, if one was actually registered
*/
public VerboseListener unregisterListener(UUID uuid) {
public VerboseListener unregisterListener(Sender sender) {
// immediately flush, so the listener gets all current data
flush();
return this.listeners.remove(uuid);
return this.listeners.remove(sender.getUniqueId());
}
private void tick() {

View File

@ -25,7 +25,6 @@
package me.lucko.luckperms.nukkit;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.sender.SenderFactory;
import me.lucko.luckperms.common.util.TextUtils;
@ -39,8 +38,8 @@ import cn.nukkit.command.ConsoleCommandSender;
import java.util.UUID;
public class NukkitSenderFactory extends SenderFactory<CommandSender> {
public NukkitSenderFactory(LuckPermsPlugin plugin) {
public class NukkitSenderFactory extends SenderFactory<LPNukkitPlugin, CommandSender> {
public NukkitSenderFactory(LPNukkitPlugin plugin) {
super(plugin);
}
@ -94,6 +93,11 @@ public class NukkitSenderFactory extends SenderFactory<CommandSender> {
return sender.hasPermission(node);
}
@Override
protected void performCommand(CommandSender sender, String command) {
getPlugin().getBootstrap().getServer().dispatchCommand(sender, command);
}
private static final class SyncMessengerAgent implements Runnable {
private final CommandSender sender;
private final String message;

View File

@ -25,7 +25,6 @@
package me.lucko.luckperms.sponge;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.sender.SenderFactory;
import me.lucko.luckperms.sponge.service.CompatibilityUtil;
@ -40,8 +39,8 @@ import org.spongepowered.api.text.serializer.TextSerializers;
import java.util.UUID;
public class SpongeSenderFactory extends SenderFactory<CommandSource> {
public SpongeSenderFactory(LuckPermsPlugin plugin) {
public class SpongeSenderFactory extends SenderFactory<LPSpongePlugin, CommandSource> {
public SpongeSenderFactory(LPSpongePlugin plugin) {
super(plugin);
}
@ -88,4 +87,9 @@ public class SpongeSenderFactory extends SenderFactory<CommandSource> {
protected boolean hasPermission(CommandSource source, String node) {
return source.hasPermission(node);
}
@Override
protected void performCommand(CommandSource source, String command) {
getPlugin().getBootstrap().getGame().getCommandManager().process(source, command);
}
}

View File

@ -28,7 +28,6 @@ package me.lucko.luckperms.velocity;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.sender.SenderFactory;
import me.lucko.luckperms.common.util.TextUtils;
@ -39,8 +38,8 @@ import net.luckperms.api.util.Tristate;
import java.util.UUID;
public class VelocitySenderFactory extends SenderFactory<CommandSource> {
public VelocitySenderFactory(LuckPermsPlugin plugin) {
public class VelocitySenderFactory extends SenderFactory<LPVelocityPlugin, CommandSource> {
public VelocitySenderFactory(LPVelocityPlugin plugin) {
super(plugin);
}
@ -79,4 +78,9 @@ public class VelocitySenderFactory extends SenderFactory<CommandSource> {
protected boolean hasPermission(CommandSource source, String node) {
return source.hasPermission(node);
}
@Override
protected void performCommand(CommandSource source, String command) {
getPlugin().getBootstrap().getProxy().getCommandManager().execute(source, command);
}
}