Refactor perms and upstream (#35)

* refactor permissions

* upstream

* remove shutdown from the command list

* make FabricWorldManager#getPlayer() private
This commit is contained in:
Konicai 2021-10-31 19:46:51 -04:00 committed by GitHub
parent 29fa4a9443
commit 3f88f20272
6 changed files with 93 additions and 19 deletions

View File

@ -67,9 +67,14 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap {
private GeyserConnector connector;
private Path dataFolder;
private List<String> playerCommands;
private MinecraftServer server;
/**
* Commands that don't require any permission level to ran
*/
private List<String> playerCommands;
private final List<GeyserFabricCommandExecutor> commandExecutors = new ArrayList<>();
private GeyserFabricCommandManager geyserCommandManager;
private GeyserFabricConfiguration geyserConfig;
private GeyserFabricLogger geyserLogger;
@ -167,14 +172,17 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap {
// Start command building
// Set just "geyser" as the help command
LiteralArgumentBuilder<ServerCommandSource> builder = net.minecraft.server.command.CommandManager.literal("geyser")
.executes(new GeyserFabricCommandExecutor(connector, connector.getCommandManager().getCommands().get("help"),
!playerCommands.contains("help")));
GeyserFabricCommandExecutor helpExecutor = new GeyserFabricCommandExecutor(connector,
connector.getCommandManager().getCommands().get("help"), !playerCommands.contains("help"));
commandExecutors.add(helpExecutor);
LiteralArgumentBuilder<ServerCommandSource> builder = net.minecraft.server.command.CommandManager.literal("geyser").executes(helpExecutor);
// Register all subcommands as valid
for (Map.Entry<String, GeyserCommand> 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.getValue(),
!playerCommands.contains(command.getKey()))));
GeyserFabricCommandExecutor executor = new GeyserFabricCommandExecutor(connector, command.getValue(),
!playerCommands.contains(command.getKey()));
commandExecutors.add(executor);
builder.then(net.minecraft.server.command.CommandManager.literal(command.getKey()).executes(executor));
}
server.getCommandManager().getDispatcher().register(builder);
}
@ -258,6 +266,10 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap {
return file;
}
public List<GeyserFabricCommandExecutor> getCommandExecutors() {
return commandExecutors;
}
public static GeyserFabricMod getInstance() {
return instance;
}

View File

