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.CheckedRunnable;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
@@ -52,10 +53,11 @@ public interface IContextFilter extends Comparable<IContextFilter> {
|
||||
* @return comparison value
|
||||
*/
|
||||
@Override
|
||||
default int compareTo(IContextFilter o) {
|
||||
default int compareTo(@NotNull IContextFilter o) {
|
||||
return getPriority().compareTo(o.getPriority());
|
||||
}
|
||||
|
||||
/*
|
||||
default boolean isInheritable() {
|
||||
return false;
|
||||
}
|
||||
@@ -66,7 +68,7 @@ public interface IContextFilter extends Comparable<IContextFilter> {
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* IContextFilter priorities. Executes from top to bottom.
|
||||
@@ -110,6 +112,8 @@ public interface IContextFilter extends Comparable<IContextFilter> {
|
||||
*/
|
||||
POST_PARAMETERS;
|
||||
|
||||
private IContextFilter inheritor;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -117,56 +121,12 @@ public interface IContextFilter extends Comparable<IContextFilter> {
|
||||
* @return the inheritor
|
||||
*/
|
||||
public IContextFilter getInheritor() {
|
||||
if (inheritor == null) {
|
||||
inheritor = InheritingContextFilter.inheritingPriority(this);
|
||||
}
|
||||
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) {
|
||||
Objects.requireNonNull(permission);
|
||||
return filterSender(Priority.PERMISSION, sender -> Validate.isAuthorized(sender, permission));
|
||||
return new PermissionContextFilter(permission);
|
||||
}
|
||||
|
||||
static IContextFilter permission(String permission, String failMessage) {
|
||||
Objects.requireNonNull(permission);
|
||||
Objects.requireNonNull(failMessage);
|
||||
return filterSender(Priority.PERMISSION, sender -> Validate.isAuthorized(sender, permission, failMessage));
|
||||
return new PermissionContextFilter(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
|
||||
*/
|
||||
static IContextFilter inheritablePermission(String permission, int componentInsertionIndex, String failMessage) {
|
||||
Objects.requireNonNull(permission);
|
||||
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);
|
||||
}
|
||||
};
|
||||
return new PermissionContextFilter(permission, componentInsertionIndex, 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 {
|
||||
//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);
|
||||
} catch (Exception ex) {
|
||||
throw new CommandParseException("Invalid parameter", ex);
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.bukkit.Bukkit
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.block.BlockFace
|
||||
import org.bukkit.block.data.Directional
|
||||
import org.bukkit.command.CommandSender
|
||||
import org.bukkit.entity.Player
|
||||
import java.util.Random
|
||||
|
||||
@@ -86,7 +87,12 @@ class CommandsDebug(plugin: ParcelsPlugin) : AbstractParcelCommands(plugin) {
|
||||
fun cmdForceVisitors(): Any? {
|
||||
val workers = plugin.workDispatcher.workers
|
||||
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,54 +9,52 @@ import java.util.LinkedList
|
||||
import java.util.Queue
|
||||
|
||||
@Suppress("UsePropertyAccessSyntax")
|
||||
fun getParcelCommands(plugin: ParcelsPlugin): ICommandDispatcher =
|
||||
with(CommandBuilder()) {
|
||||
val parcelsAddress = SpecialCommandAddress()
|
||||
fun getParcelCommands(plugin: ParcelsPlugin): ICommandDispatcher = CommandBuilder().apply {
|
||||
val parcelsAddress = SpecialCommandAddress()
|
||||
|
||||
setChatController(ParcelsChatController())
|
||||
addParameterType(false, ParcelParameterType(plugin.parcelProvider))
|
||||
addParameterType(false, ProfileParameterType())
|
||||
addParameterType(true, ParcelTarget.PType(plugin.parcelProvider, parcelsAddress))
|
||||
setChatController(ParcelsChatController())
|
||||
addParameterType(false, ParcelParameterType(plugin.parcelProvider))
|
||||
addParameterType(false, ProfileParameterType())
|
||||
addParameterType(true, ParcelTarget.PType(plugin.parcelProvider, parcelsAddress))
|
||||
|
||||
group(parcelsAddress, "parcel", "plot", "plots", "p") {
|
||||
addRequiredPermission("parcels.command")
|
||||
registerCommands(CommandsGeneral(plugin, parcelsAddress))
|
||||
registerCommands(CommandsPrivilegesLocal(plugin))
|
||||
group(parcelsAddress, "parcel", "plot", "plots", "p") {
|
||||
addContextFilter(IContextFilter.inheritablePermission("parcels.command"))
|
||||
registerCommands(CommandsGeneral(plugin, parcelsAddress))
|
||||
registerCommands(CommandsPrivilegesLocal(plugin))
|
||||
|
||||
group("option", "opt", "o") {
|
||||
setGroupDescription(
|
||||
"changes interaction options for this parcel",
|
||||
"Sets whether players who are not allowed to",
|
||||
"build here can interact with certain things."
|
||||
)
|
||||
group("option", "opt", "o") {
|
||||
setGroupDescription(
|
||||
"changes interaction options for this parcel",
|
||||
"Sets whether players who are not allowed to",
|
||||
"build here can interact with certain things."
|
||||
)
|
||||
|
||||
group("interact", "i") {
|
||||
val command = ParcelOptionsInteractCommand(plugin.parcelProvider)
|
||||
Interactables.classesById.forEach {
|
||||
addSubCommand(it.name, command)
|
||||
}
|
||||
group("interact", "i") {
|
||||
val command = ParcelOptionsInteractCommand(plugin.parcelProvider)
|
||||
Interactables.classesById.forEach {
|
||||
addSubCommand(it.name, command)
|
||||
}
|
||||
}
|
||||
|
||||
group("global", "g") {
|
||||
registerCommands(CommandsPrivilegesGlobal(plugin))
|
||||
}
|
||||
|
||||
group("admin", "a") {
|
||||
registerCommands(CommandsAdmin(plugin))
|
||||
}
|
||||
|
||||
if (!logger.isDebugEnabled) return@group
|
||||
|
||||
group("debug", "d") {
|
||||
registerCommands(CommandsDebug(plugin))
|
||||
}
|
||||
}
|
||||
|
||||
generateHelpAndSyntaxCommands()
|
||||
getDispatcher()
|
||||
group("global", "g") {
|
||||
registerCommands(CommandsPrivilegesGlobal(plugin))
|
||||
}
|
||||
|
||||
group("admin", "a") {
|
||||
registerCommands(CommandsAdmin(plugin))
|
||||
}
|
||||
|
||||
if (!logger.isDebugEnabled) return@group
|
||||
|
||||
group("debug", "d") {
|
||||
registerCommands(CommandsDebug(plugin))
|
||||
}
|
||||
}
|
||||
|
||||
generateHelpAndSyntaxCommands(parcelsAddress)
|
||||
}.getDispatcher()
|
||||
|
||||
inline fun CommandBuilder.group(name: String, vararg aliases: String, config: CommandBuilder.() -> Unit) {
|
||||
group(name, *aliases)
|
||||
config()
|
||||
@@ -69,8 +67,8 @@ inline fun CommandBuilder.group(address: ICommandAddress, name: String, vararg a
|
||||
parent()
|
||||
}
|
||||
|
||||
private fun CommandBuilder.generateHelpAndSyntaxCommands(): CommandBuilder {
|
||||
generateCommands(dispatcher as ICommandAddress, "help", "syntax")
|
||||
private fun CommandBuilder.generateHelpAndSyntaxCommands(root: ICommandAddress): CommandBuilder {
|
||||
generateCommands(root, "help", "syntax")
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ class ParcelOptionsInteractCommand(val parcelProvider: ParcelProvider) : Command
|
||||
|
||||
init {
|
||||
addContextFilter(IContextFilter.PLAYER_ONLY)
|
||||
addContextFilter(IContextFilter.INHERIT_PERMISSIONS)
|
||||
addParameter("allowed", "allowed", ParameterTypes.BOOLEAN)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user