mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-24 11:38:40 +01:00
Apply PermissionAttachment permissions at a higher priority than normal nodes using the transient system (#515)
This commit is contained in:
parent
1baefaade4
commit
f109cb684a
@ -173,7 +173,7 @@ public class BukkitListener implements Listener {
|
|||||||
t.printStackTrace();
|
t.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.refreshAutoOp(player);
|
plugin.refreshAutoOp(user, player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR)
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
@ -201,7 +201,7 @@ public class BukkitListener implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// everything is going well. login was processed ok, this is just to refresh auto-op status.
|
// everything is going well. login was processed ok, this is just to refresh auto-op status.
|
||||||
plugin.refreshAutoOp(e.getPlayer());
|
plugin.refreshAutoOp(plugin.getUserManager().getIfLoaded(e.getPlayer().getUniqueId()), e.getPlayer());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait until the last priority to unload, so plugins can still perform permission checks on this event
|
// Wait until the last priority to unload, so plugins can still perform permission checks on this event
|
||||||
@ -252,6 +252,6 @@ public class BukkitListener implements Listener {
|
|||||||
@EventHandler(priority = EventPriority.LOWEST)
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
public void onWorldChange(PlayerChangedWorldEvent e) {
|
public void onWorldChange(PlayerChangedWorldEvent e) {
|
||||||
plugin.getContextManager().invalidateCache(e.getPlayer());
|
plugin.getContextManager().invalidateCache(e.getPlayer());
|
||||||
plugin.refreshAutoOp(e.getPlayer());
|
plugin.refreshAutoOp(plugin.getUserManager().getIfLoaded(e.getPlayer().getUniqueId()), e.getPlayer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,23 +402,15 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshAutoOp(Player player) {
|
public void refreshAutoOp(User user, Player player) {
|
||||||
if (getConfiguration().get(ConfigKeys.AUTO_OP)) {
|
|
||||||
try {
|
|
||||||
LPPermissible permissible = Injector.getPermissible(player.getUniqueId());
|
|
||||||
if (permissible == null || !permissible.getActive().get()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
User user = permissible.getUser();
|
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Boolean> backing = user.getUserData().getPermissionData(permissible.calculateContexts()).getImmutableBacking();
|
if (getConfiguration().get(ConfigKeys.AUTO_OP)) {
|
||||||
|
Map<String, Boolean> backing = user.getUserData().getPermissionData(contextManager.getApplicableContexts(player)).getImmutableBacking();
|
||||||
boolean op = Optional.ofNullable(backing.get("luckperms.autoop")).orElse(false);
|
boolean op = Optional.ofNullable(backing.get("luckperms.autoop")).orElse(false);
|
||||||
player.setOp(op);
|
player.setOp(op);
|
||||||
} catch (Exception ignored) {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,9 +31,6 @@ import com.google.common.collect.ImmutableList;
|
|||||||
|
|
||||||
import me.lucko.luckperms.api.Contexts;
|
import me.lucko.luckperms.api.Contexts;
|
||||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||||
import me.lucko.luckperms.bukkit.model.Injector;
|
|
||||||
import me.lucko.luckperms.bukkit.model.LPPermissible;
|
|
||||||
import me.lucko.luckperms.bukkit.processors.AttachmentProcessor;
|
|
||||||
import me.lucko.luckperms.bukkit.processors.ChildProcessor;
|
import me.lucko.luckperms.bukkit.processors.ChildProcessor;
|
||||||
import me.lucko.luckperms.bukkit.processors.DefaultsProcessor;
|
import me.lucko.luckperms.bukkit.processors.DefaultsProcessor;
|
||||||
import me.lucko.luckperms.common.calculators.AbstractCalculatorFactory;
|
import me.lucko.luckperms.common.calculators.AbstractCalculatorFactory;
|
||||||
@ -47,7 +44,6 @@ import me.lucko.luckperms.common.processors.RegexProcessor;
|
|||||||
import me.lucko.luckperms.common.processors.WildcardProcessor;
|
import me.lucko.luckperms.common.processors.WildcardProcessor;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class BukkitCalculatorFactory extends AbstractCalculatorFactory {
|
public class BukkitCalculatorFactory extends AbstractCalculatorFactory {
|
||||||
@ -63,14 +59,6 @@ public class BukkitCalculatorFactory extends AbstractCalculatorFactory {
|
|||||||
processors.add(new ChildProcessor(plugin.getChildPermissionProvider()));
|
processors.add(new ChildProcessor(plugin.getChildPermissionProvider()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plugin.getConfiguration().get(ConfigKeys.APPLY_BUKKIT_ATTACHMENT_PERMISSIONS)) {
|
|
||||||
final UUID uuid = plugin.getUuidCache().getExternalUUID(user.getUuid());
|
|
||||||
processors.add(new AttachmentProcessor(() -> {
|
|
||||||
LPPermissible permissible = Injector.getPermissible(uuid);
|
|
||||||
return permissible == null ? null : permissible.getAttachmentPermissions();
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (plugin.getConfiguration().get(ConfigKeys.APPLYING_REGEX)) {
|
if (plugin.getConfiguration().get(ConfigKeys.APPLYING_REGEX)) {
|
||||||
processors.add(new RegexProcessor());
|
processors.add(new RegexProcessor());
|
||||||
}
|
}
|
||||||
|
@ -45,63 +45,17 @@ public class DummyPermissible implements Permissible {
|
|||||||
onRefresh.run();
|
onRefresh.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override public Set<PermissionAttachmentInfo> getEffectivePermissions() { return Collections.emptySet(); }
|
||||||
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
|
@Override public boolean isPermissionSet(String name) { return false; }
|
||||||
return Collections.emptySet();
|
@Override public boolean isPermissionSet(Permission perm) { return false; }
|
||||||
}
|
@Override public boolean hasPermission(String name) { return false; }
|
||||||
|
@Override public boolean hasPermission(Permission perm) { return false; }
|
||||||
@Override
|
@Override public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) { return null; }
|
||||||
public boolean isPermissionSet(String name) {
|
@Override public PermissionAttachment addAttachment(Plugin plugin) { return null; }
|
||||||
return false;
|
@Override public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) { return null; }
|
||||||
}
|
@Override public PermissionAttachment addAttachment(Plugin plugin, int ticks) { return null; }
|
||||||
|
@Override public void removeAttachment(PermissionAttachment attachment) {}
|
||||||
@Override
|
@Override public boolean isOp() { return false; }
|
||||||
public boolean isPermissionSet(Permission perm) {
|
@Override public void setOp(boolean value) {}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasPermission(String name) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasPermission(Permission perm) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PermissionAttachment addAttachment(Plugin plugin) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PermissionAttachment addAttachment(Plugin plugin, int ticks) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeAttachment(PermissionAttachment attachment) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isOp() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setOp(boolean value) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -35,77 +35,25 @@ import java.util.Collections;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class DummyPermissibleBase extends PermissibleBase {
|
public class DummyPermissibleBase extends PermissibleBase {
|
||||||
public DummyPermissibleBase() {
|
public static final DummyPermissibleBase INSTANCE = new DummyPermissibleBase();
|
||||||
|
|
||||||
|
private DummyPermissibleBase() {
|
||||||
super(null);
|
super(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override public boolean isOp() { return false; }
|
||||||
public boolean isOp() {
|
@Override public void setOp(boolean value) {}
|
||||||
return false;
|
@Override public boolean isPermissionSet(String name) { return false; }
|
||||||
}
|
@Override public boolean isPermissionSet(Permission perm) { return false; }
|
||||||
|
@Override public boolean hasPermission(String inName) { return false; }
|
||||||
@Override
|
@Override public boolean hasPermission(Permission perm) { return false; }
|
||||||
public void setOp(boolean value) {
|
@Override public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) { return null; }
|
||||||
|
@Override public PermissionAttachment addAttachment(Plugin plugin) { return null; }
|
||||||
|
@Override public void removeAttachment(PermissionAttachment attachment) {}
|
||||||
|
@Override public void recalculatePermissions() {}
|
||||||
|
@Override public void clearPermissions() {}
|
||||||
|
@Override public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) { return null; }
|
||||||
|
@Override public PermissionAttachment addAttachment(Plugin plugin, int ticks) { return null; }
|
||||||
|
@Override public Set<PermissionAttachmentInfo> getEffectivePermissions() { return Collections.emptySet(); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPermissionSet(String name) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPermissionSet(Permission perm) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasPermission(String inName) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasPermission(Permission perm) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PermissionAttachment addAttachment(Plugin plugin) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeAttachment(PermissionAttachment attachment) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void recalculatePermissions() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void clearPermissions() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PermissionAttachment addAttachment(Plugin plugin, int ticks) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
|
|
||||||
return Collections.emptySet();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* 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.bukkit.model;
|
||||||
|
|
||||||
|
import org.bukkit.Server;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.bukkit.plugin.PluginDescriptionFile;
|
||||||
|
import org.bukkit.plugin.PluginLoader;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy plugin instance
|
||||||
|
*/
|
||||||
|
public class DummyPlugin implements Plugin {
|
||||||
|
public static final DummyPlugin INSTANCE = new DummyPlugin();
|
||||||
|
|
||||||
|
private DummyPlugin() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public File getDataFolder() { return null; }
|
||||||
|
@Override public PluginDescriptionFile getDescription() { return null; }
|
||||||
|
@Override public FileConfiguration getConfig() { return null; }
|
||||||
|
@Override public InputStream getResource(String s) { return null; }
|
||||||
|
@Override public void saveConfig() {}
|
||||||
|
@Override public void saveDefaultConfig() {}
|
||||||
|
@Override public void saveResource(String s, boolean b) {}
|
||||||
|
@Override public void reloadConfig() {}
|
||||||
|
@Override public PluginLoader getPluginLoader() { return null; }
|
||||||
|
@Override public Server getServer() { return null; }
|
||||||
|
@Override public void onDisable() {}
|
||||||
|
@Override public void onLoad() {}
|
||||||
|
@Override public void onEnable() {}
|
||||||
|
@Override public boolean isNaggable() { return false; }
|
||||||
|
@Override public void setNaggable(boolean b) {}
|
||||||
|
@Override public ChunkGenerator getDefaultWorldGenerator(String s, String s1) { return null; }
|
||||||
|
@Override public Logger getLogger() { return null; }
|
||||||
|
@Override public String getName() { return null; }
|
||||||
|
@Override public boolean onCommand(CommandSender commandSender, Command command, String s, String[] strings) { return false; }
|
||||||
|
@Override public List<String> onTabComplete(CommandSender commandSender, Command command, String s, String[] strings) { return null; }
|
||||||
|
|
||||||
|
}
|
@ -116,13 +116,12 @@ public class Injector {
|
|||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
List<PermissionAttachment> attachments = (List<PermissionAttachment>) PERMISSIBLE_BASE_ATTACHMENTS_FIELD.get(oldPermissible);
|
List<PermissionAttachment> attachments = (List<PermissionAttachment>) PERMISSIBLE_BASE_ATTACHMENTS_FIELD.get(oldPermissible);
|
||||||
|
|
||||||
newPermissible.addAttachments(attachments);
|
newPermissible.convertAndAddAttachments(attachments);
|
||||||
attachments.clear();
|
attachments.clear();
|
||||||
oldPermissible.clearPermissions();
|
oldPermissible.clearPermissions();
|
||||||
|
|
||||||
// Setup the new permissible
|
// Setup the new permissible
|
||||||
newPermissible.getActive().set(true);
|
newPermissible.getActive().set(true);
|
||||||
newPermissible.recalculatePermissions(false);
|
|
||||||
newPermissible.setOldPermissible(oldPermissible);
|
newPermissible.setOldPermissible(oldPermissible);
|
||||||
newPermissible.updateSubscriptionsAsync();
|
newPermissible.updateSubscriptionsAsync();
|
||||||
|
|
||||||
@ -164,23 +163,14 @@ public class Injector {
|
|||||||
// handle the replacement permissible.
|
// handle the replacement permissible.
|
||||||
if (dummy) {
|
if (dummy) {
|
||||||
// just inject a dummy class. this is used when we know the player is about to quit the server.
|
// just inject a dummy class. this is used when we know the player is about to quit the server.
|
||||||
HUMAN_ENTITY_PERMISSIBLE_FIELD.set(player, new DummyPermissibleBase());
|
HUMAN_ENTITY_PERMISSIBLE_FIELD.set(player, DummyPermissibleBase.INSTANCE);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// otherwise, inject the permissible they had when we first injected.
|
|
||||||
|
|
||||||
List<PermissionAttachment> lpAttachments = lpPermissible.getAttachments();
|
|
||||||
|
|
||||||
PermissibleBase newPb = lpPermissible.getOldPermissible();
|
PermissibleBase newPb = lpPermissible.getOldPermissible();
|
||||||
if (newPb == null) {
|
if (newPb == null) {
|
||||||
newPb = new PermissibleBase(player);
|
newPb = new PermissibleBase(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
//noinspection unchecked
|
|
||||||
List<PermissionAttachment> newPbAttachments = (List<PermissionAttachment>) PERMISSIBLE_BASE_ATTACHMENTS_FIELD.get(newPb);
|
|
||||||
newPbAttachments.addAll(lpAttachments);
|
|
||||||
lpAttachments.clear();
|
|
||||||
|
|
||||||
HUMAN_ENTITY_PERMISSIBLE_FIELD.set(player, newPb);
|
HUMAN_ENTITY_PERMISSIBLE_FIELD.set(player, newPb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,25 +37,19 @@ import me.lucko.luckperms.common.config.ConfigKeys;
|
|||||||
import me.lucko.luckperms.common.model.User;
|
import me.lucko.luckperms.common.model.User;
|
||||||
import me.lucko.luckperms.common.verbose.CheckOrigin;
|
import me.lucko.luckperms.common.verbose.CheckOrigin;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.permissions.PermissibleBase;
|
import org.bukkit.permissions.PermissibleBase;
|
||||||
import org.bukkit.permissions.Permission;
|
import org.bukkit.permissions.Permission;
|
||||||
import org.bukkit.permissions.PermissionAttachment;
|
import org.bukkit.permissions.PermissionAttachment;
|
||||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||||
import org.bukkit.permissions.PermissionRemovedExecutor;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,12 +88,9 @@ public class LPPermissible extends PermissibleBase {
|
|||||||
// if the permissible is currently active.
|
// if the permissible is currently active.
|
||||||
private final AtomicBoolean active = new AtomicBoolean(false);
|
private final AtomicBoolean active = new AtomicBoolean(false);
|
||||||
|
|
||||||
// the permissions registered by PermissionAttachments.
|
|
||||||
// stored in this format, as that's what is used by #getEffectivePermissions
|
|
||||||
private final Map<String, PermissionAttachmentInfo> attachmentPermissions = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
// the attachments hooked onto the permissible.
|
// the attachments hooked onto the permissible.
|
||||||
private final List<PermissionAttachment> attachments = Collections.synchronizedList(new ArrayList<>());
|
// this collection is only modified by the attachments themselves
|
||||||
|
final Set<LPPermissionAttachment> attachments = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
public LPPermissible(@NonNull Player parent, @NonNull User user, @NonNull LPBukkitPlugin plugin) {
|
public LPPermissible(@NonNull Player parent, @NonNull User user, @NonNull LPBukkitPlugin plugin) {
|
||||||
super(parent);
|
super(parent);
|
||||||
@ -204,8 +195,10 @@ public class LPPermissible extends PermissibleBase {
|
|||||||
*
|
*
|
||||||
* @param attachments the attachments to add
|
* @param attachments the attachments to add
|
||||||
*/
|
*/
|
||||||
public void addAttachments(Collection<PermissionAttachment> attachments) {
|
public void convertAndAddAttachments(Collection<PermissionAttachment> attachments) {
|
||||||
this.attachments.addAll(attachments);
|
for (PermissionAttachment attachment : attachments) {
|
||||||
|
new LPPermissionAttachment(this, attachment).hook();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -226,135 +219,70 @@ public class LPPermissible extends PermissibleBase {
|
|||||||
@Override
|
@Override
|
||||||
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
|
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
|
||||||
Set<PermissionAttachmentInfo> perms = new HashSet<>();
|
Set<PermissionAttachmentInfo> perms = new HashSet<>();
|
||||||
perms.addAll(attachmentPermissions.values());
|
|
||||||
|
|
||||||
perms.addAll(
|
perms.addAll(
|
||||||
user.getUserData().getPermissionData(calculateContexts()).getImmutableBacking().entrySet().stream()
|
user.getUserData().getPermissionData(calculateContexts()).getImmutableBacking().entrySet().stream()
|
||||||
.map(e -> new PermissionAttachmentInfo(parent, e.getKey(), null, e.getValue()))
|
.map(e -> new PermissionAttachmentInfo(parent, e.getKey(), null, e.getValue()))
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
);
|
);
|
||||||
|
|
||||||
return perms;
|
return perms;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PermissionAttachment addAttachment(@NonNull Plugin plugin, @NonNull String name, boolean value) {
|
public LPPermissionAttachment addAttachment(Plugin plugin) {
|
||||||
if (!plugin.isEnabled()) {
|
LPPermissionAttachment ret = new LPPermissionAttachment(this, plugin);
|
||||||
throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is not enabled");
|
ret.hook();
|
||||||
}
|
return ret;
|
||||||
|
|
||||||
PermissionAttachment result = addAttachment(plugin);
|
|
||||||
result.setPermission(name, value);
|
|
||||||
|
|
||||||
recalculatePermissions();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PermissionAttachment addAttachment(@NonNull Plugin plugin) {
|
public PermissionAttachment addAttachment(Plugin plugin, @NonNull String name, boolean value) {
|
||||||
if (!plugin.isEnabled()) {
|
PermissionAttachment ret = addAttachment(plugin);
|
||||||
throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is not enabled");
|
ret.setPermission(name, value);
|
||||||
}
|
return ret;
|
||||||
|
|
||||||
PermissionAttachment result = new PermissionAttachment(plugin, parent);
|
|
||||||
|
|
||||||
attachments.add(result);
|
|
||||||
recalculatePermissions();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PermissionAttachment addAttachment(@NonNull Plugin plugin, @NonNull String name, boolean value, int ticks) {
|
public LPPermissionAttachment addAttachment(@NonNull Plugin plugin, int ticks) {
|
||||||
if (!plugin.isEnabled()) {
|
if (!plugin.isEnabled()) {
|
||||||
throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is not enabled");
|
throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is not enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
PermissionAttachment result = addAttachment(plugin, ticks);
|
LPPermissionAttachment ret = addAttachment(plugin);
|
||||||
if (result != null) {
|
if (getPlugin().getServer().getScheduler().scheduleSyncDelayedTask(plugin, ret::remove, ticks) == -1) {
|
||||||
result.setPermission(name, value);
|
ret.remove();
|
||||||
|
throw new RuntimeException("Could not add PermissionAttachment to " + parent + " for plugin " + plugin.getDescription().getFullName() + ": Scheduler returned -1");
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PermissionAttachment addAttachment(@NonNull Plugin plugin, int ticks) {
|
public LPPermissionAttachment addAttachment(Plugin plugin, @NonNull String name, boolean value, int ticks) {
|
||||||
if (!plugin.isEnabled()) {
|
LPPermissionAttachment ret = addAttachment(plugin, ticks);
|
||||||
throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is not enabled");
|
ret.setPermission(name, value);
|
||||||
}
|
return ret;
|
||||||
|
|
||||||
PermissionAttachment result = addAttachment(plugin);
|
|
||||||
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");
|
|
||||||
result.remove();
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeAttachment(@NonNull PermissionAttachment attachment) {
|
public void removeAttachment(@NonNull PermissionAttachment attachment) {
|
||||||
if (attachments.contains(attachment)) {
|
if (!(attachment instanceof LPPermissionAttachment)) {
|
||||||
attachments.remove(attachment);
|
throw new IllegalArgumentException("Given attachment is not a LPPermissionAttachment.");
|
||||||
PermissionRemovedExecutor ex = attachment.getRemovalCallback();
|
|
||||||
|
|
||||||
if (ex != null) {
|
|
||||||
ex.attachmentRemoved(attachment);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
recalculatePermissions();
|
LPPermissionAttachment a = ((LPPermissionAttachment) attachment);
|
||||||
} else {
|
if (a.getPermissible() != this) {
|
||||||
throw new IllegalArgumentException("Given attachment is not part of Permissible object " + parent);
|
throw new IllegalArgumentException("Attachment does not belong to this permissible.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void recalculatePermissions() {
|
public void recalculatePermissions() {
|
||||||
recalculatePermissions(true);
|
// do nothing
|
||||||
}
|
|
||||||
|
|
||||||
public void recalculatePermissions(boolean invalidate) {
|
|
||||||
if (attachmentPermissions == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
attachmentPermissions.clear();
|
|
||||||
|
|
||||||
for (PermissionAttachment attachment : attachments) {
|
|
||||||
calculateChildPermissions(attachment.getPermissions(), false, attachment);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (invalidate) {
|
|
||||||
user.getUserData().invalidatePermissionCalculators();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void clearPermissions() {
|
public void clearPermissions() {
|
||||||
Set<String> perms = attachmentPermissions.keySet();
|
attachments.forEach(LPPermissionAttachment::remove);
|
||||||
|
|
||||||
for (String name : perms) {
|
|
||||||
Bukkit.getServer().getPluginManager().unsubscribeFromPermission(name, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
attachmentPermissions.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void calculateChildPermissions(Map<String, Boolean> children, boolean invert, PermissionAttachment attachment) {
|
|
||||||
for (Map.Entry<String, Boolean> e : children.entrySet()) {
|
|
||||||
Permission perm = Bukkit.getServer().getPluginManager().getPermission(e.getKey());
|
|
||||||
boolean value = e.getValue() ^ invert;
|
|
||||||
String name = e.getKey().toLowerCase();
|
|
||||||
|
|
||||||
attachmentPermissions.put(name, new PermissionAttachmentInfo(parent, name, attachment, value));
|
|
||||||
Bukkit.getServer().getPluginManager().subscribeToPermission(name, parent);
|
|
||||||
|
|
||||||
if (perm != null) {
|
|
||||||
calculateChildPermissions(perm.getChildren(), !value, attachment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,192 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* 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.bukkit.model;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||||
|
import me.lucko.luckperms.common.node.ImmutableTransientNode;
|
||||||
|
import me.lucko.luckperms.common.node.NodeFactory;
|
||||||
|
|
||||||
|
import org.bukkit.permissions.PermissionAttachment;
|
||||||
|
import org.bukkit.permissions.PermissionRemovedExecutor;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PermissionAttachment for LuckPerms.
|
||||||
|
*
|
||||||
|
* Applies all permissions directly to the backing user instance via transient nodes.
|
||||||
|
*/
|
||||||
|
public class LPPermissionAttachment extends PermissionAttachment {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parent LPPermissible
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private final LPPermissible permissible;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The plugin which "owns" this attachment, may be null
|
||||||
|
*/
|
||||||
|
private final Plugin owner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The permissions being applied by this attachment
|
||||||
|
*/
|
||||||
|
private final Map<String, Boolean> perms = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the attachment has been applied to the user
|
||||||
|
*/
|
||||||
|
private boolean hooked = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to run when the attachment is removed
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private PermissionRemovedExecutor removalCallback = null;
|
||||||
|
|
||||||
|
public LPPermissionAttachment(LPPermissible permissible, Plugin owner) {
|
||||||
|
super(DummyPlugin.INSTANCE, null);
|
||||||
|
this.permissible = permissible;
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LPPermissionAttachment(LPPermissible permissible, PermissionAttachment bukkit) {
|
||||||
|
super(DummyPlugin.INSTANCE, null);
|
||||||
|
this.permissible = permissible;
|
||||||
|
this.owner = null;
|
||||||
|
|
||||||
|
// copy
|
||||||
|
perms.putAll(bukkit.getPermissions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hook() {
|
||||||
|
hooked = true;
|
||||||
|
permissible.attachments.add(this);
|
||||||
|
for (Map.Entry<String, Boolean> entry : perms.entrySet()) {
|
||||||
|
setPermissionInternal(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPermissionInternal(String name, boolean value) {
|
||||||
|
if (!permissible.getPlugin().getConfiguration().get(ConfigKeys.APPLY_BUKKIT_ATTACHMENT_PERMISSIONS)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableTransientNode node = ImmutableTransientNode.of(NodeFactory.make(name, value), this);
|
||||||
|
if (permissible.getUser().setTransientPermission(node).asBoolean()) {
|
||||||
|
permissible.getUser().getRefreshBuffer().request();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unsetPermissionInternal(String name) {
|
||||||
|
if (!permissible.getPlugin().getConfiguration().get(ConfigKeys.APPLY_BUKKIT_ATTACHMENT_PERMISSIONS)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (permissible.getUser().removeIfTransient(n -> n instanceof ImmutableTransientNode && ((ImmutableTransientNode) n).getOwner() == this && n.getPermission().equals(name))) {
|
||||||
|
permissible.getUser().getRefreshBuffer().request();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove() {
|
||||||
|
if (!hooked) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (permissible.getUser().removeIfTransient(n -> n instanceof ImmutableTransientNode && ((ImmutableTransientNode) n).getOwner() == this)) {
|
||||||
|
permissible.getUser().getRefreshBuffer().request();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removalCallback != null) {
|
||||||
|
removalCallback.attachmentRemoved(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
hooked = false;
|
||||||
|
permissible.attachments.remove(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPermission(String name, boolean value) {
|
||||||
|
Boolean previous = perms.put(name, value);
|
||||||
|
if (previous != null && previous == value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hooked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous != null) {
|
||||||
|
unsetPermissionInternal(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
setPermissionInternal(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unsetPermission(String name) {
|
||||||
|
Boolean previous = perms.remove(name);
|
||||||
|
if (previous == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hooked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsetPermissionInternal(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Boolean> getPermissions() {
|
||||||
|
return perms;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Plugin getPlugin() {
|
||||||
|
return owner != null ? owner : permissible.getPlugin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
return this == obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return System.identityHashCode(this);
|
||||||
|
}
|
||||||
|
}
|
@ -23,42 +23,39 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package me.lucko.luckperms.bukkit.processors;
|
package me.lucko.luckperms.common.node;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.ToString;
|
||||||
|
import lombok.experimental.Delegate;
|
||||||
|
|
||||||
import me.lucko.luckperms.api.Tristate;
|
import me.lucko.luckperms.api.Node;
|
||||||
import me.lucko.luckperms.common.processors.PermissionProcessor;
|
|
||||||
|
|
||||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permission Processor for permissions set to a player via permission attachments.
|
* Holds a Node and plus an owning object. All calls are passed onto the contained Node instance.
|
||||||
*/
|
*/
|
||||||
@AllArgsConstructor
|
|
||||||
public class AttachmentProcessor implements PermissionProcessor {
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final Supplier<Map<String, PermissionAttachmentInfo>> map;
|
@ToString
|
||||||
|
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
@Override
|
public final class ImmutableTransientNode implements Node {
|
||||||
public Tristate hasPermission(String permission) {
|
public static ImmutableTransientNode of(@NonNull Node node, @NonNull Object owner) {
|
||||||
Map<String, PermissionAttachmentInfo> m = map.get();
|
return new ImmutableTransientNode(node, owner);
|
||||||
if (m == null) {
|
|
||||||
return Tristate.UNDEFINED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PermissionAttachmentInfo pai = m.get(permission);
|
@Delegate
|
||||||
return pai == null ? Tristate.UNDEFINED : Tristate.fromBoolean(pai.getValue());
|
private final Node node;
|
||||||
|
private final Object owner;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return node.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateBacking(Map<String, Boolean> map) {
|
public boolean equals(Object obj) {
|
||||||
// Do nothing, this doesn't use the backing
|
return this == obj || node.equals(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user