allow apps define their own command permission level, fixes #542

This commit is contained in:
gnembon committed 2020-12-07 16:03:42 -04:00
1 parent c7554c888e
commit f54a098948
3 files changed
+74 -8

No files matched your search

@@ -11,6 +11,7 @@ import carpet.script.exception.CarpetExpressionException;
import carpet.script.exception.ExpressionException;
import carpet.script.exception.InternalExpressionException;
import carpet.script.exception.InvalidCallbackException;
import carpet.script.value.EntityValue;
import carpet.script.value.FunctionValue;
import carpet.script.value.MapValue;
import carpet.script.value.NumericValue;
@@ -38,6 +39,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -163,8 +165,9 @@ public class CarpetScriptHost extends ScriptHost
) throws CommandSyntaxException
{
String hostName = main.getName();
Function<ServerCommandSource, Boolean> configValidator = getCommandConfigPermissions();
LiteralArgumentBuilder<ServerCommandSource> command = literal(hostName).
requires((player) -> CarpetServer.scriptServer.modules.containsKey(hostName) && useValidator.apply(player));
requires((player) -> CarpetServer.scriptServer.modules.containsKey(hostName) && useValidator.apply(player) && configValidator.apply(player));
for (Pair<List<CommandToken>,FunctionArgument<Value>> commandData : entries)
{
command = this.addPathToCommand(command, commandData.getKey(), commandData.getValue());
@@ -172,6 +175,49 @@ public class CarpetScriptHost extends ScriptHost
return command;
}
public Function<ServerCommandSource, Boolean> getCommandConfigPermissions() throws CommandSyntaxException
{
Value confValue = appConfig.get(StringValue.of("command_permission"));
if (confValue == null) return s -> true;
if (confValue instanceof NumericValue)
{
int level = ((NumericValue) confValue).getInt();
if (level < 1 || level > 4) throw CommandArgument.error("Numeric permission level for custom commands should be between 1 and 4");
return s -> s.hasPermissionLevel(level);
}
if (!(confValue instanceof FunctionValue))
{
String perm = confValue.getString().toLowerCase(Locale.ROOT);
switch (perm)
{
case "ops": return s -> s.hasPermissionLevel(2);
case "server": return s -> !(s.getEntity() instanceof ServerPlayerEntity);
case "players": return s -> s.getEntity() instanceof ServerPlayerEntity;
case "all": return s -> true;
default: throw CommandArgument.error("Unknown command permission: "+perm);
}
}
FunctionValue fun = (FunctionValue) confValue;
if (fun.getNumParams() != 1) throw CommandArgument.error("Custom command permission function should expect 1 argument");
String hostName = getName();
return s -> {
try
{
CarpetScriptHost cHost = null;
cHost = CarpetServer.scriptServer.modules.get(hostName).retrieveOwnForExecution(s);
Value response = cHost.handleCommand(s, fun, Collections.singletonList(
(s.getEntity() instanceof ServerPlayerEntity)?new EntityValue(s.getEntity()):Value.NULL)
);
return response.getBoolean();
}
catch (CommandSyntaxException e)
{
Messenger.m(s, "rb Unable to run app command: "+e.getMessage());
return false;
}
};
}
@Override
protected ScriptHost duplicate()
{
@@ -221,7 +221,6 @@ public class CarpetScriptServer
public boolean addScriptHost(ServerCommandSource source, String name, Function<ServerCommandSource, Boolean> commandValidator,
boolean perPlayer, boolean autoload, boolean isRuleApp)
{
//TODO add per player modules to support player actions better on a server
if (commandValidator == null) commandValidator = p -> true;
long start = System.nanoTime();
name = name.toLowerCase(Locale.ROOT);
@@ -325,8 +324,19 @@ public class CarpetScriptServer
return true;
}
Function<ServerCommandSource, Boolean> configValidator;
try
{
configValidator = host.getCommandConfigPermissions();
}
catch (CommandSyntaxException e)
{
Messenger.m(source, "rb "+e.getMessage());
return false;
}
LiteralArgumentBuilder<ServerCommandSource> command = literal(hostName).
requires((player) -> modules.containsKey(hostName) && useValidator.apply(player)).
requires((player) -> modules.containsKey(hostName) && useValidator.apply(player) && configValidator.apply(player)).
executes( (c) ->
{
CarpetScriptHost targetHost = modules.get(hostName).retrieveOwnForExecution(c.getSource());