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.components.StaticComponent;
|
||||||
import com.intellectualsites.commands.context.CommandContext;
|
import com.intellectualsites.commands.context.CommandContext;
|
||||||
import com.intellectualsites.commands.exceptions.InvalidSyntaxException;
|
import com.intellectualsites.commands.exceptions.InvalidSyntaxException;
|
||||||
|
import com.intellectualsites.commands.exceptions.NoPermissionException;
|
||||||
import com.intellectualsites.commands.exceptions.NoSuchCommandException;
|
import com.intellectualsites.commands.exceptions.NoSuchCommandException;
|
||||||
import com.intellectualsites.commands.internal.CommandRegistrationHandler;
|
import com.intellectualsites.commands.internal.CommandRegistrationHandler;
|
||||||
import com.intellectualsites.commands.components.parser.ComponentParseResult;
|
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,
|
private Optional<Command<C>> parseCommand(@Nonnull final CommandContext<C> commandContext,
|
||||||
@Nonnull final Queue<String> commandQueue,
|
@Nonnull final Queue<String> commandQueue,
|
||||||
@Nonnull final Node<CommandComponent<C, ?>> root) {
|
@Nonnull final Node<CommandComponent<C, ?>> root) {
|
||||||
if (!this.isPermitted(commandContext.getCommandSender(), root)) {
|
String permission;
|
||||||
/* TODO: Send not allowed */
|
if ((permission = this.isPermitted(commandContext.getCommandSender(), root)) != null) {
|
||||||
throw new RuntimeException("Nope!");
|
throw new NoPermissionException(permission, commandContext.getCommandSender(), this.getChain(root)
|
||||||
|
.stream()
|
||||||
|
.map(Node::getValue)
|
||||||
|
.collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
final List<Node<CommandComponent<C, ?>>> children = root.getChildren();
|
final List<Node<CommandComponent<C, ?>>> children = root.getChildren();
|
||||||
if (children.size() == 1 && !(children.get(0).getValue() instanceof StaticComponent)) {
|
if (children.size() == 1 && !(children.get(0).getValue() instanceof StaticComponent)) {
|
||||||
// The value has to be a variable
|
// The value has to be a variable
|
||||||
final Node<CommandComponent<C, ?>> child = children.get(0);
|
final Node<CommandComponent<C, ?>> child = children.get(0);
|
||||||
if (!this.isPermitted(commandContext.getCommandSender(), child)) {
|
if ((permission = this.isPermitted(commandContext.getCommandSender(), child)) != null) {
|
||||||
/* TODO: Send not allowed */
|
throw new NoPermissionException(permission, commandContext.getCommandSender(), this.getChain(child)
|
||||||
throw new RuntimeException("Nope!");
|
.stream()
|
||||||
|
.map(Node::getValue)
|
||||||
|
.collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
if (child.getValue() != null) {
|
if (child.getValue() != null) {
|
||||||
if (commandQueue.isEmpty()) {
|
if (commandQueue.isEmpty()) {
|
||||||
|
|
@ -204,7 +210,7 @@ public class CommandTree<C extends CommandSender> {
|
||||||
@Nonnull final Node<CommandComponent<C, ?>> root) {
|
@Nonnull final Node<CommandComponent<C, ?>> root) {
|
||||||
|
|
||||||
/* If the sender isn't allowed to access the root node, no suggestions are needed */
|
/* 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();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
final List<Node<CommandComponent<C, ?>>> children = root.getChildren();
|
final List<Node<CommandComponent<C, ?>>> children = root.getChildren();
|
||||||
|
|
@ -254,7 +260,7 @@ public class CommandTree<C extends CommandSender> {
|
||||||
}
|
}
|
||||||
final List<String> suggestions = new LinkedList<>();
|
final List<String> suggestions = new LinkedList<>();
|
||||||
for (final Node<CommandComponent<C, ?>> component : root.getChildren()) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
suggestions.addAll(
|
suggestions.addAll(
|
||||||
|
|
@ -297,25 +303,31 @@ public class CommandTree<C extends CommandSender> {
|
||||||
this.verifyAndRegister();
|
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");
|
final String permission = node.nodeMeta.get("permission");
|
||||||
if (permission != null) {
|
if (permission != null) {
|
||||||
return sender.hasPermission(permission);
|
return sender.hasPermission(permission) ? null : permission;
|
||||||
}
|
}
|
||||||
if (node.isLeaf()) {
|
if (node.isLeaf()) {
|
||||||
// noinspection all
|
// 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
|
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
|
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()) {
|
for (final Node<CommandComponent<C, ?>> child : node.getChildren()) {
|
||||||
if (this.isPermitted(sender, child)) {
|
final String check = this.isPermitted(sender, child);
|
||||||
return true;
|
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