From 5e2f45ebd0270b8e5deebc58dd576cabab9dfe4f Mon Sep 17 00:00:00 2001
From: Luck
Date: Mon, 26 Aug 2019 15:03:30 +0100
Subject: [PATCH] Web editor changes, towards #1703
---
.../api/event/cause/CreationCause.java | 5 +
.../me/lucko/luckperms/api/node/Node.java | 7 +
.../lucko/luckperms/api/node/NodeBuilder.java | 14 +-
.../lucko/luckperms/api/node/ScopedNode.java | 3 +
.../api/node/types/ChatMetaNode.java | 2 +-
.../api/node/types/DisplayNameNode.java | 6 +
.../api/node/types/InheritanceNode.java | 6 +
.../luckperms/api/node/types/MetaNode.java | 6 +
.../api/node/types/PermissionNode.java | 6 +
.../luckperms/api/node/types/PrefixNode.java | 6 +
.../api/node/types/RegexPermissionNode.java | 6 +
.../luckperms/api/node/types/SuffixNode.java | 6 +
.../luckperms/api/node/types/WeightNode.java | 6 +
.../commands/generic/meta/MetaInfo.java | 2 +-
.../commands/generic/other/HolderEditor.java | 2 +-
.../commands/misc/ApplyEditsCommand.java | 204 +++++++++++++++---
.../common/commands/misc/EditorCommand.java | 8 +-
.../common/locale/message/Message.java | 5 +-
.../lucko/luckperms/common/model/Track.java | 2 +-
.../common/node/AbstractNodeBuilder.java | 16 +-
.../common/node/factory/NodeFactory.java | 2 +-
.../luckperms/common/node/types/Prefix.java | 2 +-
.../luckperms/common/node/types/Suffix.java | 2 +-
.../file/AbstractConfigurateStorage.java | 2 +-
.../lucko/luckperms/common/web/WebEditor.java | 157 +++++---------
25 files changed, 333 insertions(+), 150 deletions(-)
diff --git a/api/src/main/java/me/lucko/luckperms/api/event/cause/CreationCause.java b/api/src/main/java/me/lucko/luckperms/api/event/cause/CreationCause.java
index 3b12f9ca0..305477e03 100644
--- a/api/src/main/java/me/lucko/luckperms/api/event/cause/CreationCause.java
+++ b/api/src/main/java/me/lucko/luckperms/api/event/cause/CreationCause.java
@@ -35,6 +35,11 @@ public enum CreationCause {
*/
COMMAND,
+ /**
+ * The creation was caused by the web editor
+ */
+ WEB_EDITOR,
+
/**
* The creation was caused by an API call
*/
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/Node.java b/api/src/main/java/me/lucko/luckperms/api/node/Node.java
index a0d5de855..c2f62e335 100644
--- a/api/src/main/java/me/lucko/luckperms/api/node/Node.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/Node.java
@@ -100,6 +100,13 @@ public interface Node {
return LuckPermsProvider.get().getNodeBuilderRegistry().forKey(key);
}
+ /**
+ * Gets the type of the node.
+ *
+ * @return the node type
+ */
+ @NonNull NodeType> getType();
+
/**
* Gets the key ({@link String}) of the node.
*
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/NodeBuilder.java b/api/src/main/java/me/lucko/luckperms/api/node/NodeBuilder.java
index 791d93b09..302c5bd41 100644
--- a/api/src/main/java/me/lucko/luckperms/api/node/NodeBuilder.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/NodeBuilder.java
@@ -31,6 +31,7 @@ import me.lucko.luckperms.api.node.metadata.NodeMetadataKey;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
+import java.time.temporal.TemporalAccessor;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@@ -66,11 +67,20 @@ public interface NodeBuilder, B extends NodeBuilderThe parameter passed to this method must be the unix timestamp
* (in seconds) when the node should expire.
*
- * @param expiryUnixTimestamp the expiry timestamp (unix seconds)
+ * @param expiryEpochSeconds the expiry timestamp (unix seconds)
* @return the builder
* @see Node#getExpiry()
*/
- @NonNull B expiry(long expiryUnixTimestamp);
+ @NonNull B expiry(long expiryEpochSeconds);
+
+ /**
+ * Sets the time when the node should expire.
+ *
+ * @param expiry the expiry time
+ * @return the builder
+ * @see Node#getExpiry()
+ */
+ @NonNull B expiry(@Nullable TemporalAccessor expiry);
/**
* Sets the time when the node should expire.
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/ScopedNode.java b/api/src/main/java/me/lucko/luckperms/api/node/ScopedNode.java
index 8a78241f8..50ed43dab 100644
--- a/api/src/main/java/me/lucko/luckperms/api/node/ScopedNode.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/ScopedNode.java
@@ -36,6 +36,9 @@ import org.checkerframework.checker.nullness.qual.NonNull;
*/
public interface ScopedNode, B extends NodeBuilder> extends Node {
+ @Override
+ @NonNull NodeType getType();
+
@Override
@NonNull B toBuilder();
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/types/ChatMetaNode.java b/api/src/main/java/me/lucko/luckperms/api/node/types/ChatMetaNode.java
index 07b372ebc..db541cb48 100644
--- a/api/src/main/java/me/lucko/luckperms/api/node/types/ChatMetaNode.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/types/ChatMetaNode.java
@@ -58,7 +58,7 @@ public interface ChatMetaNode, B extends ChatMetaNo
*
* @return the type
*/
- @NonNull ChatMetaType getType();
+ @NonNull ChatMetaType getMetaType();
/**
* A {@link ChatMetaNode} builder.
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/types/DisplayNameNode.java b/api/src/main/java/me/lucko/luckperms/api/node/types/DisplayNameNode.java
index 079d41e22..0f0e2adff 100644
--- a/api/src/main/java/me/lucko/luckperms/api/node/types/DisplayNameNode.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/types/DisplayNameNode.java
@@ -28,6 +28,7 @@ package me.lucko.luckperms.api.node.types;
import me.lucko.luckperms.api.LuckPermsProvider;
import me.lucko.luckperms.api.node.Node;
import me.lucko.luckperms.api.node.NodeBuilder;
+import me.lucko.luckperms.api.node.NodeType;
import me.lucko.luckperms.api.node.ScopedNode;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -37,6 +38,11 @@ import org.checkerframework.checker.nullness.qual.NonNull;
*/
public interface DisplayNameNode extends ScopedNode {
+ @Override
+ default @NonNull NodeType getType() {
+ return NodeType.DISPLAY_NAME;
+ }
+
/**
* Gets the display name.
*
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/types/InheritanceNode.java b/api/src/main/java/me/lucko/luckperms/api/node/types/InheritanceNode.java
index 98b532cd5..ed9ca4763 100644
--- a/api/src/main/java/me/lucko/luckperms/api/node/types/InheritanceNode.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/types/InheritanceNode.java
@@ -29,6 +29,7 @@ import me.lucko.luckperms.api.LuckPermsProvider;
import me.lucko.luckperms.api.model.group.Group;
import me.lucko.luckperms.api.node.Node;
import me.lucko.luckperms.api.node.NodeBuilder;
+import me.lucko.luckperms.api.node.NodeType;
import me.lucko.luckperms.api.node.ScopedNode;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -39,6 +40,11 @@ import org.checkerframework.checker.nullness.qual.NonNull;
*/
public interface InheritanceNode extends ScopedNode {
+ @Override
+ default @NonNull NodeType getType() {
+ return NodeType.INHERITANCE;
+ }
+
/**
* Gets the name of the group to be inherited.
*
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/types/MetaNode.java b/api/src/main/java/me/lucko/luckperms/api/node/types/MetaNode.java
index 77739aaf5..0b95830b1 100644
--- a/api/src/main/java/me/lucko/luckperms/api/node/types/MetaNode.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/types/MetaNode.java
@@ -28,6 +28,7 @@ package me.lucko.luckperms.api.node.types;
import me.lucko.luckperms.api.LuckPermsProvider;
import me.lucko.luckperms.api.node.Node;
import me.lucko.luckperms.api.node.NodeBuilder;
+import me.lucko.luckperms.api.node.NodeType;
import me.lucko.luckperms.api.node.ScopedNode;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -37,6 +38,11 @@ import org.checkerframework.checker.nullness.qual.NonNull;
*/
public interface MetaNode extends ScopedNode {
+ @Override
+ default @NonNull NodeType getType() {
+ return NodeType.META;
+ }
+
/**
* Gets the meta key.
*
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/types/PermissionNode.java b/api/src/main/java/me/lucko/luckperms/api/node/types/PermissionNode.java
index 7573ddce6..c5530a5c3 100644
--- a/api/src/main/java/me/lucko/luckperms/api/node/types/PermissionNode.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/types/PermissionNode.java
@@ -28,6 +28,7 @@ package me.lucko.luckperms.api.node.types;
import me.lucko.luckperms.api.LuckPermsProvider;
import me.lucko.luckperms.api.node.Node;
import me.lucko.luckperms.api.node.NodeBuilder;
+import me.lucko.luckperms.api.node.NodeType;
import me.lucko.luckperms.api.node.ScopedNode;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -39,6 +40,11 @@ import java.util.OptionalInt;
*/
public interface PermissionNode extends ScopedNode {
+ @Override
+ default @NonNull NodeType getType() {
+ return NodeType.PERMISSION;
+ }
+
/**
* Gets the permission string this node encapsulates.
*
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/types/PrefixNode.java b/api/src/main/java/me/lucko/luckperms/api/node/types/PrefixNode.java
index 8a1d24c1a..a8e4d6010 100644
--- a/api/src/main/java/me/lucko/luckperms/api/node/types/PrefixNode.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/types/PrefixNode.java
@@ -27,6 +27,7 @@ package me.lucko.luckperms.api.node.types;
import me.lucko.luckperms.api.LuckPermsProvider;
import me.lucko.luckperms.api.node.Node;
+import me.lucko.luckperms.api.node.NodeType;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -35,6 +36,11 @@ import org.checkerframework.checker.nullness.qual.NonNull;
*/
public interface PrefixNode extends ChatMetaNode {
+ @Override
+ default @NonNull NodeType getType() {
+ return NodeType.PREFIX;
+ }
+
/**
* Creates a {@link PrefixNode} builder.
*
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/types/RegexPermissionNode.java b/api/src/main/java/me/lucko/luckperms/api/node/types/RegexPermissionNode.java
index eecdb13be..6345d157d 100644
--- a/api/src/main/java/me/lucko/luckperms/api/node/types/RegexPermissionNode.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/types/RegexPermissionNode.java
@@ -28,6 +28,7 @@ package me.lucko.luckperms.api.node.types;
import me.lucko.luckperms.api.LuckPermsProvider;
import me.lucko.luckperms.api.node.Node;
import me.lucko.luckperms.api.node.NodeBuilder;
+import me.lucko.luckperms.api.node.NodeType;
import me.lucko.luckperms.api.node.ScopedNode;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -40,6 +41,11 @@ import java.util.regex.Pattern;
*/
public interface RegexPermissionNode extends ScopedNode {
+ @Override
+ default @NonNull NodeType getType() {
+ return NodeType.REGEX_PERMISSION;
+ }
+
/**
* Gets the non-compiled pattern string.
*
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/types/SuffixNode.java b/api/src/main/java/me/lucko/luckperms/api/node/types/SuffixNode.java
index d8d2dce88..5eacc23c7 100644
--- a/api/src/main/java/me/lucko/luckperms/api/node/types/SuffixNode.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/types/SuffixNode.java
@@ -27,6 +27,7 @@ package me.lucko.luckperms.api.node.types;
import me.lucko.luckperms.api.LuckPermsProvider;
import me.lucko.luckperms.api.node.Node;
+import me.lucko.luckperms.api.node.NodeType;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -35,6 +36,11 @@ import org.checkerframework.checker.nullness.qual.NonNull;
*/
public interface SuffixNode extends ChatMetaNode {
+ @Override
+ default @NonNull NodeType getType() {
+ return NodeType.SUFFIX;
+ }
+
/**
* Creates a {@link SuffixNode} builder.
*
diff --git a/api/src/main/java/me/lucko/luckperms/api/node/types/WeightNode.java b/api/src/main/java/me/lucko/luckperms/api/node/types/WeightNode.java
index 884d3a429..ed6a711c7 100644
--- a/api/src/main/java/me/lucko/luckperms/api/node/types/WeightNode.java
+++ b/api/src/main/java/me/lucko/luckperms/api/node/types/WeightNode.java
@@ -28,6 +28,7 @@ package me.lucko.luckperms.api.node.types;
import me.lucko.luckperms.api.LuckPermsProvider;
import me.lucko.luckperms.api.node.Node;
import me.lucko.luckperms.api.node.NodeBuilder;
+import me.lucko.luckperms.api.node.NodeType;
import me.lucko.luckperms.api.node.ScopedNode;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -37,6 +38,11 @@ import org.checkerframework.checker.nullness.qual.NonNull;
*/
public interface WeightNode extends ScopedNode {
+ @Override
+ default @NonNull NodeType getType() {
+ return NodeType.WEIGHT;
+ }
+
/**
* Gets the weight value.
*
diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaInfo.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaInfo.java
index 4d0195f8a..200a760d9 100644
--- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaInfo.java
+++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaInfo.java
@@ -174,7 +174,7 @@ public class MetaInfo extends SharedSubCommand {
HoverEvent hoverEvent = HoverEvent.showText(TextUtils.fromLegacy(TextUtils.joinNewline(
"¥3> ¥a" + node.getPriority() + " ¥7- ¥r" + node.getMetaValue(),
" ",
- "¥7Click to remove this " + node.getType().name().toLowerCase() + " from " + holder.getFormattedDisplayName()
+ "¥7Click to remove this " + node.getMetaType().name().toLowerCase() + " from " + holder.getFormattedDisplayName()
), '¥'));
String command = "/" + label + " " + NodeFactory.nodeAsCommand(node, holder.getType() == HolderType.GROUP ? holder.getObjectName() : holder.getFormattedDisplayName(), holder.getType(), false, !holder.getPlugin().getConfiguration().getContextsFile().getDefaultContexts().isEmpty());
diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderEditor.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderEditor.java
index caa39c391..3ebd0bc45 100644
--- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderEditor.java
+++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderEditor.java
@@ -66,7 +66,7 @@ public class HolderEditor extends SubCommand {
Message.EDITOR_START.send(sender);
// form the payload data
- JsonObject payload = WebEditor.formPayload(Collections.singletonList(holder), sender, label, plugin);
+ JsonObject payload = WebEditor.formPayload(Collections.singletonList(holder), Collections.emptyList(), sender, label, plugin);
// upload the payload data to gist
String pasteId = plugin.getBytebin().postJson(payload, true).id();
diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/misc/ApplyEditsCommand.java b/common/src/main/java/me/lucko/luckperms/common/commands/misc/ApplyEditsCommand.java
index a76b70f78..b2a462982 100644
--- a/common/src/main/java/me/lucko/luckperms/common/commands/misc/ApplyEditsCommand.java
+++ b/common/src/main/java/me/lucko/luckperms/common/commands/misc/ApplyEditsCommand.java
@@ -30,6 +30,9 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
+import me.lucko.luckperms.api.actionlog.Action;
+import me.lucko.luckperms.api.event.cause.CreationCause;
+import me.lucko.luckperms.api.event.cause.DeletionCause;
import me.lucko.luckperms.api.model.DataType;
import me.lucko.luckperms.api.node.Node;
import me.lucko.luckperms.common.actionlog.LoggedAction;
@@ -42,19 +45,24 @@ import me.lucko.luckperms.common.command.utils.StorageAssistant;
import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message;
+import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.PermissionHolder;
-import me.lucko.luckperms.common.node.model.NodeDataContainer;
+import me.lucko.luckperms.common.model.Track;
+import me.lucko.luckperms.common.node.factory.NodeFactory;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.util.DurationFormatter;
import me.lucko.luckperms.common.util.Predicates;
+import me.lucko.luckperms.common.util.Uuids;
import me.lucko.luckperms.common.web.WebEditor;
+import java.util.ArrayList;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.stream.Collectors;
+import java.util.UUID;
public class ApplyEditsCommand extends SingleCommand {
public ApplyEditsCommand(LocaleManager locale) {
@@ -76,37 +84,75 @@ public class ApplyEditsCommand extends SingleCommand {
return CommandResult.FAILURE;
}
- boolean success = false;
-
- if (data.has("tabs") && data.get("tabs").isJsonArray()) {
- JsonArray rows = data.get("tabs").getAsJsonArray();
- for (JsonElement row : rows) {
- if (read(row.getAsJsonObject(), sender, plugin)) {
- success = true;
+ boolean work = false;
+ if (data.has("changes")) {
+ JsonArray changes = data.get("changes").getAsJsonArray();
+ for (JsonElement change : changes) {
+ if (readChanges(change.getAsJsonObject(), sender, plugin)) {
+ work = true;
+ }
+ }
+ }
+ if (data.has("groupDeletions")) {
+ JsonArray groupDeletions = data.get("groupDeletions").getAsJsonArray();
+ for (JsonElement groupDeletion : groupDeletions) {
+ if (readGroupDeletion(groupDeletion, sender, plugin)) {
+ work = true;
+ }
+ }
+ }
+ if (data.has("trackDeletions")) {
+ JsonArray trackDeletions = data.get("trackDeletions").getAsJsonArray();
+ for (JsonElement trackDeletion : trackDeletions) {
+ if (readTrackDeletion(trackDeletion, sender, plugin)) {
+ work = true;
}
}
- } else {
- success = read(data, sender, plugin);
}
- if (!success) {
+ if (!work) {
Message.APPLY_EDITS_TARGET_NO_CHANGES_PRESENT.send(sender);
}
return CommandResult.SUCCESS;
}
- private boolean read(JsonObject data, Sender sender, LuckPermsPlugin plugin) {
- if (!data.has("who") || data.get("who").getAsString().isEmpty()) {
- Message.APPLY_EDITS_NO_TARGET.send(sender);
+ private boolean readChanges(JsonObject data, Sender sender, LuckPermsPlugin plugin) {
+ String type = data.get("type").getAsString();
+
+ if (type.equals("user") || type.equals("group")) {
+ return readHolderChanges(data, sender, plugin);
+ } else if (type.equals("track")) {
+ return readTrackChanges(data, sender, plugin);
+ } else {
+ Message.APPLY_EDITS_UNKNOWN_TYPE.send(sender, type);
return false;
}
+ }
- String who = data.get("who").getAsString();
- PermissionHolder holder = WebEditor.getHolderFromIdentifier(plugin, sender, who);
- if (holder == null) {
- // the #getHolderFromIdentifier method will send the error message onto the sender
- return false;
+ private boolean readHolderChanges(JsonObject data, Sender sender, LuckPermsPlugin plugin) {
+ String type = data.get("type").getAsString();
+ String id = data.get("id").getAsString();
+
+ PermissionHolder holder;
+ if (type.equals("user")) {
+ // user
+ UUID uuid = Uuids.parse(id);
+ if (uuid == null) {
+ Message.APPLY_EDITS_TARGET_USER_NOT_UUID.send(sender, id);
+ return false;
+ }
+ holder = plugin.getStorage().loadUser(uuid, null).join();
+ if (holder == null) {
+ Message.APPLY_EDITS_TARGET_USER_UNABLE_TO_LOAD.send(sender, uuid.toString());
+ return false;
+ }
+ } else {
+ // group
+ holder = plugin.getStorage().loadGroup(id).join().orElse(null);
+ if (holder == null) {
+ holder = plugin.getStorage().createAndLoadGroup(id, CreationCause.WEB_EDITOR).join();
+ }
}
if (ArgumentPermissions.checkModifyPerms(plugin, sender, getPermission().get(), holder)) {
@@ -114,10 +160,8 @@ public class ApplyEditsCommand extends SingleCommand {
return false;
}
- Set nodes = WebEditor.deserializePermissions(data.getAsJsonArray("nodes"));
-
Set before = new HashSet<>(holder.normalData().immutable().values());
- Set after = nodes.stream().map(NodeDataContainer::toNode).collect(Collectors.toSet());
+ Set after = new HashSet<>(WebEditor.deserializePermissions(data.getAsJsonArray("nodes")));
Map.Entry, Set> diff = diff(before, after);
Set diffAdded = diff.getKey();
@@ -146,7 +190,7 @@ public class ApplyEditsCommand extends SingleCommand {
String additionsSummary = "addition" + (additions == 1 ? "" : "s");
String deletionsSummary = "deletion" + (deletions == 1 ? "" : "s");
- Message.APPLY_EDITS_SUCCESS.send(sender, holder.getFormattedDisplayName());
+ Message.APPLY_EDITS_SUCCESS.send(sender, type, holder.getFormattedDisplayName());
Message.APPLY_EDITS_SUCCESS_SUMMARY.send(sender, additions, additionsSummary, deletions, deletionsSummary);
for (Node n : diffAdded) {
Message.APPLY_EDITS_DIFF_ADDED.send(sender, formatNode(plugin.getLocaleManager(), n));
@@ -158,19 +202,125 @@ public class ApplyEditsCommand extends SingleCommand {
return true;
}
+ private boolean readTrackChanges(JsonObject data, Sender sender, LuckPermsPlugin plugin) {
+ String id = data.get("id").getAsString();
+
+ Track track = plugin.getStorage().loadTrack(id).join().orElse(null);
+ if (track == null) {
+ track = plugin.getStorage().createAndLoadTrack(id, CreationCause.WEB_EDITOR).join();
+ }
+
+ Set before = new LinkedHashSet<>(track.getGroups());
+ Set after = new LinkedHashSet<>();
+ data.getAsJsonArray("groups").forEach(e -> after.add(e.getAsString()));
+
+ Map.Entry, Set> diff = diff(before, after);
+ Set diffAdded = diff.getKey();
+ Set diffRemoved = diff.getValue();
+
+ int additions = diffAdded.size();
+ int deletions = diffRemoved.size();
+
+ if (additions == 0 && deletions == 0) {
+ return false;
+ }
+
+ track.setGroups(new ArrayList<>(after));
+
+ for (String n : diffAdded) {
+ LoggedAction.build().source(sender).target(track)
+ .description("webeditor", "add", n)
+ .build().submit(plugin, sender);
+ }
+ for (String n : diffRemoved) {
+ LoggedAction.build().source(sender).target(track)
+ .description("webeditor", "remove", n)
+ .build().submit(plugin, sender);
+ }
+
+ String additionsSummary = "addition" + (additions == 1 ? "" : "s");
+ String deletionsSummary = "deletion" + (deletions == 1 ? "" : "s");
+
+ Message.APPLY_EDITS_SUCCESS.send(sender, "track", track.getName());
+ Message.APPLY_EDITS_SUCCESS_SUMMARY.send(sender, additions, additionsSummary, deletions, deletionsSummary);
+ for (String n : diffAdded) {
+ Message.APPLY_EDITS_DIFF_ADDED.send(sender, n);
+ }
+ for (String n : diffRemoved) {
+ Message.APPLY_EDITS_DIFF_REMOVED.send(sender, n);
+ }
+ StorageAssistant.save(track, sender, plugin);
+ return true;
+ }
+
+ private boolean readGroupDeletion(JsonElement data, Sender sender, LuckPermsPlugin plugin) {
+ String groupName = data.getAsString();
+
+ if (groupName.equalsIgnoreCase(NodeFactory.DEFAULT_GROUP_NAME)) {
+ Message.DELETE_GROUP_ERROR_DEFAULT.send(sender);
+ return true;
+ }
+
+ Group group = plugin.getStorage().loadGroup(groupName).join().orElse(null);
+ if (group == null) {
+ return false;
+ }
+
+ try {
+ plugin.getStorage().deleteGroup(group, DeletionCause.COMMAND).get();
+ } catch (Exception e) {
+ e.printStackTrace();
+ Message.DELETE_ERROR.send(sender, group.getFormattedDisplayName());
+ return true;
+ }
+
+ Message.DELETE_SUCCESS.send(sender, group.getFormattedDisplayName());
+
+ LoggedAction.build().source(sender).targetName(groupName).targetType(Action.Target.Type.GROUP)
+ .description("webeditor", "delete")
+ .build().submit(plugin, sender);
+
+ return true;
+ }
+
+ private boolean readTrackDeletion(JsonElement data, Sender sender, LuckPermsPlugin plugin) {
+ String trackName = data.getAsString();
+
+ Track track = plugin.getStorage().loadTrack(trackName).join().orElse(null);
+ if (track == null) {
+ return false;
+ }
+
+ try {
+ plugin.getStorage().deleteTrack(track, DeletionCause.COMMAND).get();
+ } catch (Exception e) {
+ e.printStackTrace();
+ Message.DELETE_ERROR.send(sender, track.getName());
+ return true;
+ }
+
+ Message.DELETE_SUCCESS.send(sender, trackName);
+
+ LoggedAction.build().source(sender).targetName(trackName).targetType(Action.Target.Type.TRACK)
+ .description("webeditor", "delete")
+ .build().submit(plugin, sender);
+
+ return true;
+ }
+
private static String formatNode(LocaleManager localeManager, Node n) {
return n.getKey() + " &7(" + (n.getValue() ? "&a" : "&c") + n.getValue() + "&7)" + MessageUtils.getAppendableNodeContextString(localeManager, n) +
(n.hasExpiry() ? " &7(" + DurationFormatter.CONCISE.formatDateDiff(n.getExpiry().getEpochSecond()) + ")" : "");
}
- private static Map.Entry, Set> diff(Set before, Set after) {
+ private static Map.Entry, Set> diff(Set before, Set after) {
// entries in before but not after are being removed
// entries in after but not before are being added
- Set added = new HashSet<>(after);
+ Set added = new LinkedHashSet<>(after);
added.removeAll(before);
- Set removed = new HashSet<>(before);
+ Set removed = new LinkedHashSet<>(before);
removed.removeAll(after);
return Maps.immutableEntry(added, removed);
diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/misc/EditorCommand.java b/common/src/main/java/me/lucko/luckperms/common/commands/misc/EditorCommand.java
index 0bb19578e..c0fa60011 100644
--- a/common/src/main/java/me/lucko/luckperms/common/commands/misc/EditorCommand.java
+++ b/common/src/main/java/me/lucko/luckperms/common/commands/misc/EditorCommand.java
@@ -37,6 +37,7 @@ import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.model.PermissionHolder;
+import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.util.Predicates;
@@ -72,6 +73,7 @@ public class EditorCommand extends SingleCommand {
// collect holders
List holders = new ArrayList<>();
+ List