From ed9dd031cb28ef76af3330c7f0271a1db6f126be Mon Sep 17 00:00:00 2001 From: Luck Date: Wed, 28 Dec 2022 22:49:41 +0000 Subject: [PATCH] Add basic rate-limit for commands (#3546) --- .../lucko/luckperms/common/command/CommandManager.java | 10 ++++++++++ .../me/lucko/luckperms/common/config/ConfigKeys.java | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/common/src/main/java/me/lucko/luckperms/common/command/CommandManager.java b/common/src/main/java/me/lucko/luckperms/common/command/CommandManager.java index 3443eff42..c5be1966a 100644 --- a/common/src/main/java/me/lucko/luckperms/common/command/CommandManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/command/CommandManager.java @@ -58,6 +58,7 @@ import me.lucko.luckperms.common.commands.track.DeleteTrack; import me.lucko.luckperms.common.commands.track.ListTracks; import me.lucko.luckperms.common.commands.track.TrackParentCommand; import me.lucko.luckperms.common.commands.user.UserParentCommand; +import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.locale.Message; import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.plugin.AbstractLuckPermsPlugin; @@ -65,6 +66,7 @@ import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter; import me.lucko.luckperms.common.plugin.scheduler.SchedulerTask; import me.lucko.luckperms.common.sender.Sender; +import me.lucko.luckperms.common.util.ExpiringSet; import me.lucko.luckperms.common.util.ImmutableCollectors; import net.kyori.adventure.text.Component; @@ -78,6 +80,7 @@ import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -99,6 +102,7 @@ public class CommandManager { .build() ); private final AtomicBoolean executingCommand = new AtomicBoolean(false); + private final ExpiringSet playerRateLimit = new ExpiringSet<>(500, TimeUnit.MILLISECONDS); private final TabCompletions tabCompletions; private final Map> mainCommands; @@ -145,6 +149,12 @@ public class CommandManager { } public CompletableFuture executeCommand(Sender sender, String label, List args) { + UUID uniqueId = sender.getUniqueId(); + if (this.plugin.getConfiguration().get(ConfigKeys.COMMANDS_RATE_LIMIT) && !sender.isConsole() && !this.playerRateLimit.add(uniqueId)) { + this.plugin.getLogger().warn("Player '" + uniqueId + "' is spamming LuckPerms commands. Ignoring further inputs."); + return CompletableFuture.completedFuture(null); + } + SchedulerAdapter scheduler = this.plugin.getBootstrap().getScheduler(); List argsCopy = new ArrayList<>(args); diff --git a/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java b/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java index 140817177..17b2d7b48 100644 --- a/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java +++ b/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java @@ -464,6 +464,11 @@ public final class ConfigKeys { */ public static final ConfigKey COMMANDS_ALLOW_OP = notReloadable(booleanKey("commands-allow-op", true)); + /** + * If LuckPerms should rate-limit command executions. + */ + public static final ConfigKey COMMANDS_RATE_LIMIT = booleanKey("commands-rate-limit", true); + /** * If Vault lookups for offline players on the main server thread should be enabled */