Improve permission checks and throw permission exceptions when the caller lacks permissions
This commit is contained in:
parent
a8d3fa7c5e
commit
cbe7771b63
2 changed files with 84 additions and 14 deletions
|
|
@ -27,6 +27,7 @@ import com.intellectualsites.commands.components.CommandComponent;
|
|||
import com.intellectualsites.commands.components.StaticComponent;
|
||||
import com.intellectualsites.commands.context.CommandContext;
|
||||
import com.intellectualsites.commands.exceptions.InvalidSyntaxException;
|
||||
import com.intellectualsites.commands.exceptions.NoPermissionException;
|
||||
import com.intellectualsites.commands.exceptions.NoSuchCommandException;
|
||||
import com.intellectualsites.commands.internal.CommandRegistrationHandler;
|
||||
import com.intellectualsites.commands.components.parser.ComponentParseResult;
|
||||
|
|
@ -86,17 +87,22 @@ public class CommandTree<C extends CommandSender> {
|
|||
private Optional<Command<C>> parseCommand(@Nonnull final CommandContext<C> commandContext,
|
||||
@Nonnull final Queue<String> commandQueue,
|
||||
@Nonnull final Node<CommandComponent<C, ?>> root) {
|
||||
if (!this.isPermitted(commandContext.getCommandSender(), root)) {
|
||||
/* TODO: Send not allowed */
|
||||
throw new RuntimeException("Nope!");
|
||||
String permission;
|
||||
if ((permission = this.isPermitted(commandContext.getCommandSender(), root)) != null) {
|
||||
throw new NoPermissionException(permission, commandContext.getCommandSender(), this.getChain(root)
|
||||
.stream()
|
||||
.map(Node::getValue)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
final List<Node<CommandComponent<C, ?>>> children = root.getChildren();
|
||||
if (children.size() == 1 && !(children.get(0).getValue() instanceof StaticComponent)) {
|
||||
// The value has to be a variable
|
||||
final Node<CommandComponent<C, ?>> child = children.get(0);
|
||||
if (!this.isPermitted(commandContext.getCommandSender(), child)) {
|
||||
/* TODO: Send not allowed */
|
||||
throw new RuntimeException("Nope!");
|
||||
if ((permission = this.isPermitted(commandContext.getCommandSender(), child)) != null) {
|
||||
throw new NoPermissionException(permission, commandContext.getCommandSender(), this.getChain(child)
|
||||
.stream()
|
||||
.map(Node::getValue)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
if (child.getValue() != null) {
|
||||
if (commandQueue.isEmpty()) {
|
||||
|
|
@ -204,7 +210,7 @@ public class CommandTree<C extends CommandSender> {
|
|||
@Nonnull final Node<CommandComponent<C, ?>> root) {
|
||||
|
||||
/* If the sender isn't allowed to access the root node, no suggestions are needed */
|
||||
if (!this.isPermitted(commandContext.getCommandSender(), root)) {
|
||||
if (this.isPermitted(commandContext.getCommandSender(), root) != null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final List<Node<CommandComponent<C, ?>>> children = root.getChildren();
|
||||
|
|
@ -254,7 +260,7 @@ public class CommandTree<C extends CommandSender> {
|
|||
}
|
||||
final List<String> suggestions = new LinkedList<>();
|
||||
for (final Node<CommandComponent<C, ?>> component : root.getChildren()) {
|
||||
if (component.getValue() == null || !this.isPermitted(commandContext.getCommandSender(), component)) {
|
||||
if (component.getValue() == null || this.isPermitted(commandContext.getCommandSender(), component) != null) {
|
||||
continue;
|
||||
}
|
||||
suggestions.addAll(
|
||||
|
|
@ -297,25 +303,31 @@ public class CommandTree<C extends CommandSender> {
|
|||
this.verifyAndRegister();
|
||||
}
|
||||
|
||||
private boolean isPermitted(@Nonnull final C sender, @Nonnull final Node<CommandComponent<C, ?>> node) {
|
||||
@Nullable
|
||||
private String isPermitted(@Nonnull final C sender, @Nonnull final Node<CommandComponent<C, ?>> node) {
|
||||
final String permission = node.nodeMeta.get("permission");
|
||||
if (permission != null) {
|
||||
return sender.hasPermission(permission);
|
||||
return sender.hasPermission(permission) ? null : permission;
|
||||
}
|
||||
if (node.isLeaf()) {
|
||||
// noinspection all
|
||||
return sender.hasPermission(node.value.getOwningCommand().getCommandPermission());
|
||||
return sender.hasPermission(node.value.getOwningCommand().getCommandPermission())
|
||||
? null : node.value.getOwningCommand().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<>();
|
||||
for (final Node<CommandComponent<C, ?>> child : node.getChildren()) {
|
||||
if (this.isPermitted(sender, child)) {
|
||||
return true;
|
||||
final String check = this.isPermitted(sender, child);
|
||||
if (check == null) {
|
||||
return null;
|
||||
} else {
|
||||
missingPermissions.add(check);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return String.join(", ", missingPermissions);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
//
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020 IntellectualSites
|
||||
//
|
||||
// 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.exceptions;
|
||||
|
||||
import com.intellectualsites.commands.components.CommandComponent;
|
||||
import com.intellectualsites.commands.sender.CommandSender;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Exception thrown when a {@link CommandSender} misses a permission required
|
||||
* to execute a {@link com.intellectualsites.commands.Command}
|
||||
*/
|
||||
public class NoPermissionException extends CommandParseException {
|
||||
|
||||
private final String missingPermission;
|
||||
|
||||
public NoPermissionException(@Nonnull final String missingPermission,
|
||||
@Nonnull final CommandSender commandSender,
|
||||
@Nonnull final List<CommandComponent<?, ?>> currentChain) {
|
||||
super(commandSender, currentChain);
|
||||
this.missingPermission = missingPermission;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return String.format("Missing permission '%s'", this.missingPermission);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getMissingPermission() {
|
||||
return this.missingPermission;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue