Archived
0

Tweaks to command permissions

This commit is contained in:
Dico
2018-09-26 09:58:37 +01:00
parent 520ae530d2
commit e7dcf7ecc9
7 changed files with 221 additions and 177 deletions

View File

@@ -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);
}
}

View File

@@ -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;
}
};
}
}

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -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()
}
}

View File

@@ -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
}

View File

@@ -15,6 +15,7 @@ class ParcelOptionsInteractCommand(val parcelProvider: ParcelProvider) : Command
init {
addContextFilter(IContextFilter.PLAYER_ONLY)
addContextFilter(IContextFilter.INHERIT_PERMISSIONS)
addParameter("allowed", "allowed", ParameterTypes.BOOLEAN)
}