Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1230,19 +1230,23 @@ private final class PickupListenerPre1_12 implements Listener {
public void onPlayerPickupItem(final org.bukkit.event.player.PlayerPickupItemEvent event) {
if (event.getItem().hasMetadata(Commandfireball.FIREBALL_META_KEY)) {
event.setCancelled(true);
} else if (ess.getSettings().getDisableItemPickupWhileAfk()) {
if (ess.getUser(event.getPlayer()).isAfk()) {
event.setCancelled(true);
}
return;
}
final User user = ess.getUser(event.getPlayer());
if ((ess.getSettings().getDisableItemPickupWhileAfk() && user.isAfk())
|| (user.isVanished() && !user.isAuthorizedCached("essentials.vanish.pickup"))) {
event.setCancelled(true);
}
}
}

private final class PickupListener1_12 implements Listener {
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerPickupItem(final org.bukkit.event.entity.EntityPickupItemEvent event) {
if (ess.getSettings().getDisableItemPickupWhileAfk() && event.getEntity() instanceof Player) {
if (ess.getUser((Player) event.getEntity()).isAfk()) {
if (event.getEntity() instanceof Player) {
final User user = ess.getUser((Player) event.getEntity());
if ((ess.getSettings().getDisableItemPickupWhileAfk() && user.isAfk())
|| (user.isVanished() && !user.isAuthorizedCached("essentials.vanish.pickup"))) {
event.setCancelled(true);
}
}
Expand All @@ -1261,6 +1265,10 @@ public void onGameEvent(final org.bukkit.event.block.BlockReceiveGameEvent event
private final class CommandSendFilter implements CommandSendListenerProvider.Filter {
@Override
public Predicate<String> apply(Player player) {
// There is no event for op status changes, but the command list is resent when
// a player is opped/deopped, so we invalidate cached permissions here.
ess.getPermissionsHandler().invalidatePermissionCache(player.getUniqueId());

final User user = ess.getUser(player);
final Set<PluginCommand> checked = new HashSet<>();
final Set<PluginCommand> toRemove = new HashSet<>();
Expand Down
2 changes: 2 additions & 0 deletions Essentials/src/main/java/com/earth2me/essentials/IUser.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
public interface IUser {
boolean isAuthorized(String node);

boolean isAuthorizedCached(String node);

boolean isAuthorized(IEssentialsCommand cmd);

boolean isAuthorized(IEssentialsCommand cmd, String permissionPrefix);
Expand Down
33 changes: 32 additions & 1 deletion Essentials/src/main/java/com/earth2me/essentials/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,19 @@ public boolean isAuthorized(final String node) {
return result;
}

@Override
public boolean isAuthorizedCached(final String node) {
if (Essentials.TESTING) {
return false;
}

final boolean result = isAuthorizedCachedCheck(node);
if (ess.getSettings().isDebug()) {
ess.getLogger().log(Level.INFO, "checking if " + base.getName() + " has " + node + " (cached) - " + result);
}
return result;
}

@Override
public boolean isPermissionSet(final String node) {
if (Essentials.TESTING) {
Expand Down Expand Up @@ -186,6 +199,24 @@ private boolean isAuthorizedCheck(final String node) {
}
}

private boolean isAuthorizedCachedCheck(final String node) {
if (base instanceof OfflinePlayerStub) {
return false;
}

try {
return ess.getPermissionsHandler().hasPermissionCached(base, node);
} catch (final Exception ex) {
if (ess.getSettings().isDebug()) {
ess.getLogger().log(Level.SEVERE, "Permission System Error: " + ess.getPermissionsHandler().getName() + " returned: " + ex.getMessage(), ex);
} else {
ess.getLogger().log(Level.SEVERE, "Permission System Error: " + ess.getPermissionsHandler().getName() + " returned: " + ex.getMessage());
}

return false;
}
}

private boolean isPermSetCheck(final String node) {
if (base instanceof OfflinePlayerStub) {
return false;
Expand Down Expand Up @@ -872,7 +903,7 @@ public void checkActivity() {
}
}
final long autoafk = ess.getSettings().getAutoAfk();
if (!isAfk() && autoafk > 0 && lastActivity + autoafk * 1000 < System.currentTimeMillis() && isAuthorized("essentials.afk.auto")) {
if (!isAfk() && autoafk > 0 && lastActivity + autoafk * 1000 < System.currentTimeMillis() && isAuthorizedCached("essentials.afk.auto")) {
setAfk(true, AfkStatusChangeEvent.Cause.ACTIVITY);
if (isAfk() && !isHidden()) {
setDisplayNick();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ public interface IPermissionsHandler {

boolean hasPermission(Player base, String node);

default boolean hasPermissionCached(Player base, String node) {
return hasPermission(base, node);
}

default void invalidatePermissionCache(UUID uuid) {
}

// Does not check for * permissions
boolean isPermissionSet(Player base, String node);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,16 @@ public boolean hasPermission(final Player base, final String node) {
return handler.hasPermission(base, node);
}

@Override
public boolean hasPermissionCached(final Player base, final String node) {
return handler.hasPermissionCached(base, node);
}

@Override
public void invalidatePermissionCache(final UUID uuid) {
handler.invalidatePermissionCache(uuid);
}

@Override
public boolean isPermissionSet(final Player base, final String node) {
return handler.isPermissionSet(base, node);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,31 @@
import net.luckperms.api.context.ContextConsumer;
import net.luckperms.api.context.ContextSet;
import net.luckperms.api.context.ImmutableContextSet;
import net.luckperms.api.event.EventSubscription;
import net.luckperms.api.event.user.UserDataRecalculateEvent;
import net.luckperms.api.model.group.Group;
import net.luckperms.api.query.QueryOptions;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider;

import java.util.logging.Level;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Supplier;

public class LuckPermsHandler extends ModernVaultHandler {
private LuckPerms luckPerms;
private Essentials ess;
private CombinedCalculator calculator;
private final Map<UUID, Map<String, Boolean>> permissionCache = new ConcurrentHashMap<>();
private EventSubscription<UserDataRecalculateEvent> recalculateSubscription;

@Override
public void registerContext(final String context, final Function<User, Iterable<String>> calculator, final Supplier<Iterable<String>> suggestions) {
Expand All @@ -41,6 +48,30 @@ public void unregisterContexts() {
this.luckPerms.getContextManager().unregisterCalculator(this.calculator);
this.calculator = null;
}
if (this.recalculateSubscription != null) {
this.recalculateSubscription.close();
this.recalculateSubscription = null;
}
this.permissionCache.clear();
}

@Override
public boolean hasPermissionCached(final Player base, final String node) {
final UUID uuid = base.getUniqueId();
final Map<String, Boolean> userCache = permissionCache.computeIfAbsent(uuid, k -> new ConcurrentHashMap<>());
return userCache.computeIfAbsent(node, k -> hasPermission(base, node));
}

@Override
public void invalidatePermissionCache(final UUID uuid) {
invalidateCache(uuid);
}

public void invalidateCache(final UUID uuid) {
if (ess.getSettings().isDebug()) {
ess.getLogger().log(Level.INFO, "Invalidating permission cache for " + uuid);
}
permissionCache.remove(uuid);
}

@Override
Expand Down Expand Up @@ -77,6 +108,11 @@ public boolean tryProvider(Essentials ess) {
if (provider != null) {
this.luckPerms = provider.getProvider();
this.ess = ess;
this.recalculateSubscription = this.luckPerms.getEventBus().subscribe(
ess,
UserDataRecalculateEvent.class,
event -> invalidateCache(event.getUser().getUniqueId())
);
}
return luckPerms != null && super.tryProvider(ess);
}
Expand Down
3 changes: 3 additions & 0 deletions Essentials/src/main/resources/plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1374,6 +1374,9 @@ permissions:
description: Applies invisibility effects to the player when they are in vanish mode
essentials.vanish.interact:
description: Allows the bearer to interact with players in vanish mode
essentials.vanish.pickup:
description: Allows the bearer to pick up items while in vanish mode
default: false
essentials.version:
description: Allows access to the /version command
essentials.warp:
Expand Down
Loading