@ -25,6 +25,7 @@
package org.geysermc.platform.fabric;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@ -34,6 +35,12 @@ import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class GeyserFabricPermissions {
/**
* The minimum permission level a command source must have in order for it to run commands that are restricted
*/
@JsonIgnore
public static final int RESTRICTED_MIN_LEVEL = 2;
@JsonProperty("commands")
private String[] commands;

View File

@ -31,6 +31,7 @@ import net.minecraft.text.LiteralText;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.CommandSender;
import org.geysermc.connector.common.ChatColor;
import org.geysermc.platform.fabric.GeyserFabricMod;
public class FabricCommandSender implements CommandSender {
@ -58,4 +59,18 @@ public class FabricCommandSender implements CommandSender {
public boolean isConsole() {
return !(source.getEntity() instanceof ServerPlayerEntity);
}
@Override
public boolean hasPermission(String s) {
// Mostly copied from fabric's world manager since the method there takes a GeyserSession
// Workaround for our commands because fabric doesn't have native permissions
for (GeyserFabricCommandExecutor executor : GeyserFabricMod.getInstance().getCommandExecutors()) {
if (executor.getCommand().getPermission().equals(s)) {
return executor.canRun(source);
}
}
return false;
}
}

View File

@ -35,6 +35,7 @@ import org.geysermc.connector.common.ChatColor;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.utils.LanguageUtils;
import org.geysermc.platform.fabric.GeyserFabricMod;
import org.geysermc.platform.fabric.GeyserFabricPermissions;
public class GeyserFabricCommandExecutor extends CommandExecutor implements Command<ServerCommandSource> {
@ -50,11 +51,22 @@ public class GeyserFabricCommandExecutor extends CommandExecutor implements Comm
this.requiresPermission = requiresPermission;
}
/**
* Determine whether or not a command source is allowed to run a given executor.
*
* @param source The command source attempting to run the command
* @return True if the command source is allowed to
*/
public boolean canRun(ServerCommandSource source) {
return !requiresPermission() || source.hasPermissionLevel(GeyserFabricPermissions.RESTRICTED_MIN_LEVEL);
}
@Override
public int run(CommandContext context) {
ServerCommandSource source = (ServerCommandSource) context.getSource();
FabricCommandSender sender = new FabricCommandSender(source);
if (requiresPermission && !source.hasPermissionLevel(2)) {
GeyserSession session = getGeyserSession(sender);
if (!canRun(source)) {
sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.bootstrap.command.permission_fail"));
return 0;
}
@ -62,15 +74,22 @@ public class GeyserFabricCommandExecutor extends CommandExecutor implements Comm
GeyserFabricMod.getInstance().setReloading(true);
}
GeyserSession session = null;
if (command.isBedrockOnly()) {
session = getGeyserSession(sender);
if (session == null) {
sender.sendMessage(ChatColor.RED + LanguageUtils.getPlayerLocaleString("geyser.bootstrap.command.bedrock_only", sender.getLocale()));
return 0;
}
if (command.isBedrockOnly() && session == null) {
sender.sendMessage(ChatColor.RED + LanguageUtils.getPlayerLocaleString("geyser.bootstrap.command.bedrock_only", sender.getLocale()));
return 0;
}
command.execute(session, sender, new String[0]);
return 0;
}
public GeyserCommand getCommand() {
return command;
}
/**
* Returns whether the command requires permission level of {@link GeyserFabricPermissions#RESTRICTED_MIN_LEVEL} or higher to be ran
*/
public boolean requiresPermission() {
return requiresPermission;
}
}

View File

@ -42,6 +42,8 @@ import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.inventory.translators.LecternInventoryTranslator;
import org.geysermc.connector.network.translators.world.GeyserWorldManager;
import org.geysermc.connector.utils.BlockEntityUtils;
import org.geysermc.platform.fabric.GeyserFabricMod;
import org.geysermc.platform.fabric.command.GeyserFabricCommandExecutor;
import java.util.ArrayList;
import java.util.List;
@ -63,7 +65,7 @@ public class GeyserFabricWorldManager extends GeyserWorldManager {
public NbtMap getLecternDataAt(GeyserSession session, int x, int y, int z, boolean isChunkLoad) {
Runnable lecternGet = () -> {
// Mostly a reimplementation of Spigot lectern support
PlayerEntity player = server.getPlayerManager().getPlayer(session.getPlayerEntity().getUuid());
PlayerEntity player = getPlayer(session);
if (player != null) {
BlockEntity blockEntity = player.world.getBlockEntity(new BlockPos(x, y, z));
if (!(blockEntity instanceof LecternBlockEntity lectern)) {
@ -119,4 +121,21 @@ public class GeyserFabricWorldManager extends GeyserWorldManager {
}
return LecternInventoryTranslator.getBaseLecternTag(x, y, z, 0).build();
}
@Override
public boolean hasPermission(GeyserSession session, String permission) {
// Workaround for our commands because fabric doesn't have native permissions
for (GeyserFabricCommandExecutor executor : GeyserFabricMod.getInstance().getCommandExecutors()) {
if (executor.getCommand().getPermission().equals(permission)) {
return executor.canRun(getPlayer(session).getCommandSource());
}
}
return false;
}
private PlayerEntity getPlayer(GeyserSession session) {
return server.getPlayerManager().getPlayer(session.getPlayerEntity().getUuid());
}
}

View File

@ -1,10 +1,12 @@
# Uncomment any commands that you wish to be run by clients
# Commented commands require an OP permission of 2 or greater
commands:
# - dump
- help
- advancements
- statistics
- settings
- offhand
# - list
# - reload
# - shutdown
# - version
# - dump