mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2025-01-23 16:51:43 +01:00
Web editor changes, towards #1703
This commit is contained in:
parent
eff93c788b
commit
5e2f45ebd0
@ -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
|
||||
*/
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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<N extends ScopedNode<N, B>, B extends NodeBuilder<N
|
||||
* <p>The parameter passed to this method must be the unix timestamp
|
||||
* (in seconds) when the node should expire.</p>
|
||||
*
|
||||
* @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.
|
||||
|
@ -36,6 +36,9 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
*/
|
||||
public interface ScopedNode<N extends ScopedNode<N, B>, B extends NodeBuilder<N, B>> extends Node {
|
||||
|
||||
@Override
|
||||
@NonNull NodeType<N> getType();
|
||||
|
||||
@Override
|
||||
@NonNull B toBuilder();
|
||||
|
||||
|
@ -58,7 +58,7 @@ public interface ChatMetaNode<N extends ChatMetaNode<N, B>, B extends ChatMetaNo
|
||||
*
|
||||
* @return the type
|
||||
*/
|
||||
@NonNull ChatMetaType getType();
|
||||
@NonNull ChatMetaType getMetaType();
|
||||
|
||||
/**
|
||||
* A {@link ChatMetaNode} builder.
|
||||
|
@ -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<DisplayNameNode, DisplayNameNode.Builder> {
|
||||
|
||||
@Override
|
||||
default @NonNull NodeType<DisplayNameNode> getType() {
|
||||
return NodeType.DISPLAY_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the display name.
|
||||
*
|
||||
|
@ -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<InheritanceNode, InheritanceNode.Builder> {
|
||||
|
||||
@Override
|
||||
default @NonNull NodeType<InheritanceNode> getType() {
|
||||
return NodeType.INHERITANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the group to be inherited.
|
||||
*
|
||||
|
@ -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<MetaNode, MetaNode.Builder> {
|
||||
|
||||
@Override
|
||||
default @NonNull NodeType<MetaNode> getType() {
|
||||
return NodeType.META;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the meta key.
|
||||
*
|
||||
|
@ -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<PermissionNode, PermissionNode.Builder> {
|
||||
|
||||
@Override
|
||||
default @NonNull NodeType<PermissionNode> getType() {
|
||||
return NodeType.PERMISSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the permission string this node encapsulates.
|
||||
*
|
||||
|
@ -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<PrefixNode, PrefixNode.Builder> {
|
||||
|
||||
@Override
|
||||
default @NonNull NodeType<PrefixNode> getType() {
|
||||
return NodeType.PREFIX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link PrefixNode} builder.
|
||||
*
|
||||
|
@ -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<RegexPermissionNode, RegexPermissionNode.Builder> {
|
||||
|
||||
@Override
|
||||
default @NonNull NodeType<RegexPermissionNode> getType() {
|
||||
return NodeType.REGEX_PERMISSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the non-compiled pattern string.
|
||||
*
|
||||
|
@ -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<SuffixNode, SuffixNode.Builder> {
|
||||
|
||||
@Override
|
||||
default @NonNull NodeType<SuffixNode> getType() {
|
||||
return NodeType.SUFFIX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SuffixNode} builder.
|
||||
*
|
||||
|
@ -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<WeightNode, WeightNode.Builder> {
|
||||
|
||||
@Override
|
||||
default @NonNull NodeType<WeightNode> getType() {
|
||||
return NodeType.WEIGHT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the weight value.
|
||||
*
|
||||
|
@ -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());
|
||||
|
@ -66,7 +66,7 @@ public class HolderEditor<T extends PermissionHolder> extends SubCommand<T> {
|
||||
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();
|
||||
|
@ -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<NodeDataContainer> nodes = WebEditor.deserializePermissions(data.getAsJsonArray("nodes"));
|
||||
|
||||
Set<Node> before = new HashSet<>(holder.normalData().immutable().values());
|
||||
Set<Node> after = nodes.stream().map(NodeDataContainer::toNode).collect(Collectors.toSet());
|
||||
Set<Node> after = new HashSet<>(WebEditor.deserializePermissions(data.getAsJsonArray("nodes")));
|
||||
|
||||
Map.Entry<Set<Node>, Set<Node>> diff = diff(before, after);
|
||||
Set<Node> 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<String> before = new LinkedHashSet<>(track.getGroups());
|
||||
Set<String> after = new LinkedHashSet<>();
|
||||
data.getAsJsonArray("groups").forEach(e -> after.add(e.getAsString()));
|
||||
|
||||
Map.Entry<Set<String>, Set<String>> diff = diff(before, after);
|
||||
Set<String> diffAdded = diff.getKey();
|
||||
Set<String> 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<Node>, Set<Node>> diff(Set<Node> before, Set<Node> after) {
|
||||
private static <T> Map.Entry<Set<T>, Set<T>> diff(Set<T> before, Set<T> after) {
|
||||
// entries in before but not after are being removed
|
||||
// entries in after but not before are being added
|
||||
|
||||
Set<Node> added = new HashSet<>(after);
|
||||
Set<T> added = new LinkedHashSet<>(after);
|
||||
added.removeAll(before);
|
||||
|
||||
Set<Node> removed = new HashSet<>(before);
|
||||
Set<T> removed = new LinkedHashSet<>(before);
|
||||
removed.removeAll(after);
|
||||
|
||||
return Maps.immutableEntry(added, removed);
|
||||
|
@ -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<PermissionHolder> holders = new ArrayList<>();
|
||||
List<Track> tracks = new ArrayList<>();
|
||||
if (type.includingGroups) {
|
||||
plugin.getGroupManager().getAll().values().stream()
|
||||
.sorted((o1, o2) -> {
|
||||
@ -79,6 +81,7 @@ public class EditorCommand extends SingleCommand {
|
||||
return i != 0 ? i : o1.getName().compareToIgnoreCase(o2.getName());
|
||||
})
|
||||
.forEach(holders::add);
|
||||
tracks = new ArrayList<>(plugin.getTrackManager().getAll().values());
|
||||
}
|
||||
if (type.includingUsers) {
|
||||
plugin.getUserManager().getAll().values().stream()
|
||||
@ -93,9 +96,10 @@ public class EditorCommand extends SingleCommand {
|
||||
|
||||
// remove holders which the sender doesn't have perms to view
|
||||
holders.removeIf(holder -> ArgumentPermissions.checkViewPerms(plugin, sender, getPermission().get(), holder));
|
||||
tracks.removeIf(track -> ArgumentPermissions.checkViewPerms(plugin, sender, getPermission().get(), track));
|
||||
|
||||
// they don't have perms to view any of them
|
||||
if (holders.isEmpty()) {
|
||||
if (holders.isEmpty() && tracks.isEmpty()) {
|
||||
Message.COMMAND_NO_PERMISSION.send(sender);
|
||||
return CommandResult.NO_PERMISSION;
|
||||
}
|
||||
@ -103,7 +107,7 @@ public class EditorCommand extends SingleCommand {
|
||||
Message.EDITOR_START.send(sender);
|
||||
|
||||
// form the payload data
|
||||
JsonObject payload = WebEditor.formPayload(holders, sender, label, plugin);
|
||||
JsonObject payload = WebEditor.formPayload(holders, tracks, sender, label, plugin);
|
||||
|
||||
// upload the payload data to gist
|
||||
String pasteId = plugin.getBytebin().postJson(payload, true).id();
|
||||
|
@ -152,13 +152,12 @@ public enum Message {
|
||||
|
||||
APPLY_EDITS_INVALID_CODE("&cInvalid code. &7({})", true),
|
||||
APPLY_EDITS_UNABLE_TO_READ("&cUnable to read data using the given code. &7({})", true),
|
||||
APPLY_EDITS_NO_TARGET("&cUnable to parse the target of the edit.", true),
|
||||
APPLY_EDITS_TARGET_GROUP_NOT_EXISTS("&cTarget group &4{}&c does not exist.", true),
|
||||
APPLY_EDITS_UNKNOWN_TYPE("&cUnable to apply edit to the specified object type. &7({})", true),
|
||||
APPLY_EDITS_TARGET_USER_NOT_UUID("&cTarget user &4{}&c is not a valid uuid.", true),
|
||||
APPLY_EDITS_TARGET_USER_UNABLE_TO_LOAD("&cUnable to load target user &4{}&c.", true),
|
||||
APPLY_EDITS_TARGET_UNKNOWN("&cInvalid target. &7({})", true),
|
||||
APPLY_EDITS_TARGET_NO_CHANGES_PRESENT("&aNo changes were applied from the web editor. The returned data didn't contain any edits.", true),
|
||||
APPLY_EDITS_SUCCESS("&aWeb editor data was applied to &b{}&a successfully.", true),
|
||||
APPLY_EDITS_SUCCESS("&aWeb editor data was applied to {} &b{}&a successfully.", true),
|
||||
APPLY_EDITS_SUCCESS_SUMMARY("&7(&a{} &7{} and &c{} &7{})", true),
|
||||
APPLY_EDITS_DIFF_ADDED("&a+ &f{}", false),
|
||||
APPLY_EDITS_DIFF_REMOVED("&c- &f{}", false),
|
||||
|
@ -87,7 +87,7 @@ public final class Track implements Identifiable<String> {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return this.name.toLowerCase();
|
||||
return getName();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -35,6 +35,8 @@ 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.ChronoField;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@ -72,8 +74,18 @@ public abstract class AbstractNodeBuilder<N extends ScopedNode<N, B>, B extends
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull B expiry(long expiryUnixTimestamp) {
|
||||
this.expireAt = expiryUnixTimestamp;
|
||||
public @NonNull B expiry(long expiryEpochSeconds) {
|
||||
this.expireAt = expiryEpochSeconds;
|
||||
return (B) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull B expiry(@Nullable TemporalAccessor expiry) {
|
||||
if (expiry == null) {
|
||||
return clearExpiry();
|
||||
}
|
||||
|
||||
this.expireAt = expiry.getLong(ChronoField.INSTANT_SECONDS);
|
||||
return (B) this;
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,7 @@ public final class NodeFactory {
|
||||
sb.append("temp");
|
||||
}
|
||||
|
||||
sb.append(cmNode.getType().toString())
|
||||
sb.append(cmNode.getMetaType().toString())
|
||||
.append(" ")
|
||||
.append(cmNode.getPriority()) // weight
|
||||
.append(" ");
|
||||
|
@ -59,7 +59,7 @@ public class Prefix extends AbstractNode<PrefixNode, PrefixNode.Builder> impleme
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ChatMetaType getType() {
|
||||
public @NonNull ChatMetaType getMetaType() {
|
||||
return ChatMetaType.PREFIX;
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ public class Suffix extends AbstractNode<SuffixNode, SuffixNode.Builder> impleme
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ChatMetaType getType() {
|
||||
public @NonNull ChatMetaType getMetaType() {
|
||||
return ChatMetaType.SUFFIX;
|
||||
}
|
||||
|
||||
|
@ -665,7 +665,7 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio
|
||||
attributes.getNode("priority").setValue(chatMeta.getPriority());
|
||||
writeAttributesTo(attributes, node, false);
|
||||
|
||||
switch (chatMeta.getType()) {
|
||||
switch (chatMeta.getMetaType()) {
|
||||
case PREFIX:
|
||||
appendNode(prefixesSection, chatMeta.getMetaValue(), attributes, "prefix");
|
||||
break;
|
||||
|
@ -30,17 +30,14 @@ import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.api.node.Node;
|
||||
import me.lucko.luckperms.api.node.NodeBuilder;
|
||||
import me.lucko.luckperms.common.context.ContextSetJsonSerializer;
|
||||
import me.lucko.luckperms.common.locale.message.Message;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.HolderType;
|
||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
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.Uuids;
|
||||
import me.lucko.luckperms.common.util.gson.GsonProvider;
|
||||
import me.lucko.luckperms.common.util.gson.JArray;
|
||||
import me.lucko.luckperms.common.util.gson.JObject;
|
||||
@ -54,11 +51,11 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Utility methods for interacting with the LuckPerms web permission editor.
|
||||
@ -66,42 +63,49 @@ import java.util.stream.Stream;
|
||||
public final class WebEditor {
|
||||
private WebEditor() {}
|
||||
|
||||
private static final String USER_ID_PATTERN = "user/";
|
||||
private static final String GROUP_ID_PATTERN = "group/";
|
||||
|
||||
private static JObject writeData(PermissionHolder holder) {
|
||||
return new JObject()
|
||||
.add("who", new JObject()
|
||||
.add("id", getHolderIdentifier(holder))
|
||||
.add("friendly", holder.getPlainDisplayName())
|
||||
.consume(obj -> {
|
||||
if (holder.getType() == HolderType.USER) {
|
||||
obj.add("uuid", ((User) holder).getUuid().toString());
|
||||
}
|
||||
}))
|
||||
.add("nodes", serializePermissions(holder.normalData().immutable().values().stream().map(NodeDataContainer::fromNode)));
|
||||
.add("type", holder.getType().toString())
|
||||
.add("id", holder.getObjectName())
|
||||
.add("displayName", holder.getPlainDisplayName())
|
||||
.add("nodes", serializePermissions(holder.normalData().immutable().values()));
|
||||
}
|
||||
|
||||
public static JsonObject formPayload(List<PermissionHolder> holders, Sender sender, String cmdLabel, LuckPermsPlugin plugin) {
|
||||
private static JObject writeData(Track track) {
|
||||
return new JObject()
|
||||
.add("type", "track")
|
||||
.add("id", track.getName())
|
||||
.add("groups", new JArray().consume(a -> track.getGroups().forEach(a::add)));
|
||||
}
|
||||
|
||||
public static JsonObject formPayload(List<PermissionHolder> holders, List<Track> tracks, Sender sender, String cmdLabel, LuckPermsPlugin plugin) {
|
||||
Preconditions.checkArgument(!holders.isEmpty(), "holders is empty");
|
||||
|
||||
// form the payload data
|
||||
return new JObject()
|
||||
.add("metadata", new JObject()
|
||||
.add("cmdAlias", cmdLabel)
|
||||
.add("commandAlias", cmdLabel)
|
||||
.add("uploader", new JObject()
|
||||
.add("name", sender.getNameWithLocation())
|
||||
.add("uuid", sender.getUuid().toString())
|
||||
)
|
||||
.add("time", System.currentTimeMillis())
|
||||
.add("pluginVersion", plugin.getBootstrap().getVersion())
|
||||
)
|
||||
.add("sessions", new JArray()
|
||||
.add("permissionHolders", new JArray()
|
||||
.consume(arr -> {
|
||||
for (PermissionHolder holder : holders) {
|
||||
arr.add(writeData(holder));
|
||||
}
|
||||
})
|
||||
)
|
||||
.add("tracks", new JArray()
|
||||
.consume(arr -> {
|
||||
for (Track track : tracks) {
|
||||
arr.add(writeData(track));
|
||||
}
|
||||
})
|
||||
)
|
||||
.add("knownPermissions", new JArray()
|
||||
.consume(arr -> {
|
||||
for (String perm : plugin.getPermissionRegistry().rootAsList()) {
|
||||
@ -111,42 +115,6 @@ public final class WebEditor {
|
||||
).toJson();
|
||||
}
|
||||
|
||||
private static String getHolderIdentifier(PermissionHolder holder) {
|
||||
if (holder.getType() == HolderType.USER) {
|
||||
User user = ((User) holder);
|
||||
return USER_ID_PATTERN + user.getUuid().toString();
|
||||
} else {
|
||||
Group group = ((Group) holder);
|
||||
return GROUP_ID_PATTERN + group.getName();
|
||||
}
|
||||
}
|
||||
|
||||
public static PermissionHolder getHolderFromIdentifier(LuckPermsPlugin plugin, Sender sender, String who) {
|
||||
if (who.startsWith(GROUP_ID_PATTERN)) {
|
||||
String group = who.substring(GROUP_ID_PATTERN.length());
|
||||
Group holder = plugin.getStorage().loadGroup(group).join().orElse(null);
|
||||
if (holder == null) {
|
||||
Message.APPLY_EDITS_TARGET_GROUP_NOT_EXISTS.send(sender, group);
|
||||
}
|
||||
return holder;
|
||||
} else if (who.startsWith(USER_ID_PATTERN)) {
|
||||
String user = who.substring(USER_ID_PATTERN.length());
|
||||
UUID uuid = Uuids.parse(user);
|
||||
if (uuid == null) {
|
||||
Message.APPLY_EDITS_TARGET_USER_NOT_UUID.send(sender, user);
|
||||
return null;
|
||||
}
|
||||
User holder = plugin.getStorage().loadUser(uuid, null).join();
|
||||
if (holder == null) {
|
||||
Message.APPLY_EDITS_TARGET_USER_UNABLE_TO_LOAD.send(sender, uuid.toString());
|
||||
}
|
||||
return holder;
|
||||
} else {
|
||||
Message.APPLY_EDITS_TARGET_UNKNOWN.send(sender, who);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static JsonObject readDataFromBytebin(Bytebin bytebin, String id) {
|
||||
Request request = new Request.Builder()
|
||||
.url(bytebin.getPasteUrl(id))
|
||||
@ -169,23 +137,18 @@ public final class WebEditor {
|
||||
}
|
||||
}
|
||||
|
||||
private static JsonArray serializePermissions(Stream<NodeDataContainer> nodes) {
|
||||
private static JsonArray serializePermissions(Collection<Node> nodes) {
|
||||
JsonArray arr = new JsonArray();
|
||||
nodes.forEach(node -> {
|
||||
for (Node node : nodes) {
|
||||
JsonObject attributes = new JsonObject();
|
||||
attributes.addProperty("permission", node.getPermission());
|
||||
|
||||
attributes.addProperty("type", node.getType().name().toLowerCase());
|
||||
attributes.addProperty("key", node.getKey());
|
||||
attributes.addProperty("value", node.getValue());
|
||||
|
||||
if (!node.getServer().equals("global")) {
|
||||
attributes.addProperty("server", node.getServer());
|
||||
}
|
||||
|
||||
if (!node.getWorld().equals("global")) {
|
||||
attributes.addProperty("world", node.getWorld());
|
||||
}
|
||||
|
||||
if (node.getExpiry() != 0L) {
|
||||
attributes.addProperty("expiry", node.getExpiry());
|
||||
Instant expiry = node.getExpiry();
|
||||
if (expiry != null) {
|
||||
attributes.addProperty("expiry", expiry.getEpochSecond());
|
||||
}
|
||||
|
||||
if (!node.getContexts().isEmpty()) {
|
||||
@ -193,48 +156,30 @@ public final class WebEditor {
|
||||
}
|
||||
|
||||
arr.add(attributes);
|
||||
});
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
public static Set<NodeDataContainer> deserializePermissions(JsonArray permissionsSection) {
|
||||
Set<NodeDataContainer> nodes = new HashSet<>();
|
||||
public static Set<Node> deserializePermissions(JsonArray arr) {
|
||||
Set<Node> nodes = new HashSet<>();
|
||||
for (JsonElement ent : arr) {
|
||||
JsonObject attributes = ent.getAsJsonObject();
|
||||
|
||||
for (JsonElement ent : permissionsSection) {
|
||||
if (!ent.isJsonObject()) {
|
||||
continue;
|
||||
String key = attributes.get("key").getAsString();
|
||||
boolean value = attributes.get("value").getAsBoolean();
|
||||
|
||||
NodeBuilder<?, ?> builder = NodeFactory.builder(key).value(value);
|
||||
|
||||
if (attributes.has("expiry")) {
|
||||
builder.expiry(attributes.get("expiry").getAsLong());
|
||||
}
|
||||
|
||||
JsonObject data = ent.getAsJsonObject();
|
||||
|
||||
String permission = data.get("permission").getAsString();
|
||||
boolean value = true;
|
||||
String server = "global";
|
||||
String world = "global";
|
||||
long expiry = 0L;
|
||||
ImmutableContextSet context = ImmutableContextSet.empty();
|
||||
|
||||
if (data.has("value")) {
|
||||
value = data.get("value").getAsBoolean();
|
||||
}
|
||||
if (data.has("server")) {
|
||||
server = data.get("server").getAsString();
|
||||
}
|
||||
if (data.has("world")) {
|
||||
world = data.get("world").getAsString();
|
||||
}
|
||||
if (data.has("expiry")) {
|
||||
expiry = data.get("expiry").getAsLong();
|
||||
if (attributes.has("context")) {
|
||||
builder.context(ContextSetJsonSerializer.deserializeContextSet(attributes.get("context")));
|
||||
}
|
||||
|
||||
if (data.has("context") && data.get("context").isJsonObject()) {
|
||||
JsonObject contexts = data.get("context").getAsJsonObject();
|
||||
context = ContextSetJsonSerializer.deserializeContextSet(contexts).immutableCopy();
|
||||
}
|
||||
|
||||
nodes.add(NodeDataContainer.of(permission, value, server, world, expiry, context));
|
||||
nodes.add(builder.build());
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user