From 3b2a04e4db771965469bd60f053749799ba2b42e Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Sun, 8 Aug 2021 13:28:43 +0200 Subject: [PATCH] Fix/v6/click event actions (#3178) Co-authored-by: NotMyFault Co-authored-by: dordsor21 --- .../plotsquared/core/command/FlagCommand.java | 4 +- .../core/configuration/Settings.java | 12 ++- .../configuration/caption/CaptionUtility.java | 68 +++++++++++++ .../caption/ClickStripTransform.java | 50 ++++++++++ .../caption/ComponentTransform.java | 67 +++++++++++++ .../caption/NestedComponentTransform.java | 54 +++++++++++ .../plotsquared/core/database/SQLManager.java | 4 +- .../core/listener/PlotListener.java | 6 -- .../java/com/plotsquared/core/plot/Plot.java | 3 - .../core/plot/flag/FlagContainer.java | 4 +- .../flag/implementations/DescriptionFlag.java | 4 +- .../plot/flag/implementations/DoneFlag.java | 4 +- .../flag/implementations/FarewellFlag.java | 4 +- .../flag/implementations/GreetingFlag.java | 4 +- .../core/plot/flag/types/StringFlag.java | 49 ++++++++++ .../caption/ClickStripTransformTest.java | 96 +++++++++++++++++++ build.gradle.kts | 5 + 17 files changed, 414 insertions(+), 24 deletions(-) create mode 100644 Core/src/main/java/com/plotsquared/core/configuration/caption/ClickStripTransform.java create mode 100644 Core/src/main/java/com/plotsquared/core/configuration/caption/ComponentTransform.java create mode 100644 Core/src/main/java/com/plotsquared/core/configuration/caption/NestedComponentTransform.java create mode 100644 Core/src/main/java/com/plotsquared/core/plot/flag/types/StringFlag.java create mode 100644 Core/src/test/java/com/plotsquared/core/configuration/caption/ClickStripTransformTest.java diff --git a/Core/src/main/java/com/plotsquared/core/command/FlagCommand.java b/Core/src/main/java/com/plotsquared/core/command/FlagCommand.java index 15d3a3bfa..6b23111f6 100644 --- a/Core/src/main/java/com/plotsquared/core/command/FlagCommand.java +++ b/Core/src/main/java/com/plotsquared/core/command/FlagCommand.java @@ -27,6 +27,7 @@ package com.plotsquared.core.command; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Settings; +import com.plotsquared.core.configuration.caption.CaptionUtility; import com.plotsquared.core.configuration.caption.StaticCaption; import com.plotsquared.core.configuration.caption.Templates; import com.plotsquared.core.configuration.caption.TranslatableCaption; @@ -335,10 +336,11 @@ public final class FlagCommand extends Command { return; } boolean force = event.getEventResult() == Result.FORCE; - final String value = StringMan.join(Arrays.copyOfRange(args, 1, args.length), " "); + String value = StringMan.join(Arrays.copyOfRange(args, 1, args.length), " "); if (!force && !checkPermValue(player, plotFlag, args[0], value)) { return; } + value = CaptionUtility.stripClickEvents(plotFlag, value); final PlotFlag parsed; try { parsed = plotFlag.parse(value); diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java index 7167d990d..410f0ff1e 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -26,12 +26,14 @@ package com.plotsquared.core.configuration; import com.plotsquared.core.configuration.file.YamlConfiguration; +import net.kyori.adventure.text.event.ClickEvent; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; public class Settings extends Config { @@ -498,10 +500,12 @@ public class Settings extends Config { "notify-enter, notify-leave, greeting or farewell flag."}) public static boolean NOTIFICATION_AS_ACTIONBAR = false; - @Comment({"Whether to strip any possible components from user-defined messages, e.g. plot greeting", - "This can allow players to use commands to give themselves ranks as commands ran in this fashion cannot be prevent by " + - "permissions etc."}) - public static boolean REMOVE_USER_DEFINED_CLICK_EVENTS = true; + @Comment({"The click event actions that should be removed from user input in e.g. plot flags like 'greeting'.", + "Actions like 'RUN_COMMAND' may be used maliciously as players could trick staff into clicking on messages", + "triggering destructive commands."}) + public static List CLICK_EVENT_ACTIONS_TO_REMOVE = Arrays.stream(ClickEvent.Action.values()) + .map(Enum::name) + .collect(Collectors.toList()); } diff --git a/Core/src/main/java/com/plotsquared/core/configuration/caption/CaptionUtility.java b/Core/src/main/java/com/plotsquared/core/configuration/caption/CaptionUtility.java index e04b8effe..93f4275b1 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/caption/CaptionUtility.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/caption/CaptionUtility.java @@ -25,12 +25,42 @@ */ package com.plotsquared.core.configuration.caption; +import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.player.PlotPlayer; +import com.plotsquared.core.plot.flag.PlotFlag; +import com.plotsquared.core.plot.flag.implementations.DescriptionFlag; +import com.plotsquared.core.plot.flag.implementations.FarewellFlag; +import com.plotsquared.core.plot.flag.implementations.GreetingFlag; +import com.plotsquared.core.plot.flag.types.StringFlag; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.minimessage.MiniMessage; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import java.util.Set; + +import static com.plotsquared.core.configuration.caption.ComponentTransform.nested; +import static com.plotsquared.core.configuration.caption.ComponentTransform.stripClicks; + public class CaptionUtility { + // flags which values are parsed by minimessage + private static final Set>> MINI_MESSAGE_FLAGS = Set.of( + GreetingFlag.class, + FarewellFlag.class, + DescriptionFlag.class + ); + + private static final ComponentTransform CLICK_STRIP_TRANSFORM = nested( + stripClicks( + Settings.Chat.CLICK_EVENT_ACTIONS_TO_REMOVE.stream() + .map(ClickEvent.Action::valueOf) + .toArray(ClickEvent.Action[]::new) + ) + ); + + /** * Format a chat message but keep the formatting keys * @@ -66,4 +96,42 @@ public class CaptionUtility { return chatContext.getMessage(); } + /** + * Strips configured click events from a MiniMessage string. + * + * @param miniMessageString the message from which the specified click events should be removed from. + * @return the string without the click events that are configured to be removed. + * + * @see Settings.Chat#CLICK_EVENT_ACTIONS_TO_REMOVE + */ + public static String stripClickEvents(final @NonNull String miniMessageString) { + // parse, transform and serialize again + Component component = MiniMessage.get().parse(miniMessageString); + component = CLICK_STRIP_TRANSFORM.transform(component); + return MiniMessage.get().serialize(component); + } + + /** + * Strips configured MiniMessage click events from a plot flag value. + * This is used before letting the string be parsed by the plot flag. + * This method works the same way as {@link #stripClickEvents(String)} but will only + * strip click events from messages that target flags that are meant to contain MiniMessage strings. + * + * @param flag the flag the message is targeted for. + * @param miniMessageString the message from which the specified click events should be removed from. + * @return the string without the click events that are configured to be removed. + * + * @see Settings.Chat#CLICK_EVENT_ACTIONS_TO_REMOVE + * @see #stripClickEvents(String) + */ + public static String stripClickEvents( + final @NonNull PlotFlag flag, + final @NonNull String miniMessageString + ) { + if (MINI_MESSAGE_FLAGS.contains(flag.getClass())) { + return stripClickEvents(miniMessageString); + } + return miniMessageString; + } + } diff --git a/Core/src/main/java/com/plotsquared/core/configuration/caption/ClickStripTransform.java b/Core/src/main/java/com/plotsquared/core/configuration/caption/ClickStripTransform.java new file mode 100644 index 000000000..1a9f8db58 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/configuration/caption/ClickStripTransform.java @@ -0,0 +1,50 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2021 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.configuration.caption; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.jetbrains.annotations.NotNull; + +import java.util.EnumSet; +import java.util.Set; + +final class ClickStripTransform implements ComponentTransform { + private final Set actionsToStrip; + + public ClickStripTransform(final Set actionsToStrip) { + this.actionsToStrip = EnumSet.copyOf(actionsToStrip); + } + + @Override + public @NonNull Component transform(@NonNull final Component original) { + var clickEvent = original.clickEvent(); + if (clickEvent == null || !actionsToStrip.contains(clickEvent.action())) return original; + return original.clickEvent(null); // remove it + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/configuration/caption/ComponentTransform.java b/Core/src/main/java/com/plotsquared/core/configuration/caption/ComponentTransform.java new file mode 100644 index 000000000..40c801fe5 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/configuration/caption/ComponentTransform.java @@ -0,0 +1,67 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2021 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.configuration.caption; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.Set; + +public interface ComponentTransform { + + /** + * Creates a transform that applies the given transform on all child components and the + * component itself. The children are transformed before the component itself is transformed. + * + * @param transform the transform to apply. + * @return a new transform which is applied on all child components and the component itself. + */ + static ComponentTransform nested(ComponentTransform transform) { + return new NestedComponentTransform(transform); + } + + /** + * Creates a transform that removes click events of the given actions from a component. + * Note: To remove click events from children too, the returned transform must be wrapped + * using {@link #nested(ComponentTransform)}. + * + * @param actionsToRemove the actions used to filter which click events should be removed. + * @return a new transform that removes click events from a component. + */ + static ComponentTransform stripClicks(ClickEvent.Action... actionsToRemove) { + return new ClickStripTransform(Set.of(actionsToRemove)); + } + + /** + * Applies this transform on the given component and returns the result. + * + * @param original the component to transform. + * @return the transformed component. + */ + @NonNull Component transform(@NonNull Component original); + +} diff --git a/Core/src/main/java/com/plotsquared/core/configuration/caption/NestedComponentTransform.java b/Core/src/main/java/com/plotsquared/core/configuration/caption/NestedComponentTransform.java new file mode 100644 index 000000000..4024d578b --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/configuration/caption/NestedComponentTransform.java @@ -0,0 +1,54 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2021 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.configuration.caption; + +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import net.kyori.adventure.text.Component; +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * A transform that applies a nested transform on all child components and the component itself. + */ +final class NestedComponentTransform implements ComponentTransform { + private final ComponentTransform transform; + + public NestedComponentTransform(final ComponentTransform transform) { + this.transform = transform; + } + + @Override + public @NonNull Component transform(final @NonNull Component original) { + return this.transform.transform(original.children(transformChildren(original.children()))); + } + + private List transformChildren(List children) { + return children.stream().map(this::transform).collect(Collectors.toList()); + } +} diff --git a/Core/src/main/java/com/plotsquared/core/database/SQLManager.java b/Core/src/main/java/com/plotsquared/core/database/SQLManager.java index ee22cbbd2..eb78968eb 100644 --- a/Core/src/main/java/com/plotsquared/core/database/SQLManager.java +++ b/Core/src/main/java/com/plotsquared/core/database/SQLManager.java @@ -30,6 +30,7 @@ import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.ConfigurationSection; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.configuration.Storage; +import com.plotsquared.core.configuration.caption.CaptionUtility; import com.plotsquared.core.configuration.file.YamlConfiguration; import com.plotsquared.core.inject.annotations.WorldConfig; import com.plotsquared.core.listener.PlotListener; @@ -2033,7 +2034,7 @@ public class SQLManager implements AbstractDB { while (resultSet.next()) { id = resultSet.getInt("plot_id"); final String flag = resultSet.getString("flag"); - final String value = resultSet.getString("value"); + String value = resultSet.getString("value"); final Plot plot = plots.get(id); if (plot != null) { final PlotFlag plotFlag = @@ -2041,6 +2042,7 @@ public class SQLManager implements AbstractDB { if (plotFlag == null) { plot.getFlagContainer().addUnknownFlag(flag, value); } else { + value = CaptionUtility.stripClickEvents(plotFlag, value); try { plot.getFlagContainer().addFlag(plotFlag.parse(value)); } catch (final FlagParseException e) { diff --git a/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java b/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java index 8e0d5719b..13679d6d4 100644 --- a/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java +++ b/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java @@ -171,9 +171,6 @@ public class PlotListener { String greeting = plot.getFlag(GreetingFlag.class); if (!greeting.isEmpty()) { - if (Settings.Chat.REMOVE_USER_DEFINED_CLICK_EVENTS) { - greeting = greeting.replaceAll(".([c-lC-L]{5}):([a-uA-U_]{11}):[^\\/]*[^>]*>>", "").replace("", ""); - } if (!Settings.Chat.NOTIFICATION_AS_ACTIONBAR) { plot.format(StaticCaption.of(greeting), player, false).thenAcceptAsync(player::sendMessage); } else { @@ -395,9 +392,6 @@ public class PlotListener { String farewell = plot.getFlag(FarewellFlag.class); if (!farewell.isEmpty()) { - if (Settings.Chat.REMOVE_USER_DEFINED_CLICK_EVENTS) { - farewell = farewell.replaceAll(".([c-lC-L]{5}):([a-uA-U_]{11}):[^\\/]*[^>]*>", "").replace("", ""); - } if (!Settings.Chat.NOTIFICATION_AS_ACTIONBAR) { plot.format(StaticCaption.of(farewell), player, false).thenAcceptAsync(player::sendMessage); } else { diff --git a/Core/src/main/java/com/plotsquared/core/plot/Plot.java b/Core/src/main/java/com/plotsquared/core/plot/Plot.java index 37e8e4f3c..488ca6558 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/Plot.java +++ b/Core/src/main/java/com/plotsquared/core/plot/Plot.java @@ -2790,9 +2790,6 @@ public class Plot { String description = this.getFlag(DescriptionFlag.class); if (description.isEmpty()) { description = TranslatableCaption.of("info.plot_no_description").getComponent(player); - } else if (Settings.Chat.REMOVE_USER_DEFINED_CLICK_EVENTS) { - description = description.replaceAll(".([c-lC-L]{5}):([a-uA-U_]{11}):[^\\/]*[^>]*>", "").replace("", - ""); } Component flags; diff --git a/Core/src/main/java/com/plotsquared/core/plot/flag/FlagContainer.java b/Core/src/main/java/com/plotsquared/core/plot/flag/FlagContainer.java index e4a0e8b0f..1fdc14664 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/flag/FlagContainer.java +++ b/Core/src/main/java/com/plotsquared/core/plot/flag/FlagContainer.java @@ -27,6 +27,7 @@ package com.plotsquared.core.plot.flag; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; +import com.plotsquared.core.configuration.caption.CaptionUtility; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.checkerframework.checker.nullness.qual.NonNull; @@ -316,8 +317,9 @@ public class FlagContainer { ) { if (plotFlagUpdateType != PlotFlagUpdateType.FLAG_REMOVED && this.unknownFlags .containsKey(flag.getName())) { - final String value = this.unknownFlags.remove(flag.getName()); + String value = this.unknownFlags.remove(flag.getName()); if (value != null) { + value = CaptionUtility.stripClickEvents(flag, value); try { this.addFlag(flag.parse(value)); } catch (final Exception ignored) { diff --git a/Core/src/main/java/com/plotsquared/core/plot/flag/implementations/DescriptionFlag.java b/Core/src/main/java/com/plotsquared/core/plot/flag/implementations/DescriptionFlag.java index aab69c6e7..8ad470fbe 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/flag/implementations/DescriptionFlag.java +++ b/Core/src/main/java/com/plotsquared/core/plot/flag/implementations/DescriptionFlag.java @@ -26,10 +26,10 @@ package com.plotsquared.core.plot.flag.implementations; import com.plotsquared.core.configuration.caption.TranslatableCaption; -import com.plotsquared.core.plot.flag.PlotFlag; +import com.plotsquared.core.plot.flag.types.StringFlag; import org.checkerframework.checker.nullness.qual.NonNull; -public class DescriptionFlag extends PlotFlag { +public class DescriptionFlag extends StringFlag { public static final DescriptionFlag DESCRIPTION_FLAG_EMPTY = new DescriptionFlag(""); diff --git a/Core/src/main/java/com/plotsquared/core/plot/flag/implementations/DoneFlag.java b/Core/src/main/java/com/plotsquared/core/plot/flag/implementations/DoneFlag.java index 54a45c92c..c7a511ca2 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/flag/implementations/DoneFlag.java +++ b/Core/src/main/java/com/plotsquared/core/plot/flag/implementations/DoneFlag.java @@ -28,10 +28,10 @@ package com.plotsquared.core.plot.flag.implementations; import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.flag.InternalFlag; -import com.plotsquared.core.plot.flag.PlotFlag; +import com.plotsquared.core.plot.flag.types.StringFlag; import org.checkerframework.checker.nullness.qual.NonNull; -public class DoneFlag extends PlotFlag implements InternalFlag { +public class DoneFlag extends StringFlag implements InternalFlag { /** * Construct a new flag instance. diff --git a/Core/src/main/java/com/plotsquared/core/plot/flag/implementations/FarewellFlag.java b/Core/src/main/java/com/plotsquared/core/plot/flag/implementations/FarewellFlag.java index 406e26a04..c74039692 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/flag/implementations/FarewellFlag.java +++ b/Core/src/main/java/com/plotsquared/core/plot/flag/implementations/FarewellFlag.java @@ -26,10 +26,10 @@ package com.plotsquared.core.plot.flag.implementations; import com.plotsquared.core.configuration.caption.TranslatableCaption; -import com.plotsquared.core.plot.flag.PlotFlag; +import com.plotsquared.core.plot.flag.types.StringFlag; import org.checkerframework.checker.nullness.qual.NonNull; -public class FarewellFlag extends PlotFlag { +public class FarewellFlag extends StringFlag { public static final FarewellFlag FAREWELL_FLAG_EMPTY = new FarewellFlag(""); diff --git a/Core/src/main/java/com/plotsquared/core/plot/flag/implementations/GreetingFlag.java b/Core/src/main/java/com/plotsquared/core/plot/flag/implementations/GreetingFlag.java index 4bdda9d2b..41b280696 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/flag/implementations/GreetingFlag.java +++ b/Core/src/main/java/com/plotsquared/core/plot/flag/implementations/GreetingFlag.java @@ -26,10 +26,10 @@ package com.plotsquared.core.plot.flag.implementations; import com.plotsquared.core.configuration.caption.TranslatableCaption; -import com.plotsquared.core.plot.flag.PlotFlag; +import com.plotsquared.core.plot.flag.types.StringFlag; import org.checkerframework.checker.nullness.qual.NonNull; -public class GreetingFlag extends PlotFlag { +public class GreetingFlag extends StringFlag { public static final GreetingFlag GREETING_FLAG_EMPTY = new GreetingFlag(""); diff --git a/Core/src/main/java/com/plotsquared/core/plot/flag/types/StringFlag.java b/Core/src/main/java/com/plotsquared/core/plot/flag/types/StringFlag.java new file mode 100644 index 000000000..18ce371fc --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/plot/flag/types/StringFlag.java @@ -0,0 +1,49 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2021 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.plot.flag.types; + +import com.plotsquared.core.configuration.caption.Caption; +import com.plotsquared.core.plot.flag.PlotFlag; +import org.checkerframework.checker.nullness.qual.NonNull; + +public abstract class StringFlag> extends PlotFlag { + + /** + * Construct a new flag instance. + * + * @param value Flag value + * @param flagCategory The flag category + * @param flagDescription A caption describing the flag functionality + */ + protected StringFlag( + final @NonNull String value, + final @NonNull Caption flagCategory, + final @NonNull Caption flagDescription + ) { + super(value, flagCategory, flagDescription); + } + +} diff --git a/Core/src/test/java/com/plotsquared/core/configuration/caption/ClickStripTransformTest.java b/Core/src/test/java/com/plotsquared/core/configuration/caption/ClickStripTransformTest.java new file mode 100644 index 000000000..89f484ac2 --- /dev/null +++ b/Core/src/test/java/com/plotsquared/core/configuration/caption/ClickStripTransformTest.java @@ -0,0 +1,96 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2021 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.configuration.caption; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.EnumSet; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; + +class ClickStripTransformTest { + + @Test + @DisplayName("Remove click event of specific action correctly") + void removeClickEvent() { + var commonAction = ClickEvent.Action.OPEN_FILE; + var transform = new ClickStripTransform(EnumSet.of(commonAction)); + var component = Component.text("Hello") + .clickEvent(ClickEvent.clickEvent( + commonAction, + "World" + ) + ); + var transformedComponent = transform.transform(component); + assertNull(transformedComponent.clickEvent()); + } + + @Test + @DisplayName("Don't remove click events of other action types") + void ignoreClickEvent() { + var actionToRemove = ClickEvent.Action.SUGGEST_COMMAND; + var transform = new ClickStripTransform(EnumSet.of(actionToRemove)); + var originalClickEvent = ClickEvent.clickEvent( + ClickEvent.Action.CHANGE_PAGE, + "World" + ); + var component = Component.text("Hello") + .clickEvent(originalClickEvent); + var transformedComponent = transform.transform(component); + assertEquals(originalClickEvent, transformedComponent.clickEvent()); + } + + @Test + @DisplayName("Remove nested click events correctly") + void removeNestedClickEvent() { + // nested transform is required to apply on children + var transform = new NestedComponentTransform(new ClickStripTransform(EnumSet.allOf(ClickEvent.Action.class))); + var inner = Component + // some arbitrary values that should remain + .text("World") + .color(NamedTextColor.AQUA) + .hoverEvent(HoverEvent.showText(Component.text("ABC"))) + .decorate(TextDecoration.OBFUSCATED) + .insertion("DEF"); + var component = Component.text("Hello ") + .append( + inner.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.OPEN_URL, "https://example.org")) + ); + var transformedComponent = transform.transform(component); + assertFalse(transformedComponent.children().isEmpty()); // child still exists + assertEquals(inner, transformedComponent.children().get(0)); // only the click event has changed + assertNull(transformedComponent.children().get(0).clickEvent()); + } + +} diff --git a/build.gradle.kts b/build.gradle.kts index 96773eb9b..f333639d7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -81,6 +81,7 @@ allprojects { dependencies { // Tests testImplementation("junit:junit:4.13.2") + testImplementation("org.junit.jupiter:junit-jupiter:5.7.2") } plugins.withId("java") { @@ -215,7 +216,11 @@ allprojects { named("build") { dependsOn(named("shadowJar")) } + test { + useJUnitPlatform() + } } + } tasks {