From a80ec6d8934ea3b0a9d2e04c8ea6674d5700c86a Mon Sep 17 00:00:00 2001 From: Luck Date: Sun, 23 Oct 2016 20:42:58 +0100 Subject: [PATCH] Implement PermissionsEx 2.0 migration for Sponge --- .../migration/MigrationMainCommand.java | 5 + sponge/pom.xml | 49 +++++ .../luckperms/sponge/LPSpongePlugin.java | 11 +- .../migration/MigrationPermissionsEx.java | 167 ++++++++++++++++++ 4 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationPermissionsEx.java diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/migration/MigrationMainCommand.java b/common/src/main/java/me/lucko/luckperms/common/commands/migration/MigrationMainCommand.java index 0b8bc0e1..d5efd556 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/migration/MigrationMainCommand.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/migration/MigrationMainCommand.java @@ -69,6 +69,11 @@ public class MigrationMainCommand extends MainCommand { Class.forName("de.bananaco.bpermissions.api.WorldManager"); subCommands.add((SubCommand) Class.forName("me.lucko.luckperms.bukkit.migration.MigrationBPermissions").newInstance()); } catch (Throwable ignored) {} + + try { + Class.forName("ninja.leaping.permissionsex.sponge.PermissionsExPlugin"); + subCommands.add((SubCommand) Class.forName("me.lucko.luckperms.sponge.migration.MigrationPermissionsEx").newInstance()); + } catch (Throwable ignored) {} } @Override diff --git a/sponge/pom.xml b/sponge/pom.xml index 6f13a848..a4d60750 100644 --- a/sponge/pom.xml +++ b/sponge/pom.xml @@ -140,5 +140,54 @@ 1.16.10 provided + + + ninja.leaping.permissionsex + permissionsex-sponge + 2.0-SNAPSHOT + provided + + + com.sk89q + squirrelid + + + com.googlecode.json-simple + json-simple + + + org.gnu.gettext + libintl + + + org.antlr + antlr4-runtime + + + + + ninja.leaping.permissionsex + permissionsex-core + 2.0-SNAPSHOT + provided + + + com.sk89q + squirrelid + + + com.googlecode.json-simple + json-simple + + + org.gnu.gettext + libintl + + + org.antlr + antlr4-runtime + + + diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java b/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java index 8ea18400..40b99ca2 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java @@ -62,6 +62,7 @@ import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.game.state.GamePostInitializationEvent; import org.spongepowered.api.event.game.state.GamePreInitializationEvent; import org.spongepowered.api.event.game.state.GameStoppingServerEvent; +import org.spongepowered.api.plugin.Dependency; import org.spongepowered.api.plugin.Plugin; import org.spongepowered.api.scheduler.Scheduler; import org.spongepowered.api.service.permission.PermissionDescription; @@ -77,7 +78,15 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @Getter -@Plugin(id = "luckperms", name = "LuckPerms", version = VersionData.VERSION, authors = {"Luck"}, description = "A permissions plugin") +@Plugin(id = "luckperms", + name = "LuckPerms", + version = VersionData.VERSION, + authors = {"Luck"}, + description = "A permissions plugin", + dependencies = { + @Dependency(id = "permissionsex", optional = true) // Needed for migration. + } +) public class LPSpongePlugin implements LuckPermsPlugin { @Inject diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationPermissionsEx.java b/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationPermissionsEx.java new file mode 100644 index 00000000..b1952624 --- /dev/null +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationPermissionsEx.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2016 Lucko (Luck) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.sponge.migration; + +import me.lucko.luckperms.api.Logger; +import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.common.LuckPermsPlugin; +import me.lucko.luckperms.common.commands.*; +import me.lucko.luckperms.common.constants.Permission; +import me.lucko.luckperms.common.core.Node; +import me.lucko.luckperms.common.core.PermissionHolder; +import me.lucko.luckperms.common.groups.Group; +import me.lucko.luckperms.common.users.User; +import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; +import me.lucko.luckperms.sponge.service.LuckPermsService; +import ninja.leaping.permissionsex.sponge.PermissionsExPlugin; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.plugin.PluginContainer; +import org.spongepowered.api.service.context.Context; +import org.spongepowered.api.service.permission.PermissionService; +import org.spongepowered.api.service.permission.Subject; + +import java.util.*; + +public class MigrationPermissionsEx extends SubCommand { + public MigrationPermissionsEx() { + super("permissionsex", "Migration from PermissionsEx", Permission.MIGRATION, Predicate.alwaysFalse(), null); + } + + @Override + public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List args, String label) { + final Logger log = plugin.getLog(); + + Optional pex = Sponge.getPluginManager().getPlugin("permissionsex"); + if (!pex.isPresent()) { + log.severe("PermissionsEx Migration: Error -> PermissionsEx is not loaded."); + return CommandResult.STATE_ERROR; + } + + // Cast to PermissionService. PEX has all of it's damned classes defined as package private. + PermissionService pexService = (PermissionsExPlugin) pex.get().getInstance().get(); + + // Migrate groups + log.info("PermissionsEx Migration: Starting group migration."); + int groupCount = 0; + for (Subject pexGroup : pexService.getGroupSubjects().getAllSubjects()) { + groupCount++; + + // Make a LuckPerms group for the one being migrated + plugin.getDatastore().createAndLoadGroup(pexGroup.getIdentifier().toLowerCase()).getUnchecked(); + Group group = plugin.getGroupManager().get(pexGroup.getIdentifier().toLowerCase()); + migrateSubject(pexGroup, group); + plugin.getDatastore().saveGroup(group); + } + log.info("PermissionsEx Migration: Migrated " + groupCount + " groups"); + + // Migrate users + log.info("PermissionsEx Migration: Starting user migration."); + int userCount = 0; + for (Subject pexUser : pexService.getUserSubjects().getAllSubjects()) { + userCount++; + UUID uuid = Util.parseUuid(pexUser.getIdentifier()); + if (uuid == null) { + log.severe("PermissionsEx Migration: Error -> Could not parse UUID for user: " + pexUser.getIdentifier()); + continue; + } + + // Make a LuckPerms user for the one being migrated + plugin.getDatastore().loadUser(uuid, "null").getUnchecked(); + User user = plugin.getUserManager().get(uuid); + migrateSubject(pexUser, user); + plugin.getDatastore().saveUser(user); + plugin.getUserManager().cleanup(user); + } + + log.info("PermissionsEx Migration: Migrated " + userCount + " users."); + log.info("PermissionsEx Migration: Success! Completed without any errors."); + return CommandResult.SUCCESS; + } + + private static void migrateSubject(Subject subject, PermissionHolder holder) { + // Migrate permissions + Map, Map> perms = subject.getSubjectData().getAllPermissions(); + for (Map.Entry, Map> e : perms.entrySet()) { + ContextSet context = LuckPermsService.convertContexts(e.getKey()); + + MutableContextSet contexts = MutableContextSet.fromSet(context); + String server = contexts.getValues("server").stream().findAny().orElse(null); + String world = contexts.getValues("world").stream().findAny().orElse(null); + contexts.removeAll("server"); + contexts.removeAll("world"); + + for (Map.Entry perm : e.getValue().entrySet()) { + try { + holder.setPermission(new Node.Builder(perm.getKey()).setServerRaw(server).setWorld(world).withExtraContext(contexts).setValue(perm.getValue()).build()); + } catch (ObjectAlreadyHasException ignored) {} + } + } + + // Migrate options + Map, Map> opts = subject.getSubjectData().getAllOptions(); + for (Map.Entry, Map> e : opts.entrySet()) { + ContextSet context = LuckPermsService.convertContexts(e.getKey()); + + MutableContextSet contexts = MutableContextSet.fromSet(context); + String server = contexts.getValues("server").stream().findAny().orElse(null); + String world = contexts.getValues("world").stream().findAny().orElse(null); + contexts.removeAll("server"); + contexts.removeAll("world"); + + for (Map.Entry opt : e.getValue().entrySet()) { + if (opt.getKey().equalsIgnoreCase("prefix") || opt.getKey().equalsIgnoreCase("prefix")) { + try { + holder.setPermission(new Node.Builder(opt.getKey().toLowerCase() + ".100." + opt.getValue()).setServerRaw(server).setWorld(world).withExtraContext(contexts).setValue(true).build()); + } catch (ObjectAlreadyHasException ignored) {} + } else { + try { + holder.setPermission(new Node.Builder("meta." + opt.getKey() + "." + opt.getValue()).setServerRaw(server).setWorld(world).withExtraContext(contexts).setValue(true).build()); + } catch (ObjectAlreadyHasException ignored) {} + } + } + } + + // Migrate parents + Map, List> parents = subject.getSubjectData().getAllParents(); + for (Map.Entry, List> e : parents.entrySet()) { + ContextSet context = LuckPermsService.convertContexts(e.getKey()); + + MutableContextSet contexts = MutableContextSet.fromSet(context); + String server = contexts.getValues("server").stream().findAny().orElse(null); + String world = contexts.getValues("world").stream().findAny().orElse(null); + contexts.removeAll("server"); + contexts.removeAll("world"); + + for (Subject s : e.getValue()) { + if (!s.getContainingCollection().getIdentifier().equalsIgnoreCase(PermissionService.SUBJECTS_GROUP)) { + continue; // LuckPerms does not support persisting other subject types. + } + + try { + holder.setPermission(new Node.Builder("group." + s.getIdentifier().toLowerCase()).setServerRaw(server).setWorld(world).withExtraContext(contexts).setValue(true).build()); + } catch (ObjectAlreadyHasException ignored) {} + } + } + } +}