Cleanup vault hook

This commit is contained in:
Luck 2017-01-05 18:19:14 +00:00
parent 96035d5257
commit 454abec468
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
4 changed files with 120 additions and 91 deletions

View File

@ -208,7 +208,7 @@ public class LPPermissible extends PermissibleBase {
} }
PermissionAttachment result = addAttachment(plugin); PermissionAttachment result = addAttachment(plugin);
if (Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> result.remove(), ticks) == -1) { if (Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, result::remove, ticks) == -1) {
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not add PermissionAttachment to " + parent + " for plugin " + plugin.getDescription().getFullName() + ": Scheduler returned -1"); Bukkit.getServer().getLogger().log(Level.WARNING, "Could not add PermissionAttachment to " + parent + " for plugin " + plugin.getDescription().getFullName() + ": Scheduler returned -1");
result.remove(); result.remove();
return null; return null;

View File

@ -32,6 +32,9 @@ import net.milkbowl.vault.permission.Permission;
import org.bukkit.plugin.ServicePriority; import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.ServicesManager; import org.bukkit.plugin.ServicesManager;
/**
* Handles hooking with the Vault API
*/
@Getter @Getter
public class VaultHook { public class VaultHook {
private VaultChatHook chatHook = null; private VaultChatHook chatHook = null;
@ -40,17 +43,8 @@ public class VaultHook {
public void hook(LPBukkitPlugin plugin) { public void hook(LPBukkitPlugin plugin) {
try { try {
if (permissionHook == null) { if (permissionHook == null) {
permissionHook = new VaultPermissionHook(); permissionHook = new VaultPermissionHook(plugin);
} }
permissionHook.setPlugin(plugin);
permissionHook.setServer(plugin.getConfiguration().getVaultServer());
permissionHook.setIncludeGlobal(plugin.getConfiguration().isVaultIncludingGlobal());
permissionHook.setIgnoreWorld(plugin.getConfiguration().isVaultIgnoreWorld());
permissionHook.setPgo(plugin.getConfiguration().isVaultPrimaryGroupOverrides());
permissionHook.setPgoCheckInherited(plugin.getConfiguration().isVaultPrimaryGroupOverridesCheckInherited());
permissionHook.setPgoCheckExists(plugin.getConfiguration().isVaultPrimaryGroupOverridesCheckExists());
permissionHook.setPgoCheckMemberOf(plugin.getConfiguration().isVaultPrimaryGroupOverridesCheckMemberOf());
permissionHook.setup();
if (chatHook == null) { if (chatHook == null) {
chatHook = new VaultChatHook(permissionHook); chatHook = new VaultChatHook(permissionHook);
@ -69,9 +63,12 @@ public class VaultHook {
final ServicesManager sm = plugin.getServer().getServicesManager(); final ServicesManager sm = plugin.getServer().getServicesManager();
if (permissionHook != null) { if (permissionHook != null) {
sm.unregister(Permission.class, permissionHook); sm.unregister(Permission.class, permissionHook);
permissionHook.getScheduler().cancelTask();
permissionHook = null;
} }
if (chatHook != null) { if (chatHook != null) {
sm.unregister(Chat.class, chatHook); sm.unregister(Chat.class, chatHook);
chatHook = null;
} }
} }

View File

@ -22,10 +22,8 @@
package me.lucko.luckperms.bukkit.vault; package me.lucko.luckperms.bukkit.vault;
import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import lombok.Setter;
import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.LocalizedNode; import me.lucko.luckperms.api.LocalizedNode;
@ -44,31 +42,42 @@ import net.milkbowl.vault.permission.Permission;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
/** /**
* The LuckPerms Vault Permission implementation * The LuckPerms Vault Permission implementation
* Most lookups are cached. * Most lookups are cached.
*/ */
@Getter @Getter
@Setter
public class VaultPermissionHook extends Permission { public class VaultPermissionHook extends Permission {
private LPBukkitPlugin plugin; private LPBukkitPlugin plugin;
@Setter(value = AccessLevel.NONE)
private VaultScheduler scheduler; private VaultScheduler scheduler;
private final String name = "LuckPerms";
private String server = "global"; private String server = "global";
private boolean includeGlobal = true; private boolean includeGlobal = true;
private boolean ignoreWorld = false; private boolean ignoreWorld = false;
// Primary Group override settings
private boolean pgo = false; private boolean pgo = false;
private boolean pgoCheckInherited = false; private boolean pgoCheckInherited = false;
private boolean pgoCheckExists = true; private boolean pgoCheckExists = true;
private boolean pgoCheckMemberOf = true; private boolean pgoCheckMemberOf = true;
public void setup() { private Function<String, String> WORLD_CORRECTION_FUNCTION = s -> ignoreWorld ? null : s;
scheduler = new VaultScheduler(plugin);
public VaultPermissionHook(LPBukkitPlugin plugin) {
this.plugin = plugin;
this.scheduler = new VaultScheduler(plugin);
// Config options
this.server = plugin.getConfiguration().getVaultServer();
this.includeGlobal = plugin.getConfiguration().isVaultIncludingGlobal();
this.ignoreWorld = plugin.getConfiguration().isVaultIgnoreWorld();
this.pgo = plugin.getConfiguration().isVaultPrimaryGroupOverrides();
this.pgoCheckInherited = plugin.getConfiguration().isVaultPrimaryGroupOverridesCheckInherited();
this.pgoCheckExists = plugin.getConfiguration().isVaultPrimaryGroupOverridesCheckExists();
this.pgoCheckMemberOf = plugin.getConfiguration().isVaultPrimaryGroupOverridesCheckMemberOf();
} }
public void log(String s) { public void log(String s) {
@ -77,14 +86,9 @@ public class VaultPermissionHook extends Permission {
} }
} }
@Override
public String getName() {
return "LuckPerms";
}
@Override @Override
public boolean isEnabled() { public boolean isEnabled() {
return plugin.getStorage().isAcceptingLogins(); return plugin.isEnabled();
} }
@Override @Override
@ -99,16 +103,18 @@ public class VaultPermissionHook extends Permission {
* @param holder the holder to add the permission to * @param holder the holder to add the permission to
* @param permission the permission to add * @param permission the permission to add
*/ */
private void add(String world, PermissionHolder holder, String permission) { private CompletableFuture<Void> add(String world, PermissionHolder holder, String permission) {
try { return CompletableFuture.runAsync(() -> {
if (world != null && !world.equals("")) { try {
holder.setPermission(permission, true, server, world); if (world != null && !world.equals("") && !world.equalsIgnoreCase("global")) {
} else { holder.setPermission(permission, true, server, world);
holder.setPermission(permission, true, server); } else {
} holder.setPermission(permission, true, server);
}
save(holder); save(holder);
} catch (ObjectAlreadyHasException ignored) {} } catch (ObjectAlreadyHasException ignored) {}
}, scheduler);
} }
/** /**
@ -118,35 +124,37 @@ public class VaultPermissionHook extends Permission {
* @param holder the holder to remove the permission from * @param holder the holder to remove the permission from
* @param permission the permission to remove * @param permission the permission to remove
*/ */
private void remove(String world, PermissionHolder holder, String permission) { private CompletableFuture<Void> remove(String world, PermissionHolder holder, String permission) {
try { return CompletableFuture.runAsync(() -> {
if (world != null && !world.equals("")) { try {
holder.unsetPermission(permission, server, world); if (world != null && !world.equals("") && !world.equalsIgnoreCase("global")) {
} else { holder.unsetPermission(permission, server, world);
holder.unsetPermission(permission, server); } else {
} holder.unsetPermission(permission, server);
}
save(holder); save(holder);
} catch (ObjectLacksException ignored) {} } catch (ObjectLacksException ignored) {}
}, scheduler);
} }
/** /**
* Utility method for saving a user or group * Utility method to asynchronously save a user or group
* *
* @param holder the holder instance * @param holder the holder instance
*/ */
void save(PermissionHolder holder) { public void save(PermissionHolder holder) {
if (holder instanceof User) { if (holder instanceof User) {
plugin.getStorage().saveUser(((User) holder)) User u = (User) holder;
.thenRunAsync(() -> ((User) holder).getRefreshBuffer().request(), plugin.getAsyncExecutor()); plugin.getStorage().saveUser(u).thenRunAsync(() -> u.getRefreshBuffer().request(), plugin.getAsyncExecutor());
} }
if (holder instanceof Group) { if (holder instanceof Group) {
plugin.getStorage().saveGroup(((Group) holder)) Group g = (Group) holder;
.thenRunAsync(() -> plugin.getUpdateTaskBuffer().request(), plugin.getAsyncExecutor()); plugin.getStorage().saveGroup(g).thenRunAsync(() -> plugin.getUpdateTaskBuffer().request(), plugin.getAsyncExecutor());
} }
} }
Contexts createContext(String server, String world) { public Contexts createContextForWorld(String world) {
Map<String, String> context = new HashMap<>(); Map<String, String> context = new HashMap<>();
if (world != null && !world.equals("")) { if (world != null && !world.equals("")) {
context.put("world", world); context.put("world", world);
@ -157,7 +165,7 @@ public class VaultPermissionHook extends Permission {
@Override @Override
public boolean playerHas(String world, @NonNull String player, @NonNull String permission) { public boolean playerHas(String world, @NonNull String player, @NonNull String permission) {
world = ignoreWorld ? null : world; // Correct world value world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Checking if player " + player + " has permission: " + permission + " on world " + world + ", server " + server); log("Checking if player " + player + " has permission: " + permission + " on world " + world + ", server " + server);
User user = plugin.getUserManager().getByUsername(player); User user = plugin.getUserManager().getByUsername(player);
@ -168,91 +176,91 @@ public class VaultPermissionHook extends Permission {
} }
// Effectively fallback to the standard Bukkit #hasPermission check. // Effectively fallback to the standard Bukkit #hasPermission check.
return user.getUserData().getPermissionData(createContext(server, world)).getPermissionValue(permission).asBoolean(); return user.getUserData().getPermissionData(createContextForWorld(world)).getPermissionValue(permission).asBoolean();
} }
@Override @Override
public boolean playerAdd(String world, @NonNull String player, @NonNull String permission) { public boolean playerAdd(String world, @NonNull String player, @NonNull String permission) {
String finalWorld = ignoreWorld ? null : world; // Correct world value world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Adding permission to player " + player + ": '" + permission + "' on world " + finalWorld + ", server " + server); log("Adding permission to player " + player + ": '" + permission + "' on world " + world + ", server " + server);
final User user = plugin.getUserManager().getByUsername(player); final User user = plugin.getUserManager().getByUsername(player);
if (user == null) return false; if (user == null) return false;
scheduler.scheduleTask(() -> add(finalWorld, user, permission)); add(world, user, permission);
return true; return true;
} }
@Override @Override
public boolean playerRemove(String world, @NonNull String player, @NonNull String permission) { public boolean playerRemove(String world, @NonNull String player, @NonNull String permission) {
String finalWorld = ignoreWorld ? null : world; // Correct world value world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Removing permission from player " + player + ": '" + permission + "' on world " + finalWorld + ", server " + server); log("Removing permission from player " + player + ": '" + permission + "' on world " + world + ", server " + server);
final User user = plugin.getUserManager().getByUsername(player); final User user = plugin.getUserManager().getByUsername(player);
if (user == null) return false; if (user == null) return false;
scheduler.scheduleTask(() -> remove(finalWorld, user, permission)); remove(world, user, permission);
return true; return true;
} }
@Override @Override
public boolean groupHas(String world, @NonNull String groupName, @NonNull String permission) { public boolean groupHas(String world, @NonNull String groupName, @NonNull String permission) {
world = ignoreWorld ? null : world; // Correct world value world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Checking if group " + groupName + " has permission: " + permission + " on world " + world + ", server " + server); log("Checking if group " + groupName + " has permission: " + permission + " on world " + world + ", server " + server);
final Group group = plugin.getGroupManager().getIfLoaded(groupName); final Group group = plugin.getGroupManager().getIfLoaded(groupName);
if (group == null) return false; if (group == null) return false;
// This is a nasty call. Groups aren't cached. :( // This is a nasty call. Groups aren't cached. :(
Map<String, Boolean> permissions = group.exportNodes(createContext(server, world), true); Map<String, Boolean> permissions = group.exportNodes(createContextForWorld(world), true);
return permissions.containsKey(permission.toLowerCase()) && permissions.get(permission.toLowerCase());
return permissions.containsKey(permission) && permissions.get(permission);
} }
@Override @Override
public boolean groupAdd(String world, @NonNull String groupName, @NonNull String permission) { public boolean groupAdd(String world, @NonNull String groupName, @NonNull String permission) {
String finalWorld = ignoreWorld ? null : world; // Correct world value world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Adding permission to group " + groupName + ": '" + permission + "' on world " + finalWorld + ", server " + server); log("Adding permission to group " + groupName + ": '" + permission + "' on world " + world + ", server " + server);
final Group group = plugin.getGroupManager().getIfLoaded(groupName); final Group group = plugin.getGroupManager().getIfLoaded(groupName);
if (group == null) return false; if (group == null) return false;
scheduler.scheduleTask(() -> add(finalWorld, group, permission)); add(world, group, permission);
return true; return true;
} }
@Override @Override
public boolean groupRemove(String world, @NonNull String groupName, @NonNull String permission) { public boolean groupRemove(String world, @NonNull String groupName, @NonNull String permission) {
String finalWorld = ignoreWorld ? null : world; // Correct world value world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Removing permission from group " + groupName + ": '" + permission + "' on world " + finalWorld + ", server " + server); log("Removing permission from group " + groupName + ": '" + permission + "' on world " + world + ", server " + server);
final Group group = plugin.getGroupManager().getIfLoaded(groupName); final Group group = plugin.getGroupManager().getIfLoaded(groupName);
if (group == null) return false; if (group == null) return false;
scheduler.scheduleTask(() -> remove(finalWorld, group, permission)); remove(world, group, permission);
return true; return true;
} }
@Override @Override
public boolean playerInGroup(String world, @NonNull String player, @NonNull String group) { public boolean playerInGroup(String world, @NonNull String player, @NonNull String group) {
String finalWorld = ignoreWorld ? null : world; // Correct world value world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Checking if player " + player + " is in group: " + group + " on world " + finalWorld + ", server " + server); log("Checking if player " + player + " is in group: " + group + " on world " + world + ", server " + server);
final User user = plugin.getUserManager().getByUsername(player); final User user = plugin.getUserManager().getByUsername(player);
if (user == null) return false; if (user == null) return false;
String w = world; // screw effectively final
return user.getNodes().stream() return user.getNodes().stream()
.filter(Node::isGroupNode) .filter(Node::isGroupNode)
.filter(n -> n.shouldApplyOnServer(server, isIncludeGlobal(), false)) .filter(n -> n.shouldApplyOnServer(server, isIncludeGlobal(), false))
.filter(n -> n.shouldApplyOnWorld(finalWorld, true, false)) .filter(n -> n.shouldApplyOnWorld(w, true, false))
.map(Node::getGroupName) .map(Node::getGroupName)
.anyMatch(s -> s.equalsIgnoreCase(group)); .anyMatch(s -> s.equalsIgnoreCase(group));
} }
@Override @Override
public boolean playerAddGroup(String world, @NonNull String player, @NonNull String groupName) { public boolean playerAddGroup(String world, @NonNull String player, @NonNull String groupName) {
String finalWorld = ignoreWorld ? null : world; // Correct world value world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Adding player " + player + " to group: '" + groupName + "' on world " + finalWorld + ", server " + server); log("Adding player " + player + " to group: '" + groupName + "' on world " + world + ", server " + server);
final User user = plugin.getUserManager().getByUsername(player); final User user = plugin.getUserManager().getByUsername(player);
if (user == null) return false; if (user == null) return false;
@ -260,10 +268,11 @@ public class VaultPermissionHook extends Permission {
final Group group = plugin.getGroupManager().getIfLoaded(groupName); final Group group = plugin.getGroupManager().getIfLoaded(groupName);
if (group == null) return false; if (group == null) return false;
scheduler.scheduleTask(() -> { String w = world;
scheduler.execute(() -> {
try { try {
if (finalWorld != null && !finalWorld.equals("")) { if (w != null && !w.equals("") && !w.equalsIgnoreCase("global")) {
user.setInheritGroup(group, server, finalWorld); user.setInheritGroup(group, server, w);
} else { } else {
user.setInheritGroup(group, server); user.setInheritGroup(group, server);
} }
@ -276,8 +285,8 @@ public class VaultPermissionHook extends Permission {
@Override @Override
public boolean playerRemoveGroup(String world, @NonNull String player, @NonNull String groupName) { public boolean playerRemoveGroup(String world, @NonNull String player, @NonNull String groupName) {
String finalWorld = ignoreWorld ? null : world; // Correct world value world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Removing player " + player + " from group: '" + groupName + "' on world " + finalWorld + ", server " + server); log("Removing player " + player + " from group: '" + groupName + "' on world " + world + ", server " + server);
final User user = plugin.getUserManager().getByUsername(player); final User user = plugin.getUserManager().getByUsername(player);
if (user == null) return false; if (user == null) return false;
@ -285,10 +294,11 @@ public class VaultPermissionHook extends Permission {
final Group group = plugin.getGroupManager().getIfLoaded(groupName); final Group group = plugin.getGroupManager().getIfLoaded(groupName);
if (group == null) return false; if (group == null) return false;
scheduler.scheduleTask(() -> { String w = world;
scheduler.execute(() -> {
try { try {
if (finalWorld != null && !finalWorld.equals("")) { if (w != null && !w.equals("") && !w.equalsIgnoreCase("global")) {
user.unsetInheritGroup(group, server, finalWorld); user.unsetInheritGroup(group, server, w);
} else { } else {
user.unsetInheritGroup(group, server); user.unsetInheritGroup(group, server);
} }
@ -301,23 +311,24 @@ public class VaultPermissionHook extends Permission {
@Override @Override
public String[] getPlayerGroups(String world, @NonNull String player) { public String[] getPlayerGroups(String world, @NonNull String player) {
String finalWorld = ignoreWorld ? null : world; // Correct world value world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Getting groups of player: " + player + ", on world " + finalWorld + ", server " + server); log("Getting groups of player: " + player + ", on world " + world + ", server " + server);
User user = plugin.getUserManager().getByUsername(player); User user = plugin.getUserManager().getByUsername(player);
if (user == null) return new String[0]; if (user == null) return new String[0];
String w = world; // screw effectively final
return user.getNodes().stream() return user.getNodes().stream()
.filter(Node::isGroupNode) .filter(Node::isGroupNode)
.filter(n -> n.shouldApplyOnServer(server, isIncludeGlobal(), false)) .filter(n -> n.shouldApplyOnServer(server, isIncludeGlobal(), false))
.filter(n -> n.shouldApplyOnWorld(finalWorld, true, false)) .filter(n -> n.shouldApplyOnWorld(w, true, false))
.map(Node::getGroupName) .map(Node::getGroupName)
.toArray(String[]::new); .toArray(String[]::new);
} }
@Override @Override
public String getPrimaryGroup(String world, @NonNull String player) { public String getPrimaryGroup(String world, @NonNull String player) {
world = ignoreWorld ? null : world; // Correct world value world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Getting primary group of player: " + player); log("Getting primary group of player: " + player);
final User user = plugin.getUserManager().getByUsername(player); final User user = plugin.getUserManager().getByUsername(player);
@ -331,7 +342,7 @@ public class VaultPermissionHook extends Permission {
} }
if (pgoCheckInherited) { if (pgoCheckInherited) {
PermissionData data = user.getUserData().getPermissionData(createContext(server, world)); PermissionData data = user.getUserData().getPermissionData(createContextForWorld(world));
for (Map.Entry<String, Boolean> e : data.getImmutableBacking().entrySet()) { for (Map.Entry<String, Boolean> e : data.getImmutableBacking().entrySet()) {
if (!e.getValue()) { if (!e.getValue()) {
continue; continue;

View File

@ -24,17 +24,26 @@ package me.lucko.luckperms.bukkit.vault;
import me.lucko.luckperms.bukkit.LPBukkitPlugin; import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import org.bukkit.scheduler.BukkitTask;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor;
public class VaultScheduler implements Runnable { /**
* Sequential executor for Vault modifications
*/
public class VaultScheduler implements Runnable, Executor {
private BukkitTask task = null;
private final List<Runnable> tasks = new ArrayList<>(); private final List<Runnable> tasks = new ArrayList<>();
public VaultScheduler(LPBukkitPlugin plugin) { public VaultScheduler(LPBukkitPlugin plugin) {
plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, this, 1L, 1L); task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, this, 1L, 1L);
} }
public void scheduleTask(Runnable r) { @Override
public void execute(Runnable r) {
synchronized (tasks) { synchronized (tasks) {
tasks.add(r); tasks.add(r);
} }
@ -42,12 +51,24 @@ public class VaultScheduler implements Runnable {
@Override @Override
public void run() { public void run() {
List<Runnable> toRun = new ArrayList<>(); List<Runnable> toRun;
synchronized (tasks) { synchronized (tasks) {
if (tasks.isEmpty()) {
return;
}
toRun = new ArrayList<>();
toRun.addAll(tasks); toRun.addAll(tasks);
tasks.clear(); tasks.clear();
} }
toRun.forEach(Runnable::run); toRun.forEach(Runnable::run);
} }
public void cancelTask() {
if (task != null) {
task.cancel();
task = null;
}
}
} }