From ae3896d1d00c731417d9a4a08a158abea8a6978b Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Wed, 7 Oct 2020 22:42:17 -0400 Subject: [PATCH] Add command permissions system --- .../platform/fabric/GeyserFabricDumpInfo.java | 1 - .../platform/fabric/GeyserFabricMod.java | 38 +++++++++++++++-- .../fabric/GeyserFabricPermissions.java | 42 +++++++++++++++++++ .../fabric/{command => }/ModInfo.java | 2 +- .../command/GeyserFabricCommandExecutor.java | 15 ++++++- .../src/main/resources/fabric.mixins.json | 13 ------ .../fabric/src/main/resources/fabric.mod.json | 3 -- .../fabric/src/main/resources/permissions.yml | 10 +++++ 8 files changed, 100 insertions(+), 24 deletions(-) create mode 100644 bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/GeyserFabricPermissions.java rename bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/{command => }/ModInfo.java (97%) delete mode 100644 bootstrap/fabric/src/main/resources/fabric.mixins.json create mode 100644 bootstrap/fabric/src/main/resources/permissions.yml diff --git a/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/GeyserFabricDumpInfo.java b/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/GeyserFabricDumpInfo.java index 2c9917de9..1b9d68a9c 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/GeyserFabricDumpInfo.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/GeyserFabricDumpInfo.java @@ -31,7 +31,6 @@ import net.fabricmc.loader.api.ModContainer; import net.minecraft.server.MinecraftServer; import org.geysermc.connector.common.serializer.AsteriskSerializer; import org.geysermc.connector.dump.BootstrapDumpInfo; -import org.geysermc.platform.fabric.command.ModInfo; import java.util.ArrayList; import java.util.List; diff --git a/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/GeyserFabricMod.java b/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/GeyserFabricMod.java index c5058a130..0e395dcee 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/GeyserFabricMod.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/GeyserFabricMod.java @@ -50,16 +50,19 @@ import org.geysermc.platform.fabric.command.GeyserFabricCommandExecutor; import org.geysermc.platform.fabric.command.GeyserFabricCommandManager; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.nio.file.Path; -import java.util.Map; -import java.util.UUID; +import java.util.*; +import java.util.function.Function; @Environment(EnvType.SERVER) public class GeyserFabricMod implements DedicatedServerModInitializer, GeyserBootstrap { private GeyserConnector connector; private Path dataFolder; + private List playerCommands; private MinecraftServer server; private GeyserFabricCommandManager geyserCommandManager; @@ -83,6 +86,8 @@ public class GeyserFabricMod implements DedicatedServerModInitializer, GeyserBoo File configFile = FileUtils.fileOrCopiedFromResource(dataFolder.resolve("config.yml").toFile(), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString())); this.geyserConfig = FileUtils.loadConfig(configFile, GeyserFabricConfiguration.class); + File permissionsFile = fileOrCopiedFromResource(dataFolder.resolve("permissions.yml").toFile(), "permissions.yml"); + this.playerCommands = Arrays.asList(FileUtils.loadConfig(permissionsFile, GeyserFabricPermissions.class).getCommands()); } catch (IOException ex) { LogManager.getLogger("geyser-fabric").error(LanguageUtils.getLocaleStringLog("geyser.config.failed"), ex); ex.printStackTrace(); @@ -118,11 +123,12 @@ public class GeyserFabricMod implements DedicatedServerModInitializer, GeyserBoo // Start command building // Set just "geyser" as the help command LiteralArgumentBuilder builder = net.minecraft.server.command.CommandManager.literal("geyser") - .executes(new GeyserFabricCommandExecutor(connector, "help")); + .executes(new GeyserFabricCommandExecutor(connector, "help", !playerCommands.contains("help"))); for (Map.Entry command : connector.getCommandManager().getCommands().entrySet()) { // Register all subcommands as valid builder.then(net.minecraft.server.command.CommandManager.literal( - command.getKey()).executes(new GeyserFabricCommandExecutor(connector, command.getKey()))); + command.getKey()).executes(new GeyserFabricCommandExecutor(connector, command.getKey(), + !playerCommands.contains(command.getKey())))); } server.getCommandManager().getDispatcher().register(builder); }); @@ -167,4 +173,28 @@ public class GeyserFabricMod implements DedicatedServerModInitializer, GeyserBoo public BootstrapDumpInfo getDumpInfo() { return new GeyserFabricDumpInfo(server); } + + private File fileOrCopiedFromResource(File file, String name) throws IOException { + if (!file.exists()) { + //noinspection ResultOfMethodCallIgnored + file.createNewFile(); + FileOutputStream fos = new FileOutputStream(file); + InputStream input = GeyserFabricMod.class.getResourceAsStream("/" + name); // resources need leading "/" prefix + + byte[] bytes = new byte[input.available()]; + + //noinspection ResultOfMethodCallIgnored + input.read(bytes); + + for(char c : new String(bytes).toCharArray()) { + fos.write(c); + } + + fos.flush(); + input.close(); + fos.close(); + } + + return file; + } } diff --git a/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/GeyserFabricPermissions.java b/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/GeyserFabricPermissions.java new file mode 100644 index 000000000..51a7cb2e4 --- /dev/null +++ b/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/GeyserFabricPermissions.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020 GeyserMC. http://geysermc.org + * + * 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. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.platform.fabric; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; + +/** + * A class outline of the permissions.yml file + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class GeyserFabricPermissions { + + @Getter + @JsonProperty("commands") + private String[] commands; + +} diff --git a/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/command/ModInfo.java b/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/ModInfo.java similarity index 97% rename from bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/command/ModInfo.java rename to bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/ModInfo.java index 722fd2ded..159678766 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/command/ModInfo.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/ModInfo.java @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.platform.fabric.command; +package org.geysermc.platform.fabric; import lombok.Getter; import net.fabricmc.loader.api.ModContainer; diff --git a/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/command/GeyserFabricCommandExecutor.java b/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/command/GeyserFabricCommandExecutor.java index 290e452c6..1064af3a9 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/command/GeyserFabricCommandExecutor.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/platform/fabric/command/GeyserFabricCommandExecutor.java @@ -30,21 +30,32 @@ import com.mojang.brigadier.context.CommandContext; import net.minecraft.server.command.ServerCommandSource; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.GeyserCommand; +import org.geysermc.connector.utils.LanguageUtils; public class GeyserFabricCommandExecutor implements Command { private final String commandName; private final GeyserConnector connector; + /** + * Whether the command requires an OP permission level of 2 or greater + */ + private final boolean requiresPermission; - public GeyserFabricCommandExecutor(GeyserConnector connector, String commandName) { + public GeyserFabricCommandExecutor(GeyserConnector connector, String commandName, boolean requiresPermission) { this.commandName = commandName; this.connector = connector; + this.requiresPermission = requiresPermission; } @Override public int run(CommandContext context) { ServerCommandSource source = (ServerCommandSource) context.getSource(); - getCommand(commandName).execute(new FabricCommandSender(source), new String[0]); + FabricCommandSender sender = new FabricCommandSender(source); + if (requiresPermission && !source.hasPermissionLevel(2)) { + sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.bootstrap.command.permission_fail")); + return 0; + } + getCommand(commandName).execute(sender, new String[0]); return 0; } diff --git a/bootstrap/fabric/src/main/resources/fabric.mixins.json b/bootstrap/fabric/src/main/resources/fabric.mixins.json deleted file mode 100644 index a1f71d182..000000000 --- a/bootstrap/fabric/src/main/resources/fabric.mixins.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "required": true, - "minVersion": "0.8", - "package": "org.geysermc.platform.fabric.mixin", - "compatibilityLevel": "JAVA_8", - "mixins": [ - ], - "client": [ - ], - "injectors": { - "defaultRequire": 1 - } -} diff --git a/bootstrap/fabric/src/main/resources/fabric.mod.json b/bootstrap/fabric/src/main/resources/fabric.mod.json index 10defc82d..1655cc212 100644 --- a/bootstrap/fabric/src/main/resources/fabric.mod.json +++ b/bootstrap/fabric/src/main/resources/fabric.mod.json @@ -19,9 +19,6 @@ "org.geysermc.platform.fabric.GeyserFabricMod" ] }, - "mixins": [ - "fabric.mixins.json" - ], "depends": { "fabricloader": ">=0.10.1+build.209", "fabric": "*", diff --git a/bootstrap/fabric/src/main/resources/permissions.yml b/bootstrap/fabric/src/main/resources/permissions.yml new file mode 100644 index 000000000..a51d3169a --- /dev/null +++ b/bootstrap/fabric/src/main/resources/permissions.yml @@ -0,0 +1,10 @@ +# Uncomment any commands that you wish to be run by clients +# Commented commands require an OP permission of 2 or greater +commands: +# - dump + - help + - offhand +# - list +# - reload +# - shutdown +# - version