From 82789328c1b6d18920d801a6f0062d980a665c73 Mon Sep 17 00:00:00 2001 From: Luck Date: Tue, 4 Oct 2016 14:57:00 +0100 Subject: [PATCH] Pre-process permissions and apply immediately on login events --- .../me/lucko/luckperms/BukkitListener.java | 77 ++++++++++++++++--- .../api/vault/cache/ContextCache.java | 2 +- .../me/lucko/luckperms/inject/Injector.java | 2 +- .../me/lucko/luckperms/users/BukkitUser.java | 8 ++ .../storage/methods/FlatfileDatastore.java | 6 +- .../luckperms/utils/AbstractListener.java | 4 +- 6 files changed, 83 insertions(+), 16 deletions(-) diff --git a/bukkit/src/main/java/me/lucko/luckperms/BukkitListener.java b/bukkit/src/main/java/me/lucko/luckperms/BukkitListener.java index 18b7957e..34135ae7 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/BukkitListener.java +++ b/bukkit/src/main/java/me/lucko/luckperms/BukkitListener.java @@ -23,6 +23,7 @@ package me.lucko.luckperms; import me.lucko.luckperms.constants.Message; +import me.lucko.luckperms.contexts.Contexts; import me.lucko.luckperms.inject.Injector; import me.lucko.luckperms.inject.LPPermissible; import me.lucko.luckperms.users.BukkitUser; @@ -34,6 +35,8 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.player.*; +import java.util.Collections; +import java.util.Map; import java.util.UUID; class BukkitListener extends AbstractListener implements Listener { @@ -52,7 +55,41 @@ class BukkitListener extends AbstractListener implements Listener { return; } + // Process login onAsyncLogin(e.getUniqueId(), e.getName()); + + // Pre-process the user's permissions, so they're ready for PLE. + BukkitUser user = (BukkitUser) plugin.getUserManager().get(plugin.getUuidCache().getUUID(e.getUniqueId())); + Map toApply = user.exportNodes( + new Contexts( + Collections.singletonMap("server", plugin.getConfiguration().getServer()), + plugin.getConfiguration().isIncludingGlobalPerms(), + plugin.getConfiguration().isIncludingGlobalWorldPerms(), + true, + plugin.getConfiguration().isApplyingGlobalGroups(), + plugin.getConfiguration().isApplyingGlobalWorldGroups() + ), + Collections.emptyList(), + true + ); + user.setLoginPreProcess(toApply); + + // Hook with Vault early + if (plugin.getVaultHook() != null && plugin.getVaultHook().isHooked()) { + plugin.getVaultHook().getPermissionHook().getVaultUserManager().setupUser(user); + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerPreLoginMonitor(AsyncPlayerPreLoginEvent e) { + if (plugin.getDatastore().isAcceptingLogins() && e.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { + // Login event was cancelled by another plugin + final UUID internal = plugin.getUuidCache().getUUID(e.getUniqueId()); + onLeave(e.getUniqueId()); + if (plugin.getVaultHook() != null && plugin.getVaultHook().isHooked()) { + plugin.getVaultHook().getPermissionHook().getVaultUserManager().clearUser(internal); + } + } } @EventHandler(priority = EventPriority.LOWEST) @@ -65,19 +102,39 @@ class BukkitListener extends AbstractListener implements Listener { return; } - if (user instanceof BukkitUser) { - BukkitUser u = (BukkitUser) user; + BukkitUser u = (BukkitUser) user; + try { + // Make a new permissible for the user + LPPermissible lpPermissible = new LPPermissible(player, plugin, plugin.getDefaultsProvider()); - try { - LPPermissible lpPermissible = new LPPermissible(player, plugin, plugin.getDefaultsProvider()); - Injector.inject(player, lpPermissible); - u.setLpPermissible(lpPermissible); - } catch (Throwable t) { - t.printStackTrace(); - } + // Insert the pre-processed permissions into the permissible + lpPermissible.getLuckPermsPermissions().putAll(u.getLoginPreProcess()); + u.setLoginPreProcess(null); + + // Inject into the player + Injector.inject(player, lpPermissible); + u.setLpPermissible(lpPermissible); + + } catch (Throwable t) { + t.printStackTrace(); } + } - plugin.doAsync(user::refreshPermissions); + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerLoginMonitor(PlayerLoginEvent e) { + if (e.getResult() != PlayerLoginEvent.Result.ALLOWED) { + // The player got denied on sync login. + final UUID internal = plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()); + onLeave(e.getPlayer().getUniqueId()); + if (plugin.getVaultHook() != null && plugin.getVaultHook().isHooked()) { + plugin.getVaultHook().getPermissionHook().getVaultUserManager().clearUser(internal); + } + } else { + User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId())); + + // Call another update to calculate full context. (incl. per world permissions) + plugin.doAsync(user::refreshPermissions); + } } @EventHandler(priority = EventPriority.LOWEST) diff --git a/bukkit/src/main/java/me/lucko/luckperms/api/vault/cache/ContextCache.java b/bukkit/src/main/java/me/lucko/luckperms/api/vault/cache/ContextCache.java index c93d97e6..54cf7a49 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/api/vault/cache/ContextCache.java +++ b/bukkit/src/main/java/me/lucko/luckperms/api/vault/cache/ContextCache.java @@ -57,7 +57,7 @@ public class ContextCache { processors.add(new RegexProcessor(permissionCache)); } - processors.add(new DefaultsProcessor(() -> ((BukkitUser) user).getLpPermissible().isOp(), defaultsProvider)); + processors.add(new DefaultsProcessor(((BukkitUser) user)::isOp, defaultsProvider)); calculator = new PermissionCalculator(plugin, user.getName(), plugin.getConfiguration().isDebugPermissionChecks(), processors); } diff --git a/bukkit/src/main/java/me/lucko/luckperms/inject/Injector.java b/bukkit/src/main/java/me/lucko/luckperms/inject/Injector.java index fbfae7df..d47fc388 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/inject/Injector.java +++ b/bukkit/src/main/java/me/lucko/luckperms/inject/Injector.java @@ -62,7 +62,7 @@ public class Injector { try { Permissible permissible = getPermissible(sender); if (permissible instanceof LPPermissible) { - getPermField(sender).set(sender, new PermissibleBase(sender)); + getPermField(sender).set(sender, null); } return true; } catch (Exception e) { diff --git a/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUser.java b/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUser.java index 1b1b0d66..91f9f5e7 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUser.java +++ b/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUser.java @@ -44,6 +44,10 @@ public class BukkitUser extends User { @Setter private LPPermissible lpPermissible = null; + @Getter + @Setter + private Map loginPreProcess = null; + BukkitUser(UUID uuid, LPBukkitPlugin plugin) { super(uuid, plugin); this.plugin = plugin; @@ -54,6 +58,10 @@ public class BukkitUser extends User { this.plugin = plugin; } + public boolean isOp() { + return lpPermissible != null && lpPermissible.isOp(); + } + @SuppressWarnings("unchecked") @Override public synchronized void refreshPermissions() { diff --git a/common/src/main/java/me/lucko/luckperms/storage/methods/FlatfileDatastore.java b/common/src/main/java/me/lucko/luckperms/storage/methods/FlatfileDatastore.java index 07a38355..eb196867 100644 --- a/common/src/main/java/me/lucko/luckperms/storage/methods/FlatfileDatastore.java +++ b/common/src/main/java/me/lucko/luckperms/storage/methods/FlatfileDatastore.java @@ -41,12 +41,12 @@ abstract class FlatfileDatastore extends Datastore { private final Logger actionLogger = Logger.getLogger("lp_actions"); private Map uuidCache = new ConcurrentHashMap<>(); - final File pluginDir; + private final File pluginDir; + private File uuidData; + private File actionLog; File usersDir; File groupsDir; File tracksDir; - File uuidData; - File actionLog; FlatfileDatastore(LuckPermsPlugin plugin, String name, File pluginDir) { super(plugin, name); diff --git a/common/src/main/java/me/lucko/luckperms/utils/AbstractListener.java b/common/src/main/java/me/lucko/luckperms/utils/AbstractListener.java index fb22dc19..d9cafa41 100644 --- a/common/src/main/java/me/lucko/luckperms/utils/AbstractListener.java +++ b/common/src/main/java/me/lucko/luckperms/utils/AbstractListener.java @@ -70,7 +70,9 @@ public class AbstractListener { final UuidCache cache = plugin.getUuidCache(); final User user = plugin.getUserManager().get(cache.getUUID(uuid)); - plugin.getUserManager().unload(user); + if (user != null) { + plugin.getUserManager().unload(user); + } // Unload the user from memory when they disconnect; cache.clearCache(uuid);