Partially add migration support

This commit is contained in:
Luck 2016-08-21 22:20:14 +01:00
parent bbeed1e4ed
commit dd7aee9d15
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
15 changed files with 1019 additions and 3 deletions

View File

@ -156,6 +156,11 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
return getDescription().getVersion();
}
@Override
public Type getType() {
return Type.BUKKIT;
}
@Override
public File getMainDir() {
return getDataFolder();
@ -198,6 +203,21 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
return perms;
}
@Override
public Object getPlugin(String name) {
return getServer().getPluginManager().getPlugin(name);
}
@Override
public Object getService(Class clazz) {
return getServer().getServicesManager().load(clazz);
}
@Override
public boolean isPluginLoaded(String name) {
return getServer().getPluginManager().isPluginEnabled(name);
}
@Override
public void runUpdateTask() {
getServer().getScheduler().runTaskAsynchronously(this, new UpdateTask(this));

View File

@ -126,6 +126,11 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
return getDescription().getVersion();
}
@Override
public Type getType() {
return Type.BUNGEE;
}
@Override
public File getMainDir() {
return getDataFolder();
@ -162,6 +167,24 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
return Collections.emptyList();
}
@Override
public Object getPlugin(String name) {
return getProxy().getPluginManager().getPlugin(name);
}
@Override
public Object getService(Class clazz) {
return null;
}
@Override
public boolean isPluginLoaded(String name) {
return getProxy().getPluginManager().getPlugins().stream()
.filter(p -> p.getDescription().getName().equalsIgnoreCase(name))
.findAny()
.isPresent();
}
@Override
public void runUpdateTask() {
doAsync(new UpdateTask(this));

View File

@ -88,6 +88,37 @@
<version>1.16.10</version>
<scope>provided</scope>
</dependency>
<!-- **************Migration Plugins************** -->
<dependency>
<groupId>org.tyrannyofheaven.bukkit</groupId>
<artifactId>zPermissions</artifactId>
<version>1.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ru.tehkode</groupId>
<artifactId>PermissionsEx</artifactId>
<version>1.23</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.cheesesoftware</groupId>
<artifactId>PowerfulPermsAPI</artifactId>
<version>1.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.anjocaido</groupId>
<artifactId>GroupManager</artifactId>
<version>1.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -63,6 +63,12 @@ public interface LuckPermsPlugin {
*/
String getVersion();
/**
* @return the platform type
*/
Type getType();
/**
* @return the main plugin directory
*/
@ -114,6 +120,27 @@ public interface LuckPermsPlugin {
*/
Set<UUID> getIgnoringLogs();
/**
* Gets a loaded plugins instance from the platform
* @param name the name of the plugin
* @return a plugin instance
*/
Object getPlugin(String name);
/**
* Gets a provided service from the platform.
* @param clazz the class of the service
* @return the service instance, if it is provided for
*/
Object getService(Class clazz);
/**
* Checks if a plugin is loaded on the platform
* @param name the name of the plugin
* @return true if the plugin is loaded
*/
boolean isPluginLoaded(String name);
/**
* Runs an update task
*/
@ -130,4 +157,9 @@ public interface LuckPermsPlugin {
* @param r the task to run
*/
void doSync(Runnable r);
enum Type {
BUKKIT, BUNGEE, SPONGE;
}
}

View File

@ -63,6 +63,7 @@ public class CommandManager {
.add(new InfoCommand())
.add(new DebugCommand())
.add(new ImportCommand())
// .add(new MigrationMainCommand()) TODO
.add(new CreateGroup())
.add(new DeleteGroup())
.add(new ListGroups())

View File

@ -76,7 +76,7 @@ public abstract class MainCommand<T> {
return CommandResult.INVALID_ARGS;
}
Optional<SubCommand<T>> o = subCommands.stream()
Optional<SubCommand<T>> o = getSubCommands().stream()
.filter(s -> s.getName().equalsIgnoreCase(args.get(requiredArgsLength - 1)))
.limit(1)
.findAny();

View File

@ -0,0 +1,91 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* 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.commands.migration;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.CommandResult;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.migration.subcommands.MigrationPowerfulPerms;
import me.lucko.luckperms.constants.Constants;
import me.lucko.luckperms.constants.Message;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MigrationMainCommand extends MainCommand<Object> {
private final List<SubCommand<Object>> subCommands = new ArrayList<>();
public MigrationMainCommand() {
super("Migration", "/%s migration", 1, null);
try {
subCommands.add(new MigrationPowerfulPerms());
} catch (Throwable ignored) {
}
}
@Override
public List<SubCommand<Object>> getSubCommands() {
return subCommands;
}
@Override
protected boolean isAuthorized(Sender sender) {
return sender.getUuid().equals(Constants.getConsoleUUID());
}
@Override
protected CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
if (!sender.getUuid().equals(Constants.getConsoleUUID())) {
Message.MIGRATION_NOT_CONSOLE.send(sender);
return CommandResult.NO_PERMISSION;
}
return super.execute(plugin, sender, args, label);
}
@Override
protected Object getTarget(String target, LuckPermsPlugin plugin, Sender sender) {
return new Object();
}
@Override
protected void cleanup(Object object, LuckPermsPlugin plugin) {
}
@Override
protected List<String> getObjects(LuckPermsPlugin plugin) {
return Collections.emptyList();
}
@Override
protected List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return Collections.emptyList();
}
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* 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.commands.migration.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.commands.CommandResult;
import me.lucko.luckperms.commands.Predicate;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Permission;
import org.anjocaido.groupmanager.GroupManager;
import java.util.List;
public class MigrationGroupManager extends SubCommand<Object> {
public MigrationGroupManager() {
super("groupmanager", "Migration from GroupManager",
"/%s migration groupmanager [world names]", Permission.MIGRATION, Predicate.alwaysFalse());
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
final Logger log = plugin.getLog();
if (!plugin.isPluginLoaded("GroupManager")) {
log.severe("GroupManager Migration: Error -> GroupManager is not loaded.");
return CommandResult.STATE_ERROR;
}
GroupManager gm = (GroupManager) plugin.getPlugin("GroupManager");
// Migrate all users.
log.info("GroupManager Migration: Starting user migration.");
// gm.getWorldsHolder().getWorldData().
// TODO
return null;
}
}

View File

@ -0,0 +1,178 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* 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.commands.migration.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.commands.CommandResult;
import me.lucko.luckperms.commands.Predicate;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import ru.tehkode.permissions.PermissionGroup;
import ru.tehkode.permissions.PermissionManager;
import ru.tehkode.permissions.PermissionUser;
import ru.tehkode.permissions.bukkit.PermissionsEx;
import java.util.List;
import java.util.UUID;
public class MigrationPermissionsEx extends SubCommand<Object> {
public MigrationPermissionsEx() {
super("permissionsex", "Migration from PermissionsEx",
"/%s migration permissionsex [world names]", Permission.MIGRATION, Predicate.alwaysFalse());
}
@SuppressWarnings("deprecation")
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
final Logger log = plugin.getLog();
if (!plugin.isPluginLoaded("PermissionsEx")) {
log.severe("PermissionsEx Migration: Error -> PermissionsEx is not loaded.");
return CommandResult.STATE_ERROR;
}
PermissionsEx pex = (PermissionsEx) plugin.getPlugin("PermissionsEx");
PermissionManager manager = null; // TODO
// Migrate all users
log.info("PermissionsEx Migration: Starting user migration.");
for (PermissionUser user : manager.getUsers()) {
UUID u = UUID.fromString(user.getIdentifier());
plugin.getDatastore().loadOrCreateUser(u, "null");
User lpUser = plugin.getUserManager().get(u);
try {
for (String node : user.getOwnPermissions(null)) {
boolean value = true;
if (node.startsWith("!")) {
node = node.substring(1);
value = false;
}
try {
lpUser.setPermission(node, value);
} catch (ObjectAlreadyHasException ignored) {}
}
} catch (NullPointerException ignored) {
// Probably won't happen. I have no API docs on getOwnPermissions#null though.
}
if (args != null && !args.isEmpty()) {
for (String world : args) {
for (String node : user.getOwnPermissions(world)) {
boolean value = true;
if (node.startsWith("!")) {
node = node.substring(1);
value = false;
}
try {
lpUser.setPermission(node, value, "global", world);
} catch (ObjectAlreadyHasException ignored) {}
}
}
}
for (String s : user.getGroupNames()) {
try {
lpUser.setPermission("group." + s.toLowerCase(), true);
} catch (ObjectAlreadyHasException ignored) {}
}
if (args != null && !args.isEmpty()) {
for (String world : args) {
for (String s : user.getGroupNames(world)) {
try {
lpUser.setPermission("group." + s.toLowerCase(), true, "global", world);
} catch (ObjectAlreadyHasException ignored) {}
}
}
}
plugin.getUserManager().cleanup(lpUser);
plugin.getDatastore().saveUser(lpUser);
}
// Migrate all groups.
log.info("PermissionsEx Migration: Starting group migration.");
for (PermissionGroup group : manager.getGroupList()) {
final String name = group.getName().toLowerCase();
plugin.getDatastore().createAndLoadGroup(name);
Group lpGroup = plugin.getGroupManager().get(name);
try {
for (String node : group.getOwnPermissions(null)) {
boolean value = true;
if (node.startsWith("!")) {
node = node.substring(1);
value = false;
}
try {
lpGroup.setPermission(node, value);
} catch (ObjectAlreadyHasException ignored) {}
}
} catch (NullPointerException ignored) {
// Probably won't happen. I have no API docs on getOwnPermissions#null though.
}
if (args != null && !args.isEmpty()) {
for (String world : args) {
for (String node : group.getOwnPermissions(world)) {
boolean value = true;
if (node.startsWith("!")) {
node = node.substring(1);
value = false;
}
try {
lpGroup.setPermission(node, value, "global", world);
} catch (ObjectAlreadyHasException ignored) {}
}
}
}
for (PermissionGroup g : group.getParents()) {
try {
lpGroup.setPermission("group." + g.getName().toLowerCase(), true);
} catch (ObjectAlreadyHasException ignored) {}
}
if (args != null && !args.isEmpty()) {
for (String world : args) {
for (PermissionGroup g : group.getParents(world)) {
try {
lpGroup.setPermission("group." + g.getName().toLowerCase(), true, "global", world);
} catch (ObjectAlreadyHasException ignored) {}
}
}
}
}
return CommandResult.SUCCESS;
}
}

View File

@ -0,0 +1,411 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* 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.commands.migration.subcommands;
import com.github.cheesesoftware.PowerfulPermsAPI.*;
import com.zaxxer.hikari.HikariDataSource;
import lombok.Cleanup;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.commands.CommandResult;
import me.lucko.luckperms.commands.Predicate;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.core.PermissionHolder;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.users.User;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import static me.lucko.luckperms.constants.Permission.MIGRATION;
public class MigrationPowerfulPerms extends SubCommand<Object> {
/* <sadness>
What kind of API requires reflection to function with multiple versions...
Doesn't that just defeat the whole god damn point of having an API in the first place?
Whatever happened to the concept of depreciation and responsible API creation?
I tried to keep reflection to a minimum, but in some places there's no other option.
This class is a complete fucking mess for that reason. I sad now :(
</sadness> */
private static Method getPlayerGroupsMethod = null;
private static Method getGroupMethod = null;
private static boolean legacy = true;
static {
try {
getPlayerGroupsMethod = PermissionManager.class.getMethod("getPlayerOwnGroups", UUID.class, ResultRunnable.class);
getPlayerGroupsMethod.setAccessible(true);
} catch (NoSuchMethodException e) {
try {
getPlayerGroupsMethod = PermissionManager.class.getMethod("getPlayerGroups", UUID.class, ResultRunnable.class);
getPlayerGroupsMethod.setAccessible(true);
} catch (NoSuchMethodException e1) {
e1.printStackTrace();
}
}
try {
getGroupMethod = CachedGroup.class.getMethod("getGroup");
getGroupMethod.setAccessible(true);
legacy = true;
} catch (NoSuchMethodException ignored) {
}
}
public MigrationPowerfulPerms() {
super("powerfulperms", "Migration from PowerfulPerms",
"/%s migration powerfulperms <address> <database> <username> <password> <db table>", MIGRATION, Predicate.not(5));
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
try {
return run(plugin, args);
} catch (Throwable t) {
t.printStackTrace();
return CommandResult.FAILURE;
}
}
private CommandResult run(LuckPermsPlugin plugin, List<String> args) {
final Logger log = plugin.getLog();
if (!plugin.isPluginLoaded("PowerfulPerms")) {
log.severe("PowerfulPerms Migration: Error -> PowerfulPerms is not loaded.");
return CommandResult.STATE_ERROR;
}
final String address = args.get(0);
final String database = args.get(1);
final String username = args.get(2);
final String password = args.get(3);
final String dbTable = args.get(4);
// Find a list of UUIDs
log.info("PowerfulPerms Migration: Getting a list of UUIDs to migrate.");
HikariDataSource hikari = new HikariDataSource();
hikari.setMaximumPoolSize(2);
hikari.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource");
hikari.addDataSourceProperty("serverName", address.split(":")[0]);
hikari.addDataSourceProperty("port", address.split(":")[1]);
hikari.addDataSourceProperty("databaseName", database);
hikari.addDataSourceProperty("user", username);
hikari.addDataSourceProperty("password", password);
Set<UUID> uuids = new HashSet<>();
try {
@Cleanup Connection connection = hikari.getConnection();
DatabaseMetaData meta = connection.getMetaData();
@Cleanup ResultSet tables = meta.getTables(null, null, dbTable, null);
if (!tables.next()) {
log.severe("PowerfulPerms Migration: Error - Couldn't find table.");
return CommandResult.FAILURE;
} else {
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement("SELECT `uuid` FROM " + dbTable);
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
uuids.add(UUID.fromString(resultSet.getString("uuid")));
}
}
} catch (Exception e) {
e.printStackTrace();
return CommandResult.FAILURE;
}
if (uuids.isEmpty()) {
log.severe("PowerfulPerms Migration: Error - Unable to find any UUIDs to migrate.");
return CommandResult.FAILURE;
}
log.info("PowerfulPerms Migration: Found " + uuids.size() + " uuids. Starting migration.");
PowerfulPermsPlugin ppPlugin = (PowerfulPermsPlugin) plugin.getPlugin("PowerfulPerms");
PermissionManager pm = ppPlugin.getPermissionManager();
final Map<UUID, CountDownLatch> progress = new HashMap<>();
// Migrate all users and their groups
for (UUID uuid : uuids) {
progress.put(uuid, new CountDownLatch(2));
// Create a LuckPerms user for the UUID
plugin.getDatastore().loadOrCreateUser(uuid, "null");
User user = plugin.getUserManager().get(uuid);
// Get a list of Permissions held by the user from the PP API.
pm.getPlayerOwnPermissions(uuid, new LPResultRunnable<List<Permission>>() {
@Override
public void run() {
List<Permission> perms = this.getResult();
perms.forEach(p -> applyPerm(user, p));
// Update the progress so the user can be saved and unloaded.
synchronized (progress) {
progress.get(uuid).countDown();
if (progress.get(uuid).getCount() == 0) {
plugin.getDatastore().saveUser(user);
plugin.getUserManager().cleanup(user);
}
}
}
});
// Migrate the user's groups to LuckPerms from PP.
try {
getPlayerGroupsMethod.invoke(pm, uuid, new LPResultRunnable<LinkedHashMap<String, List<CachedGroup>>>() {
@Override
public void run() {
Map<String, List<CachedGroup>> groups = getResult();
for (Map.Entry<String, List<CachedGroup>> e : groups.entrySet()) {
final String server;
if (e.getKey() != null && (e.getKey().equals("") || e.getKey().equalsIgnoreCase("all"))) {
server = null;
} else {
server = e.getKey();
}
// This is horrible. So many random API changes through versions, no depreciation.
if (legacy) {
e.getValue().stream()
.filter(cg -> !cg.isNegated())
.map(cg -> {
try {
return (Group) getGroupMethod.invoke(cg);
} catch (IllegalAccessException | InvocationTargetException e1) {
e1.printStackTrace();
return null;
}
})
.forEach(g -> {
if (g != null) {
if (server == null) {
try {
user.setPermission("group." + g.getName().toLowerCase(), true);
} catch (ObjectAlreadyHasException ignored) {}
} else {
try {
user.setPermission("group." + g.getName().toLowerCase(), true, server);
} catch (ObjectAlreadyHasException ignored) {}
}
}
});
} else {
e.getValue().stream()
.filter(g -> !g.hasExpired() && !g.isNegated())
.forEach(g -> {
final Group group = pm.getGroup(g.getGroupId());
if (g.willExpire()) {
if (server == null) {
try {
user.setPermission("group." + group.getName().toLowerCase(), true, g.getExpirationDate().getTime() / 1000L);
} catch (ObjectAlreadyHasException ignored) {}
} else {
try {
user.setPermission("group." + group.getName().toLowerCase(), true, server, g.getExpirationDate().getTime() / 1000L);
} catch (ObjectAlreadyHasException ignored) {}
}
} else {
if (server == null) {
try {
user.setPermission("group." + group.getName().toLowerCase(), true);
} catch (ObjectAlreadyHasException ignored) {}
} else {
try {
user.setPermission("group." + group.getName().toLowerCase(), true, server);
} catch (ObjectAlreadyHasException ignored) {}
}
}
});
}
}
// Update the progress so the user can be saved and unloaded.
synchronized (progress) {
progress.get(uuid).countDown();
if (progress.get(uuid).getCount() == 0) {
plugin.getDatastore().saveUser(user);
plugin.getUserManager().cleanup(user);
}
}
}
});
} catch (IllegalAccessException | InvocationTargetException e) {
log.info("PowerfulPerms Migration: Error");
e.printStackTrace();
}
}
// The user processes will run individually in separate threads.
// In the meantime, it's should be safe to load in the groups on this thread.
log.info("PowerfulPerms Migration: User migration is now running. Starting group migration.");
// Let's import groups. yay
Map<Integer, Group> groups = pm.getGroups();
for (Group g : groups.values()) {
plugin.getDatastore().createAndLoadGroup(g.getName().toLowerCase());
final me.lucko.luckperms.groups.Group group = plugin.getGroupManager().get(g.getName().toLowerCase());
for (Permission p : g.getOwnPermissions()) {
applyPerm(group, p);
}
for (Group parent : g.getParents()) {
try {
group.setPermission("group." + parent.getName().toLowerCase(), true);
} catch (ObjectAlreadyHasException ignored) {}
}
plugin.getDatastore().saveGroup(group);
}
// All groups are now migrated, but there may still be some users being migrated.
// This block will wait for all users to be completed.
log.info("PowerfulPerms Migration: All groups are now migrated. Waiting for user migration to complete.");
log.info("PowerfulPerms Migration: This may take some time.");
boolean sleep = true;
while (sleep) {
sleep = false;
for (Map.Entry<UUID, CountDownLatch> e : progress.entrySet()) {
if (e.getValue().getCount() != 0) {
sleep = true;
break;
}
}
if (sleep) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// We done.
log.info("PowerfulPerms Migration: Success! Migration completed without any errors.");
return CommandResult.SUCCESS;
}
private void applyPerm(PermissionHolder holder, Permission p) {
String node = p.getPermissionString();
boolean value = true;
if (node.startsWith("!")) {
node = node.substring(1);
value = false;
}
String server = p.getServer();
if (server != null && server.equalsIgnoreCase("all")) {
server = null;
}
String world = p.getWorld();
if (world != null && world.equalsIgnoreCase("all")) {
world = null;
}
long expireAt = 0L;
if (!legacy) {
if (p.willExpire()) {
expireAt = p.getExpirationDate().getTime() / 1000L;
}
}
if (world != null && server == null) {
server = "global";
}
if (world != null) {
if (expireAt == 0L) {
try {
holder.setPermission(node, value, server, world);
} catch (ObjectAlreadyHasException e) {
e.printStackTrace();
}
} else {
try {
holder.setPermission(node, value, server, world, expireAt);
} catch (ObjectAlreadyHasException e) {
e.printStackTrace();
}
}
} else if (server != null) {
if (expireAt == 0L) {
try {
holder.setPermission(node, value, server);
} catch (ObjectAlreadyHasException ignored) {}
} else {
try {
holder.setPermission(node, value, server, expireAt);
} catch (ObjectAlreadyHasException ignored) {}
}
} else {
if (expireAt == 0L) {
try {
holder.setPermission(node, value);
} catch (ObjectAlreadyHasException ignored) {}
} else {
try {
holder.setPermission(node, value, expireAt);
} catch (ObjectAlreadyHasException ignored) {}
}
}
}
/**
* Overrides the default ResultRunnable, callbacks will always run in the same thread. (an async one, hopefully.)
* @param <T> type
*/
@SuppressWarnings("WeakerAccess")
public abstract class LPResultRunnable<T> extends ResultRunnable<T> {
public LPResultRunnable() {
super();
super.sameThread = true;
}
public T getResult() {
return super.result;
}
}
}

View File

@ -0,0 +1,138 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* 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.commands.migration.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.commands.CommandResult;
import me.lucko.luckperms.commands.Predicate;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.users.User;
import org.tyrannyofheaven.bukkit.zPermissions.ZPermissionsService;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* <3 <3 zPermissions <3 <3
* Finally a permissions plugin with a decent API. *sigh*
*/
public class MigrationZPermissions extends SubCommand<Object> {
public MigrationZPermissions() {
super("zpermissions", "Migration from zPermissions",
"/%s migration zpermissions [world names]", Permission.MIGRATION, Predicate.alwaysFalse());
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
final Logger log = plugin.getLog();
if (!plugin.isPluginLoaded("zPermissions")) {
log.severe("zPermissions Migration: Error -> zPermissions is not loaded.");
return CommandResult.STATE_ERROR;
}
ZPermissionsService service = (ZPermissionsService) plugin.getService(ZPermissionsService.class);
if (service == null) {
log.severe("zPermissions Migration: Error -> zPermissions is not loaded.");
return CommandResult.STATE_ERROR;
}
// Migrate all users.
log.info("zPermissions Migration: Starting user migration.");
for (UUID u : service.getAllPlayersUUID()) {
plugin.getDatastore().loadOrCreateUser(u, "null");
User user = plugin.getUserManager().get(u);
for (Map.Entry<String, Boolean> e : service.getPlayerPermissions(null, null, u).entrySet()) {
try {
user.setPermission(e.getKey(), e.getValue());
} catch (ObjectAlreadyHasException ignored) {}
}
if (args != null && !args.isEmpty()) {
for (String world : args) {
for (Map.Entry<String, Boolean> e : service.getPlayerPermissions(world, null, u).entrySet()) {
try {
user.setPermission(e.getKey(), e.getValue(), "global", world);
} catch (ObjectAlreadyHasException ignored) {}
}
}
}
for (String g : service.getPlayerAssignedGroups(u)) {
try {
user.setPermission("group." + g.toLowerCase(), true);
} catch (ObjectAlreadyHasException ignored) {}
}
user.setPrimaryGroup(service.getPlayerPrimaryGroup(u));
plugin.getUserManager().cleanup(user);
plugin.getDatastore().saveUser(user);
}
// Migrate all tracks
log.info("zPermissions Migration: Starting track migration.");
for (String t : service.getAllTracks()) {
plugin.getDatastore().createAndLoadTrack(t.toLowerCase());
Track track = plugin.getTrackManager().get(t.toLowerCase());
track.setGroups(service.getTrackGroups(t));
plugin.getDatastore().saveTrack(track);
}
// Migrate all groups
log.info("zPermissions Migration: Starting group migration.");
for (String g : service.getAllGroups()) {
plugin.getDatastore().createAndLoadGroup(g.toLowerCase());
Group group = plugin.getGroupManager().get(g.toLowerCase());
for (Map.Entry<String, Boolean> e : service.getGroupPermissions(null, null, g).entrySet()) {
try {
group.setPermission(e.getKey(), e.getValue());
} catch (ObjectAlreadyHasException ignored) {}
}
if (args != null && !args.isEmpty()) {
for (String world : args) {
for (Map.Entry<String, Boolean> e : service.getGroupPermissions(world, null, g).entrySet()) {
try {
group.setPermission(e.getKey(), e.getValue(), "global", world);
} catch (ObjectAlreadyHasException ignored) {}
}
}
}
plugin.getDatastore().saveGroup(group);
}
log.info("zPermissions Migration: Complete!");
return CommandResult.SUCCESS;
}
}

View File

@ -298,7 +298,9 @@ public enum Message {
),
IMPORT_END_ERROR_CONTENT("&e(Import) &d-> &c%s", true),
IMPORT_END_ERROR_FOOTER("&e(Import) &7<------------------------------------------>", true);
IMPORT_END_ERROR_FOOTER("&e(Import) &7<------------------------------------------>", true),
MIGRATION_NOT_CONSOLE("Migration must be performed from the Console.", true);
private String message;
private boolean showPrefix;

View File

@ -89,7 +89,9 @@ public enum Permission {
LOG_TRACK_HISTORY("trackhistory", "log"),
LOG_SEARCH("search", "log"),
LOG_NOTIFY("notify", "log"),
LOG_EXPORT("export", "log");
LOG_EXPORT("export", "log"),
MIGRATION("migration", null);
private String node;
private String group;

View File

@ -71,5 +71,13 @@
<id>sponge-repo</id>
<url>https://repo.spongepowered.org/maven</url>
</repository>
<repository>
<id>pex-repo</id>
<url>http://pex-repo.aoeu.xyz</url>
</repository>
<repository>
<id>alskebo-repo</id>
<url>http://repo.alskebo.com/repository/maven-releases</url>
</repository>
</repositories>
</project>

View File

@ -190,6 +190,11 @@ public class LPSpongePlugin implements LuckPermsPlugin {
return "null";
}
@Override
public Type getType() {
return Type.SPONGE;
}
@Override
public Message getPlayerStatus(UUID uuid) {
return game.getServer().getPlayer(getUuidCache().getExternalUUID(uuid)).isPresent() ? Message.PLAYER_ONLINE : Message.PLAYER_OFFLINE;
@ -224,6 +229,21 @@ public class LPSpongePlugin implements LuckPermsPlugin {
return p.get().getDescriptions().stream().map(PermissionDescription::getId).collect(Collectors.toList());
}
@Override
public Object getPlugin(String name) {
return game.getPluginManager().getPlugin(name).get().getInstance().get();
}
@Override
public Object getService(Class clazz) {
return Sponge.getServiceManager().provideUnchecked(clazz);
}
@Override
public boolean isPluginLoaded(String name) {
return game.getPluginManager().isLoaded(name);
}
@Override
public void runUpdateTask() {
scheduler.createTaskBuilder().async().execute(new UpdateTask(this)).submit(LPSpongePlugin.this);