Tweaks to command permissions
This commit is contained in:
@@ -3,6 +3,7 @@ package io.dico.dicore.command;
|
|||||||
import io.dico.dicore.exceptions.checkedfunctions.CheckedConsumer;
|
import io.dico.dicore.exceptions.checkedfunctions.CheckedConsumer;
|
||||||
import io.dico.dicore.exceptions.checkedfunctions.CheckedRunnable;
|
import io.dico.dicore.exceptions.checkedfunctions.CheckedRunnable;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -52,10 +53,11 @@ public interface IContextFilter extends Comparable<IContextFilter> {
|
|||||||
* @return comparison value
|
* @return comparison value
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
default int compareTo(IContextFilter o) {
|
default int compareTo(@NotNull IContextFilter o) {
|
||||||
return getPriority().compareTo(o.getPriority());
|
return getPriority().compareTo(o.getPriority());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
default boolean isInheritable() {
|
default boolean isInheritable() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -66,7 +68,7 @@ public interface IContextFilter extends Comparable<IContextFilter> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IContextFilter priorities. Executes from top to bottom.
|
* IContextFilter priorities. Executes from top to bottom.
|
||||||
@@ -110,6 +112,8 @@ public interface IContextFilter extends Comparable<IContextFilter> {
|
|||||||
*/
|
*/
|
||||||
POST_PARAMETERS;
|
POST_PARAMETERS;
|
||||||
|
|
||||||
|
private IContextFilter inheritor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the context filter that inherits context filters from the parent of the same priority.
|
* Get the context filter that inherits context filters from the parent of the same priority.
|
||||||
* If this filter is also present at the parent, it will do the same for the parent's parent, and so on.
|
* If this filter is also present at the parent, it will do the same for the parent's parent, and so on.
|
||||||
@@ -117,56 +121,12 @@ public interface IContextFilter extends Comparable<IContextFilter> {
|
|||||||
* @return the inheritor
|
* @return the inheritor
|
||||||
*/
|
*/
|
||||||
public IContextFilter getInheritor() {
|
public IContextFilter getInheritor() {
|
||||||
|
if (inheritor == null) {
|
||||||
|
inheritor = InheritingContextFilter.inheritingPriority(this);
|
||||||
|
}
|
||||||
return inheritor;
|
return inheritor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String[] addParent(String[] path, String parent) {
|
|
||||||
String[] out = new String[path.length + 1];
|
|
||||||
System.arraycopy(path, 0, out, 0, path.length);
|
|
||||||
out[0] = parent;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
final IContextFilter inheritor = new IContextFilter() {
|
|
||||||
@Override
|
|
||||||
public void filterContext(ExecutionContext context) throws CommandException {
|
|
||||||
ICommandAddress address = context.getAddress();
|
|
||||||
|
|
||||||
String[] traversedPath = new String[0];
|
|
||||||
do {
|
|
||||||
traversedPath = addParent(traversedPath, address.getMainKey());
|
|
||||||
address = address.getParent();
|
|
||||||
|
|
||||||
if (address != null && address.hasCommand()) {
|
|
||||||
boolean doBreak = true;
|
|
||||||
|
|
||||||
Command command = address.getCommand();
|
|
||||||
List<IContextFilter> contextFilterList = command.getContextFilters();
|
|
||||||
for (IContextFilter filter : contextFilterList) {
|
|
||||||
if (filter.getPriority() == Priority.this) {
|
|
||||||
if (filter == this) {
|
|
||||||
// do the same for next parent
|
|
||||||
// this method is necessary to keep traversedPath information
|
|
||||||
doBreak = false;
|
|
||||||
} else {
|
|
||||||
filter.filterSubContext(context, traversedPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doBreak) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (address != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Priority getPriority() {
|
|
||||||
return Priority.this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -215,14 +175,15 @@ public interface IContextFilter extends Comparable<IContextFilter> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static IContextFilter permission(String permission) {
|
static IContextFilter permission(String permission) {
|
||||||
Objects.requireNonNull(permission);
|
return new PermissionContextFilter(permission);
|
||||||
return filterSender(Priority.PERMISSION, sender -> Validate.isAuthorized(sender, permission));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static IContextFilter permission(String permission, String failMessage) {
|
static IContextFilter permission(String permission, String failMessage) {
|
||||||
Objects.requireNonNull(permission);
|
return new PermissionContextFilter(permission, failMessage);
|
||||||
Objects.requireNonNull(failMessage);
|
}
|
||||||
return filterSender(Priority.PERMISSION, sender -> Validate.isAuthorized(sender, permission, failMessage));
|
|
||||||
|
static IContextFilter inheritablePermission(String permission) {
|
||||||
|
return new PermissionContextFilter(permission, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -236,87 +197,8 @@ public interface IContextFilter extends Comparable<IContextFilter> {
|
|||||||
* @throws IllegalArgumentException if componentInsertionIndex is out of range
|
* @throws IllegalArgumentException if componentInsertionIndex is out of range
|
||||||
*/
|
*/
|
||||||
static IContextFilter inheritablePermission(String permission, int componentInsertionIndex, String failMessage) {
|
static IContextFilter inheritablePermission(String permission, int componentInsertionIndex, String failMessage) {
|
||||||
Objects.requireNonNull(permission);
|
return new PermissionContextFilter(permission, componentInsertionIndex, failMessage);
|
||||||
Objects.requireNonNull(failMessage);
|
|
||||||
if (componentInsertionIndex > permission.split("\\.").length || componentInsertionIndex < -1) {
|
|
||||||
throw new IllegalArgumentException("componentInsertionIndex out of range");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return new IContextFilter() {
|
|
||||||
private String getInheritedPermission(String[] components) {
|
|
||||||
int insertedAmount = components.length;
|
|
||||||
String[] currentComponents = permission.split("\\.");
|
|
||||||
int currentAmount = currentComponents.length;
|
|
||||||
String[] targetArray = new String[currentAmount + insertedAmount];
|
|
||||||
|
|
||||||
int insertionIndex;
|
|
||||||
//int newInsertionIndex;
|
|
||||||
if (componentInsertionIndex == -1) {
|
|
||||||
insertionIndex = currentAmount;
|
|
||||||
//newInsertionIndex = -1;
|
|
||||||
} else {
|
|
||||||
insertionIndex = componentInsertionIndex;
|
|
||||||
//newInsertionIndex = insertionIndex + insertedAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy the current components up to insertionIndex
|
|
||||||
System.arraycopy(currentComponents, 0, targetArray, 0, insertionIndex);
|
|
||||||
// copy the new components into the array at insertionIndex
|
|
||||||
System.arraycopy(components, 0, targetArray, insertionIndex, insertedAmount);
|
|
||||||
// copy the current components from insertionIndex + inserted amount
|
|
||||||
System.arraycopy(currentComponents, insertionIndex, targetArray, insertionIndex + insertedAmount, currentAmount - insertionIndex);
|
|
||||||
|
|
||||||
return String.join(".", targetArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void filterContext(ExecutionContext context) throws CommandException {
|
|
||||||
Validate.isAuthorized(context.getSender(), permission, failMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void filterSubContext(ExecutionContext subContext, String... path) throws CommandException {
|
|
||||||
Validate.isAuthorized(subContext.getSender(), getInheritedPermission(path), failMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Priority getPriority() {
|
|
||||||
return Priority.PERMISSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isInheritable() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IContextFilter inherit(String... components) {
|
|
||||||
int insertedAmount = components.length;
|
|
||||||
String[] currentComponents = permission.split("\\.");
|
|
||||||
int currentAmount = currentComponents.length;
|
|
||||||
String[] targetArray = new String[currentAmount + insertedAmount];
|
|
||||||
|
|
||||||
int insertionIndex;
|
|
||||||
int newInsertionIndex;
|
|
||||||
if (componentInsertionIndex == -1) {
|
|
||||||
insertionIndex = currentAmount;
|
|
||||||
newInsertionIndex = -1;
|
|
||||||
} else {
|
|
||||||
insertionIndex = componentInsertionIndex;
|
|
||||||
newInsertionIndex = insertionIndex + insertedAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy the current components up to insertionIndex
|
|
||||||
System.arraycopy(currentComponents, 0, targetArray, 0, insertionIndex);
|
|
||||||
// copy the new components into the array at insertionIndex
|
|
||||||
System.arraycopy(components, 0, targetArray, insertionIndex, insertedAmount);
|
|
||||||
// copy the current components from insertionIndex + inserted amount
|
|
||||||
System.arraycopy(currentComponents, insertionIndex, targetArray, insertionIndex + insertedAmount, currentAmount - insertionIndex);
|
|
||||||
|
|
||||||
return inheritablePermission(String.join(".", targetArray), newInsertionIndex, failMessage);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class InheritingContextFilter implements IContextFilter {
|
||||||
|
private static final String[] emptyStringArray = new String[0];
|
||||||
|
|
||||||
|
private static String[] addParent(String[] path, String parent) {
|
||||||
|
String[] out = new String[path.length + 1];
|
||||||
|
System.arraycopy(path, 0, out, 0, path.length);
|
||||||
|
out[0] = parent;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract boolean isInherited(IContextFilter filter);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void filterContext(ExecutionContext context) throws CommandException {
|
||||||
|
ICommandAddress address = context.getAddress();
|
||||||
|
|
||||||
|
String[] traversedPath = emptyStringArray;
|
||||||
|
do {
|
||||||
|
traversedPath = addParent(traversedPath, address.getMainKey());
|
||||||
|
address = address.getParent();
|
||||||
|
|
||||||
|
if (address != null && address.hasCommand()) {
|
||||||
|
boolean doBreak = true;
|
||||||
|
|
||||||
|
Command command = address.getCommand();
|
||||||
|
List<IContextFilter> contextFilterList = command.getContextFilters();
|
||||||
|
for (IContextFilter filter : contextFilterList) {
|
||||||
|
if (isInherited(filter)) {
|
||||||
|
if (filter == this) {
|
||||||
|
// do the same for next parent
|
||||||
|
// this method is necessary to keep traversedPath information
|
||||||
|
doBreak = false;
|
||||||
|
} else {
|
||||||
|
filter.filterSubContext(context, traversedPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doBreak) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (address != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static InheritingContextFilter inheritingPriority(Priority priority) {
|
||||||
|
return new InheritingContextFilter() {
|
||||||
|
@Override
|
||||||
|
protected boolean isInherited(IContextFilter filter) {
|
||||||
|
return filter.getPriority() == priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Priority getPriority() {
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class PermissionContextFilter implements IContextFilter {
|
||||||
|
private String permission;
|
||||||
|
private String[] permissionComponents;
|
||||||
|
private int componentInsertionIndex;
|
||||||
|
private String failMessage;
|
||||||
|
|
||||||
|
public PermissionContextFilter(String permission) {
|
||||||
|
this.permission = Objects.requireNonNull(permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PermissionContextFilter(String permission, String failMessage) {
|
||||||
|
this(permission);
|
||||||
|
this.failMessage = failMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PermissionContextFilter(String permission, boolean inheritable) {
|
||||||
|
this(permission, null, inheritable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PermissionContextFilter(String permission, String failMessage, boolean inheritable) {
|
||||||
|
this(permission, failMessage);
|
||||||
|
if (inheritable) {
|
||||||
|
setupInheritability(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PermissionContextFilter(String permission, int componentInsertionIndex, String failMessage) {
|
||||||
|
this(permission, failMessage);
|
||||||
|
setupInheritability(componentInsertionIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupInheritability(int componentInsertionIndex) {
|
||||||
|
this.permissionComponents = permission.split("\\.");
|
||||||
|
this.componentInsertionIndex = componentInsertionIndex < 0 ? permissionComponents.length : componentInsertionIndex;
|
||||||
|
if (componentInsertionIndex > permissionComponents.length) throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doFilter(ExecutionContext context, String permission) throws CommandException {
|
||||||
|
if (failMessage != null) {
|
||||||
|
Validate.isAuthorized(context.getSender(), permission, failMessage);
|
||||||
|
} else {
|
||||||
|
Validate.isAuthorized(context.getSender(), permission);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void filterContext(ExecutionContext context) throws CommandException {
|
||||||
|
doFilter(context, permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getInheritedPermission(String[] components) {
|
||||||
|
int insertedAmount = components.length;
|
||||||
|
String[] currentComponents = permissionComponents;
|
||||||
|
int currentAmount = currentComponents.length;
|
||||||
|
String[] targetArray = new String[currentAmount + insertedAmount];
|
||||||
|
|
||||||
|
int insertionIndex;
|
||||||
|
//int newInsertionIndex;
|
||||||
|
if (componentInsertionIndex == -1) {
|
||||||
|
insertionIndex = currentAmount;
|
||||||
|
//newInsertionIndex = -1;
|
||||||
|
} else {
|
||||||
|
insertionIndex = componentInsertionIndex;
|
||||||
|
//newInsertionIndex = insertionIndex + insertedAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy the current components up to insertionIndex
|
||||||
|
System.arraycopy(currentComponents, 0, targetArray, 0, insertionIndex);
|
||||||
|
// copy the new components into the array at insertionIndex
|
||||||
|
System.arraycopy(components, 0, targetArray, insertionIndex, insertedAmount);
|
||||||
|
// copy the current components from insertionIndex + inserted amount
|
||||||
|
System.arraycopy(currentComponents, insertionIndex, targetArray, insertionIndex + insertedAmount, currentAmount - insertionIndex);
|
||||||
|
|
||||||
|
return String.join(".", targetArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void filterSubContext(ExecutionContext subContext, String... path) throws CommandException {
|
||||||
|
if (permissionComponents != null) {
|
||||||
|
doFilter(subContext, getInheritedPermission(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Priority getPriority() {
|
||||||
|
return Priority.PERMISSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -350,7 +350,7 @@ public class ReflectiveRegistration {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
String flagPermission = flag == null ? null : flag.permission();
|
String flagPermission = flag == null || flag.permission().isEmpty() ? null : flag.permission();
|
||||||
return new Parameter<>(name, descString, parameterType, parameterInfo, type.isPrimitive(), name.startsWith("-"), flagPermission);
|
return new Parameter<>(name, descString, parameterType, parameterInfo, type.isPrimitive(), name.startsWith("-"), flagPermission);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new CommandParseException("Invalid parameter", ex);
|
throw new CommandParseException("Invalid parameter", ex);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import org.bukkit.Bukkit
|
|||||||
import org.bukkit.Material
|
import org.bukkit.Material
|
||||||
import org.bukkit.block.BlockFace
|
import org.bukkit.block.BlockFace
|
||||||
import org.bukkit.block.data.Directional
|
import org.bukkit.block.data.Directional
|
||||||
|
import org.bukkit.command.CommandSender
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
import java.util.Random
|
import java.util.Random
|
||||||
|
|
||||||
@@ -86,7 +87,12 @@ class CommandsDebug(plugin: ParcelsPlugin) : AbstractParcelCommands(plugin) {
|
|||||||
fun cmdForceVisitors(): Any? {
|
fun cmdForceVisitors(): Any? {
|
||||||
val workers = plugin.workDispatcher.workers
|
val workers = plugin.workDispatcher.workers
|
||||||
plugin.workDispatcher.completeAllTasks()
|
plugin.workDispatcher.completeAllTasks()
|
||||||
return "Task count: ${workers.size}"
|
return "Completed task count: ${workers.size}"
|
||||||
|
}
|
||||||
|
|
||||||
|
@Cmd("hasperm")
|
||||||
|
fun cmdHasperm(sender: CommandSender, target: Player, permission: String): Any? {
|
||||||
|
return target.hasPermission(permission).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -9,8 +9,7 @@ import java.util.LinkedList
|
|||||||
import java.util.Queue
|
import java.util.Queue
|
||||||
|
|
||||||
@Suppress("UsePropertyAccessSyntax")
|
@Suppress("UsePropertyAccessSyntax")
|
||||||
fun getParcelCommands(plugin: ParcelsPlugin): ICommandDispatcher =
|
fun getParcelCommands(plugin: ParcelsPlugin): ICommandDispatcher = CommandBuilder().apply {
|
||||||
with(CommandBuilder()) {
|
|
||||||
val parcelsAddress = SpecialCommandAddress()
|
val parcelsAddress = SpecialCommandAddress()
|
||||||
|
|
||||||
setChatController(ParcelsChatController())
|
setChatController(ParcelsChatController())
|
||||||
@@ -19,7 +18,7 @@ fun getParcelCommands(plugin: ParcelsPlugin): ICommandDispatcher =
|
|||||||
addParameterType(true, ParcelTarget.PType(plugin.parcelProvider, parcelsAddress))
|
addParameterType(true, ParcelTarget.PType(plugin.parcelProvider, parcelsAddress))
|
||||||
|
|
||||||
group(parcelsAddress, "parcel", "plot", "plots", "p") {
|
group(parcelsAddress, "parcel", "plot", "plots", "p") {
|
||||||
addRequiredPermission("parcels.command")
|
addContextFilter(IContextFilter.inheritablePermission("parcels.command"))
|
||||||
registerCommands(CommandsGeneral(plugin, parcelsAddress))
|
registerCommands(CommandsGeneral(plugin, parcelsAddress))
|
||||||
registerCommands(CommandsPrivilegesLocal(plugin))
|
registerCommands(CommandsPrivilegesLocal(plugin))
|
||||||
|
|
||||||
@@ -53,9 +52,8 @@ fun getParcelCommands(plugin: ParcelsPlugin): ICommandDispatcher =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
generateHelpAndSyntaxCommands()
|
generateHelpAndSyntaxCommands(parcelsAddress)
|
||||||
getDispatcher()
|
}.getDispatcher()
|
||||||
}
|
|
||||||
|
|
||||||
inline fun CommandBuilder.group(name: String, vararg aliases: String, config: CommandBuilder.() -> Unit) {
|
inline fun CommandBuilder.group(name: String, vararg aliases: String, config: CommandBuilder.() -> Unit) {
|
||||||
group(name, *aliases)
|
group(name, *aliases)
|
||||||
@@ -69,8 +67,8 @@ inline fun CommandBuilder.group(address: ICommandAddress, name: String, vararg a
|
|||||||
parent()
|
parent()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CommandBuilder.generateHelpAndSyntaxCommands(): CommandBuilder {
|
private fun CommandBuilder.generateHelpAndSyntaxCommands(root: ICommandAddress): CommandBuilder {
|
||||||
generateCommands(dispatcher as ICommandAddress, "help", "syntax")
|
generateCommands(root, "help", "syntax")
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ class ParcelOptionsInteractCommand(val parcelProvider: ParcelProvider) : Command
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
addContextFilter(IContextFilter.PLAYER_ONLY)
|
addContextFilter(IContextFilter.PLAYER_ONLY)
|
||||||
|
addContextFilter(IContextFilter.INHERIT_PERMISSIONS)
|
||||||
addParameter("allowed", "allowed", ParameterTypes.BOOLEAN)
|
addParameter("allowed", "allowed", ParameterTypes.BOOLEAN)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user