Skip to content

Commit

Permalink
Permission improvements
Browse files Browse the repository at this point in the history
- The standard command permission is now granted by default (battlearena.command.<command>)
- User is informed they do not have permission when attempting to execute a subcommand
- If a server admin wishes to fully hide or disable the base command, simply setting the permission value to false for the base permission will now hide it from tab complete, rather than this being the default behavior
- Wildcards are now supported (i.e. battlearena.command.arena.*)
  • Loading branch information
Redned235 committed Dec 5, 2024
1 parent def9524 commit 785e451
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 12 deletions.
3 changes: 3 additions & 0 deletions plugin/src/main/java/org/battleplugins/arena/ArenaLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.battleplugins.arena.config.ParseException;
import org.battleplugins.arena.event.arena.ArenaCreateExecutorEvent;
import org.battleplugins.arena.event.arena.ArenaInitializeEvent;
import org.battleplugins.arena.util.CommandInjector;
import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand;
import org.bukkit.configuration.Configuration;
Expand Down Expand Up @@ -46,6 +47,8 @@ public void load() {

command.setExecutor(executor);

CommandInjector.registerPermissions(arena.getName().toLowerCase(Locale.ROOT), executor);

new ArenaInitializeEvent(arena).callEvent();

this.battleArena.info("Loaded arena: {}.", arena.getName());
Expand Down
2 changes: 2 additions & 0 deletions plugin/src/main/java/org/battleplugins/arena/BattleArena.java
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,8 @@ public Set<ModuleLoadException> getFailedModules() {
public void registerExecutor(String commandName, BaseCommandExecutor executor, String... aliases) {
PluginCommand command = CommandInjector.inject(commandName, commandName.toLowerCase(Locale.ROOT), aliases);
command.setExecutor(executor);

CommandInjector.registerPermissions(commandName.toLowerCase(Locale.ROOT), executor);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public class BaseCommandExecutor implements TabExecutor {
protected final String parentCommand;
protected final String permissionSubNode;

private final Map<String, Set<CommandWrapper>> commandMethods = new HashMap<>();
private final Map<String, Set<CommandWrapper>> commandWrappers = new HashMap<>();

private final List<SubCommandExecutor> subCommandExecutors = new ArrayList<>();

Expand Down Expand Up @@ -142,20 +142,20 @@ private void registerCommands() {

CommandWrapper wrapper = new CommandWrapper(this, method, this.getUsage(method));
for (String cmd : arenaCommand.commands()) {
Set<CommandWrapper> wrappers = this.commandMethods.getOrDefault(cmd, new HashSet<>());
Set<CommandWrapper> wrappers = this.commandWrappers.getOrDefault(cmd, new HashSet<>());
wrappers.add(wrapper);

this.commandMethods.put(cmd, wrappers);
this.commandWrappers.put(cmd, wrappers);
}
}
}

public void injectWrapper(CommandWrapper wrapper) {
for (String cmd : wrapper.getCommand().commands()) {
Set<CommandWrapper> wrappers = this.commandMethods.getOrDefault(cmd, new HashSet<>());
Set<CommandWrapper> wrappers = this.commandWrappers.getOrDefault(cmd, new HashSet<>());
wrappers.add(wrapper);

this.commandMethods.put(cmd, wrappers);
this.commandWrappers.put(cmd, wrappers);
}
}

Expand Down Expand Up @@ -317,7 +317,7 @@ public void sendHeader(CommandSender sender) {
public void sendHelpMessage(CommandSender sender, int page) {
// Compile all the command arguments
Map<String, CommandWrapper> commandWrappers = new HashMap<>();
for (Map.Entry<String, Set<CommandWrapper>> entry : this.commandMethods.entrySet()) {
for (Map.Entry<String, Set<CommandWrapper>> entry : this.commandWrappers.entrySet()) {
for (CommandWrapper wrapper : entry.getValue()) {
commandWrappers.put(wrapper.usage, wrapper);
}
Expand Down Expand Up @@ -404,8 +404,8 @@ public void sendUsageMessage(CommandSender sender, Method method) {
private List<CommandWrapper> getCommandWrappers(String command, String subCommand) {
List<CommandWrapper> wrappers = new ArrayList<>();

for (String cmd : this.commandMethods.keySet()) {
for (CommandWrapper wrapper : this.commandMethods.get(cmd)) {
for (String cmd : this.commandWrappers.keySet()) {
for (CommandWrapper wrapper : this.commandWrappers.get(cmd)) {
ArenaCommand arenaCommand = wrapper.getCommand();

if (!Arrays.asList(arenaCommand.commands()).contains(command)) {
Expand Down Expand Up @@ -658,8 +658,8 @@ public final List<String> onTabComplete(CommandSender sender, Command command, S
try {
if (args.length == 1) {
List<String> commands = new ArrayList<>();
for (String cmd : this.commandMethods.keySet()) {
CommandWrapper wrapper = this.commandMethods.get(cmd).iterator().next();
for (String cmd : this.commandWrappers.keySet()) {
CommandWrapper wrapper = this.commandWrappers.get(cmd).iterator().next();
ArenaCommand arenaCommand = wrapper.getCommand();

if (!arenaCommand.permissionNode().isEmpty() && !this.hasPermission(sender, this.getPermissionNode(arenaCommand.permissionNode()))) {
Expand All @@ -677,7 +677,7 @@ public final List<String> onTabComplete(CommandSender sender, Command command, S
}

if (args.length > 1) {
Set<CommandWrapper> wrappers = this.commandMethods.get(args[0]);
Set<CommandWrapper> wrappers = this.commandWrappers.get(args[0]);
for (CommandWrapper wrapper : wrappers) {
ArenaCommand arenaCommand = wrapper.getCommand();
if (!arenaCommand.permissionNode().isEmpty() && !this.hasPermission(sender, this.getPermissionNode(arenaCommand.permissionNode()))) {
Expand Down Expand Up @@ -714,7 +714,11 @@ public final List<String> onTabComplete(CommandSender sender, Command command, S
return completions;
}

protected String getPermissionNode(String node) {
public Map<String, Set<CommandWrapper>> getCommandWrappers() {
return this.commandWrappers;
}

public String getPermissionNode(String node) {
return "battlearena.command." + (this.permissionSubNode == null ? "" : this.permissionSubNode + ".") + node;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
package org.battleplugins.arena.util;

import org.battleplugins.arena.BattleArena;
import org.battleplugins.arena.command.BaseCommandExecutor;
import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

public class CommandInjector {

Expand All @@ -31,4 +39,48 @@ public static PluginCommand inject(String headerName, String commandName, String
throw new RuntimeException("Failed to construct PluginCommand " + headerName, e);
}
}

public static void registerPermissions(String commandName, BaseCommandExecutor executor) {
String rootPermissionNode = "battlearena.command." + commandName.toLowerCase(Locale.ROOT);
String wildcardPermissionNode = rootPermissionNode + ".*";

PluginManager pluginManager = Bukkit.getServer().getPluginManager();

// Register the root permission so it shows up in things such as LuckPerms UI.
// Set to true by default so the user can see the command, however this is intentionally
// done so server owners can fully revoke the permission, and it will not show up in tab complete.
Permission rootPermission = pluginManager.getPermission(rootPermissionNode);
if (rootPermission == null) {
pluginManager.addPermission(rootPermission = new Permission(rootPermissionNode, PermissionDefault.TRUE));
}

Permission wildcardPermission = pluginManager.getPermission(wildcardPermissionNode);
if (wildcardPermission == null) {
pluginManager.addPermission(wildcardPermission = new Permission(wildcardPermissionNode, PermissionDefault.OP));
}

Set<String> childPermissions = new HashSet<>();
for (Map.Entry<String, Set<BaseCommandExecutor.CommandWrapper>> entry : executor.getCommandWrappers().entrySet()) {
for (BaseCommandExecutor.CommandWrapper wrapper : entry.getValue()) {
String node = wrapper.getCommand().permissionNode();
String permissionNode = executor.getPermissionNode(node);

// Add our permission node to the parent permission
if (permissionNode != null) {
childPermissions.add(permissionNode);
}
}
}

// Add all child permissions to the parent permission
for (String childPermissionNode : childPermissions) {
Permission childPermission = pluginManager.getPermission(childPermissionNode);
if (childPermission == null) {
pluginManager.addPermission(childPermission = new Permission(childPermissionNode, PermissionDefault.OP));
}

// For wildcard permissions, set to true as we want all permissions granted when the wildcard is present
childPermission.addParent(wildcardPermission, true);
}
}
}

0 comments on commit 785e451

Please sign in to comment.