Pre-process permissions and apply immediately on login events

This commit is contained in:
Luck 2016-10-04 14:57:00 +01:00
parent 13bccd1d3f
commit 82789328c1
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
6 changed files with 83 additions and 16 deletions

View File

@ -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<String, Boolean> 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)

View File

@ -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);
}

View File

@ -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) {

View File

@ -44,6 +44,10 @@ public class BukkitUser extends User {
@Setter
private LPPermissible lpPermissible = null;
@Getter
@Setter
private Map<String, Boolean> 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() {

View File

@ -41,12 +41,12 @@ abstract class FlatfileDatastore extends Datastore {
private final Logger actionLogger = Logger.getLogger("lp_actions");
private Map<String, String> 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);

View File

@ -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);