From a766c0e9aa31789524abcc4e264eee76e9bee603 Mon Sep 17 00:00:00 2001 From: Luck Date: Fri, 19 Feb 2021 14:33:54 +0000 Subject: [PATCH] Support the web editor payload format in /lp import This means that if a user accidentally deletes data locally but still has a working web editor session, they can automatically recover the data contained in the session by importing it with the --upload flag. Of course, this will only be able to recover the data present in the session. The sensible thing would be to create proper backups (using /lp export or otherwise) - but hey, people are dumb. --- .../luckperms/common/backup/Importer.java | 76 +++++++++++++++---- 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/common/src/main/java/me/lucko/luckperms/common/backup/Importer.java b/common/src/main/java/me/lucko/luckperms/common/backup/Importer.java index 2d5844c9d..dd3a837c1 100644 --- a/common/src/main/java/me/lucko/luckperms/common/backup/Importer.java +++ b/common/src/main/java/me/lucko/luckperms/common/backup/Importer.java @@ -33,11 +33,13 @@ import com.google.gson.JsonObject; import me.lucko.luckperms.common.locale.Message; import me.lucko.luckperms.common.model.Group; +import me.lucko.luckperms.common.model.HolderType; import me.lucko.luckperms.common.model.Track; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.node.utils.NodeJsonSerializer; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.sender.Sender; +import me.lucko.luckperms.common.util.Uuids; import net.luckperms.api.event.cause.CreationCause; import net.luckperms.api.model.data.DataType; @@ -131,20 +133,7 @@ public class Importer implements Runnable { } } - @Override - public void run() { - long startTime = System.currentTimeMillis(); - this.notify.forEach(Message.IMPORT_START::send); - - // start an update task in the background - we'll #join this later - CompletableFuture updateTask = CompletableFuture.runAsync(() -> this.plugin.getSyncTaskBuffer().requestDirectly()); - - this.notify.forEach(s -> Message.IMPORT_INFO.send(s, "Reading data...")); - - Map> groups = new HashMap<>(); - Map> tracks = new HashMap<>(); - Map users = new HashMap<>(); - + private void parseExportData(Map> groups, Map> tracks, Map users) { for (Map.Entry group : getDataSection("groups")) { groups.put(group.getKey(), NodeJsonSerializer.deserializeNodes(group.getValue().getAsJsonObject().get("nodes").getAsJsonArray())); } @@ -171,6 +160,65 @@ public class Importer implements Runnable { users.put(uuid, new UserData(username, primaryGroup, nodes)); } + } + + private void parseWebEditorData(Map> groups, Map> tracks, Map users) { + JsonArray holdersArray = this.data.get("permissionHolders").getAsJsonArray(); + for (JsonElement holderElement : holdersArray) { + JsonObject jsonData = holderElement.getAsJsonObject(); + + HolderType type = HolderType.valueOf(jsonData.get("type").getAsString().toUpperCase()); + String id = jsonData.get("id").getAsString(); + + if (type == HolderType.GROUP) { + groups.put(id, NodeJsonSerializer.deserializeNodes(jsonData.get("nodes").getAsJsonArray())); + } else { + UUID uuid = UUID.fromString(id); + String username = null; + + String displayName = jsonData.get("displayName").getAsString(); + if (!Uuids.PREDICATE.test(displayName)) { + username = displayName; + } + + Set nodes = NodeJsonSerializer.deserializeNodes(jsonData.get("nodes").getAsJsonArray()); + users.put(uuid, new UserData(username, null, nodes)); + } + } + + JsonArray tracksArray = this.data.get("tracks").getAsJsonArray(); + for (JsonElement trackElement : tracksArray) { + JsonObject jsonData = trackElement.getAsJsonObject(); + + String name = jsonData.get("id").getAsString(); + JsonArray trackGroups = jsonData.get("groups").getAsJsonArray(); + + List trackGroupsList = new ArrayList<>(); + trackGroups.forEach(g -> trackGroupsList.add(g.getAsString())); + tracks.put(name, trackGroupsList); + } + } + + @Override + public void run() { + long startTime = System.currentTimeMillis(); + this.notify.forEach(Message.IMPORT_START::send); + + // start an update task in the background - we'll #join this later + CompletableFuture updateTask = CompletableFuture.runAsync(() -> this.plugin.getSyncTaskBuffer().requestDirectly()); + + this.notify.forEach(s -> Message.IMPORT_INFO.send(s, "Reading data...")); + + Map> groups = new HashMap<>(); + Map> tracks = new HashMap<>(); + Map users = new HashMap<>(); + + if (this.data.has("knownPermissions")) { + this.notify.forEach(s -> Message.IMPORT_INFO.send(s, "The data appears to be from a web editor upload - attempting to recover from it")); + parseWebEditorData(groups, tracks, users); + } else { + parseExportData(groups, tracks, users); + } this.notify.forEach(s -> Message.IMPORT_INFO.send(s, "Waiting for initial update task to complete..."));