Replace command permissions with a new smarter permission system that allows for compound permissions

This commit is contained in:
Alexander Söderberg 2020-09-24 23:18:22 +02:00 committed by Alexander Söderberg
parent ce2fbe9746
commit e8a1a9a6cf
15 changed files with 455 additions and 41 deletions

View file

@ -28,6 +28,8 @@ import com.intellectualsites.commands.arguments.StaticArgument;
import com.intellectualsites.commands.execution.CommandExecutionHandler;
import com.intellectualsites.commands.meta.CommandMeta;
import com.intellectualsites.commands.meta.SimpleCommandMeta;
import com.intellectualsites.commands.permission.CommandPermission;
import com.intellectualsites.commands.permission.Permission;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -50,7 +52,7 @@ public class Command<C> {
@Nonnull private final Map<CommandArgument<C, ?>, Description> arguments;
@Nonnull private final CommandExecutionHandler<C> commandExecutionHandler;
@Nullable private final Class<? extends C> senderType;
@Nonnull private final String commandPermission;
@Nonnull private final CommandPermission commandPermission;
@Nonnull private final CommandMeta commandMeta;
/**
@ -65,7 +67,7 @@ public class Command<C> {
public Command(@Nonnull final Map<CommandArgument<C, ?>, Description> commandArguments,
@Nonnull final CommandExecutionHandler<C> commandExecutionHandler,
@Nullable final Class<? extends C> senderType,
@Nonnull final String commandPermission,
@Nonnull final CommandPermission commandPermission,
@Nonnull final CommandMeta commandMeta) {
this.arguments = Objects.requireNonNull(commandArguments, "Command arguments may not be null");
if (this.arguments.size() == 0) {
@ -103,7 +105,7 @@ public class Command<C> {
@Nonnull final CommandExecutionHandler<C> commandExecutionHandler,
@Nullable final Class<? extends C> senderType,
@Nonnull final CommandMeta commandMeta) {
this(commandArguments, commandExecutionHandler, senderType, "", commandMeta);
this(commandArguments, commandExecutionHandler, senderType, Permission.empty(), commandMeta);
}
/**
@ -116,7 +118,7 @@ public class Command<C> {
*/
public Command(@Nonnull final Map<CommandArgument<C, ?>, Description> commandArguments,
@Nonnull final CommandExecutionHandler<C> commandExecutionHandler,
@Nonnull final String commandPermission,
@Nonnull final CommandPermission commandPermission,
@Nonnull final CommandMeta commandMeta) {
this(commandArguments, commandExecutionHandler, null, commandPermission, commandMeta);
}
@ -140,7 +142,7 @@ public class Command<C> {
final Map<CommandArgument<C, ?>, Description> map = new LinkedHashMap<>();
map.put(StaticArgument.required(commandName, aliases), description);
return new Builder<>(null, commandMeta, null, map,
new CommandExecutionHandler.NullCommandExecutionHandler<>(), "");
new CommandExecutionHandler.NullCommandExecutionHandler<>(), Permission.empty());
}
/**
@ -160,7 +162,7 @@ public class Command<C> {
final Map<CommandArgument<C, ?>, Description> map = new LinkedHashMap<>();
map.put(StaticArgument.required(commandName, aliases), Description.empty());
return new Builder<>(null, commandMeta, null, map,
new CommandExecutionHandler.NullCommandExecutionHandler<>(), "");
new CommandExecutionHandler.NullCommandExecutionHandler<>(), Permission.empty());
}
/**
@ -199,7 +201,7 @@ public class Command<C> {
* @return Command permission
*/
@Nonnull
public String getCommandPermission() {
public CommandPermission getCommandPermission() {
return this.commandPermission;
}
@ -237,7 +239,7 @@ public class Command<C> {
@Nonnull private final Map<CommandArgument<C, ?>, Description> commandArguments;
@Nonnull private final CommandExecutionHandler<C> commandExecutionHandler;
@Nullable private final Class<? extends C> senderType;
@Nonnull private final String commandPermission;
@Nonnull private final CommandPermission commandPermission;
@Nullable private final CommandManager<C> commandManager;
private Builder(@Nullable final CommandManager<C> commandManager,
@ -245,7 +247,7 @@ public class Command<C> {
@Nullable final Class<? extends C> senderType,
@Nonnull final Map<CommandArgument<C, ?>, Description> commandArguments,
@Nonnull final CommandExecutionHandler<C> commandExecutionHandler,
@Nonnull final String commandPermission) {
@Nonnull final CommandPermission commandPermission) {
this.commandManager = commandManager;
this.senderType = senderType;
this.commandArguments = Objects.requireNonNull(commandArguments, "Arguments may not be null");
@ -391,11 +393,23 @@ public class Command<C> {
* @return New builder instance using the command permission
*/
@Nonnull
public Builder<C> withPermission(@Nonnull final String permission) {
public Builder<C> withPermission(@Nonnull final CommandPermission permission) {
return new Builder<>(this.commandManager, this.commandMeta, this.senderType, this.commandArguments,
this.commandExecutionHandler, permission);
}
/**
* Specify a command permission
*
* @param permission Command permission
* @return New builder instance using the command permission
*/
@Nonnull
public Builder<C> withPermission(@Nonnull final String permission) {
return new Builder<>(this.commandManager, this.commandMeta, this.senderType, this.commandArguments,
this.commandExecutionHandler, Permission.of(permission));
}
/**
* Build a command using the builder instance
*

View file

@ -46,6 +46,9 @@ import com.intellectualsites.commands.execution.preprocessor.CommandPreprocessin
import com.intellectualsites.commands.execution.preprocessor.CommandPreprocessor;
import com.intellectualsites.commands.internal.CommandRegistrationHandler;
import com.intellectualsites.commands.meta.CommandMeta;
import com.intellectualsites.commands.permission.CommandPermission;
import com.intellectualsites.commands.permission.OrPermission;
import com.intellectualsites.commands.permission.Permission;
import com.intellectualsites.services.ServicePipeline;
import com.intellectualsites.services.State;
@ -210,6 +213,29 @@ public abstract class CommandManager<C> {
this.commandRegistrationHandler = commandRegistrationHandler;
}
/**
* Check if the command sender has the required permission. If the permission node is
* empty, this should return {@code true}
*
* @param sender Command sender
* @param permission Permission node
* @return {@code true} if the sender has the permission, else {@code false}
*/
public boolean hasPermission(@Nonnull final C sender, @Nonnull final CommandPermission permission) {
if (permission instanceof Permission) {
return hasPermission(sender, permission.toString());
}
for (final CommandPermission innerPermission : permission.getPermissions()) {
final boolean hasPermission = this.hasPermission(sender, innerPermission);
if (permission instanceof OrPermission) {
if (hasPermission) {
return true;
}
}
}
return !(permission instanceof OrPermission);
}
/**
* Check if the command sender has the required permission. If the permission node is
* empty, this should return {@code true}

View file

@ -34,10 +34,13 @@ import com.intellectualsites.commands.exceptions.InvalidSyntaxException;
import com.intellectualsites.commands.exceptions.NoCommandInLeafException;
import com.intellectualsites.commands.exceptions.NoPermissionException;
import com.intellectualsites.commands.exceptions.NoSuchCommandException;
import com.intellectualsites.commands.permission.CommandPermission;
import com.intellectualsites.commands.permission.OrPermission;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@ -130,7 +133,7 @@ public final class CommandTree<C> {
@Nonnull final CommandContext<C> commandContext,
@Nonnull final Queue<String> commandQueue,
@Nonnull final Node<CommandArgument<C, ?>> root) {
String permission = this.isPermitted(commandContext.getSender(), root);
CommandPermission permission = this.isPermitted(commandContext.getSender(), root);
if (permission != null) {
throw new NoPermissionException(permission, commandContext.getSender(), this.getChain(root)
.stream()
@ -213,7 +216,7 @@ public final class CommandTree<C> {
@Nonnull final CommandContext<C> commandContext,
@Nonnull final Node<CommandArgument<C, ?>> root,
@Nonnull final Queue<String> commandQueue) {
String permission;
CommandPermission permission;
final List<Node<CommandArgument<C, ?>>> children = root.getChildren();
if (children.size() == 1 && !(children.get(0).getValue() instanceof StaticArgument)) {
// The value has to be a variable
@ -412,8 +415,8 @@ public final class CommandTree<C> {
}
@Nullable
private String isPermitted(@Nonnull final C sender, @Nonnull final Node<CommandArgument<C, ?>> node) {
final String permission = node.nodeMeta.get("permission");
private CommandPermission isPermitted(@Nonnull final C sender, @Nonnull final Node<CommandArgument<C, ?>> node) {
final CommandPermission permission = (CommandPermission) node.nodeMeta.get("permission");
if (permission != null) {
return this.commandManager.hasPermission(sender, permission) ? null : permission;
}
@ -422,22 +425,24 @@ public final class CommandTree<C> {
Objects.requireNonNull(
Objects.requireNonNull(node.value, "node.value").getOwningCommand(),
"owning command").getCommandPermission())
? null : Objects.requireNonNull(node.value.getOwningCommand(), "owning command").getCommandPermission();
? null : Objects.requireNonNull(node.value.getOwningCommand(), "owning command")
.getCommandPermission();
}
/*
if any of the children would permit the execution, then the sender has a valid
chain to execute, and so we allow them to execute the root
*/
final List<String> missingPermissions = new LinkedList<>();
final List<CommandPermission> missingPermissions = new LinkedList<>();
for (final Node<CommandArgument<C, ?>> child : node.getChildren()) {
final String check = this.isPermitted(sender, child);
final CommandPermission check = this.isPermitted(sender, child);
if (check == null) {
return null;
} else {
missingPermissions.add(check);
}
}
return String.join(", ", missingPermissions);
return OrPermission.of(missingPermissions);
}
/**
@ -466,20 +471,23 @@ public final class CommandTree<C> {
// Register command permissions
this.getLeavesRaw(this.internalTree).forEach(node -> {
// noinspection all
final CommandPermission commandPermission = node.getValue().getOwningCommand().getCommandPermission();
/* All leaves must necessarily have an owning command */
// noinspection all
node.nodeMeta.put("permission", node.getValue().getOwningCommand().getCommandPermission());
node.nodeMeta.put("permission", commandPermission);
// Get chain and order it tail->head then skip the tail (leaf node)
List<Node<CommandArgument<C, ?>>> chain = this.getChain(node);
Collections.reverse(chain);
chain = chain.subList(1, chain.size());
// Go through all nodes from the tail upwards until a collision occurs
for (final Node<CommandArgument<C, ?>> commandArgumentNode : chain) {
if (commandArgumentNode.nodeMeta.containsKey("permission")
&& !commandArgumentNode.nodeMeta.get("permission").equalsIgnoreCase(node.nodeMeta.get("permission"))) {
commandArgumentNode.nodeMeta.put("permission", "");
final CommandPermission existingPermission = (CommandPermission) commandArgumentNode.nodeMeta.get("permission");
if (existingPermission != null) {
commandArgumentNode.nodeMeta.put("permission",
OrPermission.of(Arrays.asList(commandPermission, existingPermission)));
} else {
commandArgumentNode.nodeMeta.put("permission", node.nodeMeta.get("permission"));
commandArgumentNode.nodeMeta.put("permission", commandPermission);
}
}
});
@ -589,7 +597,7 @@ public final class CommandTree<C> {
*/
public static final class Node<T> {
private final Map<String, String> nodeMeta = new HashMap<>();
private final Map<String, Object> nodeMeta = new HashMap<>();
private final List<Node<T>> children = new LinkedList<>();
private final T value;
private Node<T> parent;
@ -640,7 +648,7 @@ public final class CommandTree<C> {
* @return Node meta
*/
@Nonnull
public Map<String, String> getNodeMeta() {
public Map<String, Object> getNodeMeta() {
return this.nodeMeta;
}

View file

@ -24,6 +24,7 @@
package com.intellectualsites.commands.exceptions;
import com.intellectualsites.commands.arguments.CommandArgument;
import com.intellectualsites.commands.permission.CommandPermission;
import javax.annotation.Nonnull;
import java.util.List;
@ -35,7 +36,7 @@ import java.util.List;
@SuppressWarnings("unused")
public class NoPermissionException extends CommandParseException {
private final String missingPermission;
private final CommandPermission missingPermission;
/**
* Construct a new no permission exception
@ -44,7 +45,7 @@ public class NoPermissionException extends CommandParseException {
* @param commandSender Command sender
* @param currentChain Chain leading up to the exception
*/
public NoPermissionException(@Nonnull final String missingPermission,
public NoPermissionException(@Nonnull final CommandPermission missingPermission,
@Nonnull final Object commandSender,
@Nonnull final List<CommandArgument<?, ?>> currentChain) {
super(commandSender, currentChain);
@ -63,7 +64,7 @@ public class NoPermissionException extends CommandParseException {
*/
@Nonnull
public String getMissingPermission() {
return this.missingPermission;
return this.missingPermission.toString();
}
@Override

View file

@ -0,0 +1,51 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
package com.intellectualsites.commands.permission;
import javax.annotation.Nonnull;
import java.util.Collection;
/**
* A command permission string
*/
public interface CommandPermission {
/**
* Get the permission nodes
*
* @return Permission nodes
*/
@Nonnull
Collection<CommandPermission> getPermissions();
/**
* Get a string representation of the permission
*
* @return String representation of the permission node
*/
@Override
@Nonnull
String toString();
}

View file

@ -0,0 +1,96 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
package com.intellectualsites.commands.permission;
import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Objects;
import java.util.Set;
/**
* Accepts as long as at least one of the permissions is accepted
*/
public final class OrPermission implements CommandPermission {
private final Collection<CommandPermission> permissions;
private OrPermission(@Nonnull final Collection<CommandPermission> permissions) {
this.permissions = permissions;
}
/**
* Create a new OR permission
*
* @param permissions Permissions to join
* @return Constructed permission
*/
@Nonnull
public static CommandPermission of(@Nonnull final Collection<CommandPermission> permissions) {
final Set<CommandPermission> permissionSet = new HashSet<>();
for (final CommandPermission permission : permissions) {
permissionSet.addAll(permission.getPermissions());
}
return new OrPermission(permissionSet);
}
@Nonnull
@Override
public Collection<CommandPermission> getPermissions() {
return this.permissions;
}
@Override
public String toString() {
final StringBuilder stringBuilder = new StringBuilder();
final Iterator<CommandPermission> iterator = this.permissions.iterator();
while (iterator.hasNext()) {
final CommandPermission permission = iterator.next();
stringBuilder.append('(').append(permission.toString()).append(')');
if (iterator.hasNext()) {
stringBuilder.append('|');
}
}
return stringBuilder.toString();
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final OrPermission that = (OrPermission) o;
return Objects.equals(getPermissions(), that.getPermissions());
}
@Override
public int hashCode() {
return Objects.hash(getPermissions());
}
}

View file

@ -0,0 +1,112 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
package com.intellectualsites.commands.permission;
import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
/**
* {@link com.intellectualsites.commands.arguments.CommandArgument} permission
*/
public final class Permission implements CommandPermission {
/**
* Empty command permission
*/
private static final Permission EMPTY = Permission.of("");
private final String permission;
private Permission(@Nonnull final String permission) {
this.permission = permission;
}
/**
* Get an empty command permission
*
* @return Command permission
*/
@Nonnull
public static Permission empty() {
return EMPTY;
}
/**
* Create a command permission instance
*
* @param string Command permission
* @return Created command permission
*/
@Nonnull
public static Permission of(@Nonnull final String string) {
return new Permission(string);
}
/**
* Get the command permission
*
* @return Command permission
*/
@Nonnull
public String getPermission() {
return this.permission;
}
@Nonnull
@Override
public Collection<CommandPermission> getPermissions() {
return Collections.singleton(this);
}
/**
* Get the command permission
*
* @return Command permission
*/
@Nonnull
@Override
public String toString() {
return this.permission;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final Permission that = (Permission) o;
return Objects.equals(getPermission(), that.getPermission());
}
@Override
public int hashCode() {
return Objects.hash(getPermission());
}
}

View file

@ -0,0 +1,28 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
/**
* Command permissions
*/
package com.intellectualsites.commands.permission;

View file

@ -0,0 +1,71 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
package com.intellectualsites.commands;
import com.intellectualsites.commands.execution.CommandExecutionCoordinator;
import com.intellectualsites.commands.meta.CommandMeta;
import com.intellectualsites.commands.meta.SimpleCommandMeta;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import javax.annotation.Nonnull;
class CommandPermissionTest {
private final static CommandManager<TestCommandSender> manager = new PermissionOutputtingCommandManager();
@BeforeAll
static void setup() {
manager.command(manager.commandBuilder("test").literal("foo").withPermission("test.permission.one").build());
manager.command(manager.commandBuilder("test").literal("bar").withPermission("test.permission.two").build());
manager.command(manager.commandBuilder("test").literal("fizz").withPermission("test.permission.three").build());
manager.command(manager.commandBuilder("test").literal("buzz").withPermission("test.permission.four").build());
}
@Test
void testCompoundPermission() {
Assertions.assertTrue(manager.suggest(new TestCommandSender(), "").isEmpty());
}
private static final class PermissionOutputtingCommandManager extends CommandManager<TestCommandSender> {
public PermissionOutputtingCommandManager() {
super(CommandExecutionCoordinator.simpleCoordinator(), cmd -> true);
}
@Override
public boolean hasPermission(@Nonnull final TestCommandSender sender,
@Nonnull final String permission) {
return false;
}
@Nonnull
@Override
public CommandMeta createDefaultCommandMeta() {
return SimpleCommandMeta.empty();
}
}
}

View file

@ -40,6 +40,8 @@ import com.intellectualsites.commands.arguments.standard.ShortArgument;
import com.intellectualsites.commands.arguments.standard.StringArgument;
import com.intellectualsites.commands.context.CommandContext;
import com.intellectualsites.commands.execution.preprocessor.CommandPreprocessingContext;
import com.intellectualsites.commands.permission.CommandPermission;
import com.intellectualsites.commands.permission.Permission;
import com.mojang.brigadier.LiteralMessage;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.arguments.BoolArgumentType;
@ -243,14 +245,15 @@ public final class CloudBrigadierManager<C, S> {
*/
public LiteralCommandNode<S> createLiteralCommandNode(@Nonnull final String label,
@Nonnull final Command<C> cloudCommand,
@Nonnull final BiPredicate<S, String> permissionChecker,
@Nonnull final BiPredicate<S, CommandPermission> permissionChecker,
@Nonnull final com.mojang.brigadier.Command<S> executor) {
final CommandTree.Node<CommandArgument<C, ?>> node = this.commandManager
.getCommandTree().getNamedNode(cloudCommand.getArguments().get(0).getName());
final SuggestionProvider<S> provider = (context, builder) -> this.buildSuggestions(node.getValue(), context, builder);
final LiteralArgumentBuilder<S> literalArgumentBuilder = LiteralArgumentBuilder
.<S>literal(label)
.requires(sender -> permissionChecker.test(sender, node.getNodeMeta().getOrDefault("permission", "")));
.requires(sender -> permissionChecker.test(sender, (CommandPermission) node.getNodeMeta()
.getOrDefault("permission", Permission.empty())));
literalArgumentBuilder.executes(executor);
final LiteralCommandNode<S> constructedRoot = literalArgumentBuilder.build();
for (final CommandTree.Node<CommandArgument<C, ?>> child : node.getChildren()) {
@ -275,9 +278,10 @@ public final class CloudBrigadierManager<C, S> {
@Nonnull final LiteralCommandNode<S> root,
@Nonnull final SuggestionProvider<S> suggestionProvider,
@Nonnull final com.mojang.brigadier.Command<S> executor,
@Nonnull final BiPredicate<S, String> permissionChecker) {
@Nonnull final BiPredicate<S, CommandPermission> permissionChecker) {
final LiteralArgumentBuilder<S> literalArgumentBuilder = LiteralArgumentBuilder.<S>literal(root.getLiteral())
.requires(sender -> permissionChecker.test(sender, cloudCommand.getNodeMeta().getOrDefault("permission", "")));
.requires(sender -> permissionChecker.test(sender, (CommandPermission) cloudCommand.getNodeMeta()
.getOrDefault("permission", Permission.empty())));
if (cloudCommand.isLeaf() && cloudCommand.getValue() != null) {
literalArgumentBuilder.executes(executor);
}
@ -291,14 +295,15 @@ public final class CloudBrigadierManager<C, S> {
private ArgumentBuilder<S, ?> constructCommandNode(final boolean forceExecutor,
@Nonnull final CommandTree.Node<CommandArgument<C, ?>> root,
@Nonnull final BiPredicate<S, String> permissionChecker,
@Nonnull final BiPredicate<S, CommandPermission> permissionChecker,
@Nonnull final com.mojang.brigadier.Command<S> executor,
@Nonnull final SuggestionProvider<S> suggestionProvider) {
ArgumentBuilder<S, ?> argumentBuilder;
if (root.getValue() instanceof StaticArgument) {
argumentBuilder = LiteralArgumentBuilder.<S>literal(root.getValue().getName())
.requires(sender -> permissionChecker.test(sender, root.getNodeMeta().getOrDefault("permission", "")))
.requires(sender -> permissionChecker.test(sender, (CommandPermission) root.getNodeMeta()
.getOrDefault("permission", Permission.empty())))
.executes(executor);
} else {
final Pair<ArgumentType<?>, Boolean> pair = this.getArgument(root.getValue().getValueType(),
@ -308,7 +313,8 @@ public final class CloudBrigadierManager<C, S> {
argumentBuilder = RequiredArgumentBuilder
.<S, Object>argument(root.getValue().getName(), (ArgumentType<Object>) pair.getLeft())
.suggests(provider)
.requires(sender -> permissionChecker.test(sender, root.getNodeMeta().getOrDefault("permission", "")));
.requires(sender -> permissionChecker.test(sender, (CommandPermission) root.getNodeMeta()
.getOrDefault("permission", Permission.empty())));
}
if (forceExecutor || root.isLeaf() || !root.getValue().isRequired()) {
argumentBuilder.executes(executor);

View file

@ -152,7 +152,7 @@ final class BukkitCommand<C> extends org.bukkit.command.Command implements Plugi
@Override
public String getPermission() {
return this.cloudCommand.getCommandPermission();
return this.cloudCommand.getCommandPermission().toString();
}
}

View file

@ -57,6 +57,7 @@ class CloudCommodoreManager<C> extends BukkitPluginRegistrationHandler<C> {
final com.mojang.brigadier.Command<?> cmd = o -> 1;
final LiteralCommandNode<?> literalCommandNode = this.brigadierManager
.createLiteralCommandNode(label, command, (o, p) -> true, cmd);
this.commodore.register(bukkitCommand, literalCommandNode, p -> p.hasPermission(command.getCommandPermission()));
this.commodore.register(bukkitCommand, literalCommandNode, p ->
p.hasPermission(command.getCommandPermission().toString()));
}
}

View file

@ -55,7 +55,7 @@ public final class BungeeCommand<C> extends Command implements TabExecutor {
@Nonnull final CommandArgument<C, ?> command,
@Nonnull final BungeeCommandManager<C> manager) {
super(command.getName(),
cloudCommand.getCommandPermission(),
cloudCommand.getCommandPermission().toString(),
((StaticArgument<C>) command).getAlternativeAliases().toArray(new String[0]));
this.command = command;
this.manager = manager;

View file

@ -56,7 +56,7 @@ final class CloudburstCommand<C> extends PluginCommand<Plugin> {
@Nonnull final CloudburstCommandManager<C> manager) {
super(manager.getOwningPlugin(), CommandData.builder(label)
.addAliases(aliases.toArray(new String[0]))
.addPermission(cloudCommand.getCommandPermission())
.addPermission(cloudCommand.getCommandPermission().toString())
.setDescription(cloudCommand.getCommandMeta().getOrDefault("description", ""))
.build());
this.command = command;

View file

@ -128,8 +128,8 @@ class PaperBrigadierListener<C> implements Listener {
event.getLiteral(),
event.getBrigadierCommand(),
event.getBrigadierCommand(),
(s, p) -> p.isEmpty()
|| s.getBukkitSender().hasPermission(p)));
(s, p) -> p.toString().isEmpty()
|| s.getBukkitSender().hasPermission(p.toString())));
}
}