From 62ca2d9c7913aa0a95d766f65b1eb2e88f6a2bfa Mon Sep 17 00:00:00 2001 From: Luck Date: Mon, 1 Apr 2019 15:09:58 +0100 Subject: [PATCH] Implement special handling in the LP Vault implementation for NPC players (#1470) --- .../bukkit/vault/LuckPermsVaultChat.java | 28 ++++++---- .../vault/LuckPermsVaultPermission.java | 56 ++++++++++++++----- bukkit/src/main/resources/config.yml | 13 +++++ .../luckperms/common/config/ConfigKeys.java | 10 ++++ 4 files changed, 84 insertions(+), 23 deletions(-) diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/LuckPermsVaultChat.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/LuckPermsVaultChat.java index b49953bac..bbb20724a 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/LuckPermsVaultChat.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/LuckPermsVaultChat.java @@ -38,7 +38,6 @@ import me.lucko.luckperms.common.command.CommandManager; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.PermissionHolder; -import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.node.factory.NodeFactory; import me.lucko.luckperms.common.node.model.NodeTypes; import me.lucko.luckperms.common.verbose.event.MetaCheckEvent; @@ -85,8 +84,8 @@ public class LuckPermsVaultChat extends AbstractVaultChat { public String getUserChatPrefix(String world, UUID uuid) { Objects.requireNonNull(uuid, "uuid"); - User user = this.vaultPermission.lookupUser(uuid); - Contexts contexts = this.vaultPermission.contextForLookup(user, world); + PermissionHolder user = this.vaultPermission.lookupUser(uuid); + Contexts contexts = this.vaultPermission.contextForLookup(uuid, world); MetaCache metaData = user.getCachedData().getMetaData(contexts); String ret = metaData.getPrefix(MetaCheckEvent.Origin.THIRD_PARTY_API); if (log()) { @@ -99,8 +98,8 @@ public class LuckPermsVaultChat extends AbstractVaultChat { public String getUserChatSuffix(String world, UUID uuid) { Objects.requireNonNull(uuid, "uuid"); - User user = this.vaultPermission.lookupUser(uuid); - Contexts contexts = this.vaultPermission.contextForLookup(user, world); + PermissionHolder user = this.vaultPermission.lookupUser(uuid); + Contexts contexts = this.vaultPermission.contextForLookup(uuid, world); MetaCache metaData = user.getCachedData().getMetaData(contexts); String ret = metaData.getSuffix(MetaCheckEvent.Origin.THIRD_PARTY_API); if (log()) { @@ -113,7 +112,10 @@ public class LuckPermsVaultChat extends AbstractVaultChat { public void setUserChatPrefix(String world, UUID uuid, String prefix) { Objects.requireNonNull(uuid, "uuid"); - User user = this.vaultPermission.lookupUser(uuid); + PermissionHolder user = this.vaultPermission.lookupUser(uuid); + if (user instanceof Group) { + throw new UnsupportedOperationException("Unable to modify the permissions of NPC players"); + } setChatMeta(user, ChatMetaType.PREFIX, prefix, world); } @@ -121,7 +123,10 @@ public class LuckPermsVaultChat extends AbstractVaultChat { public void setUserChatSuffix(String world, UUID uuid, String suffix) { Objects.requireNonNull(uuid, "uuid"); - User user = this.vaultPermission.lookupUser(uuid); + PermissionHolder user = this.vaultPermission.lookupUser(uuid); + if (user instanceof Group) { + throw new UnsupportedOperationException("Unable to modify the permissions of NPC players"); + } setChatMeta(user, ChatMetaType.SUFFIX, suffix, world); } @@ -130,8 +135,8 @@ public class LuckPermsVaultChat extends AbstractVaultChat { Objects.requireNonNull(uuid, "uuid"); Objects.requireNonNull(key, "key"); - User user = this.vaultPermission.lookupUser(uuid); - Contexts contexts = this.vaultPermission.contextForLookup(user, world); + PermissionHolder user = this.vaultPermission.lookupUser(uuid); + Contexts contexts = this.vaultPermission.contextForLookup(uuid, world); MetaCache metaData = user.getCachedData().getMetaData(contexts); String ret = metaData.getMeta(MetaCheckEvent.Origin.THIRD_PARTY_API).get(key); if (log()) { @@ -145,7 +150,10 @@ public class LuckPermsVaultChat extends AbstractVaultChat { Objects.requireNonNull(uuid, "uuid"); Objects.requireNonNull(key, "key"); - User user = this.vaultPermission.lookupUser(uuid); + PermissionHolder user = this.vaultPermission.lookupUser(uuid); + if (user instanceof Group) { + throw new UnsupportedOperationException("Unable to modify the permissions of NPC players"); + } setMeta(user, key, value, world); } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/LuckPermsVaultPermission.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/LuckPermsVaultPermission.java index c99389870..0dca1089d 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/LuckPermsVaultPermission.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/LuckPermsVaultPermission.java @@ -52,7 +52,6 @@ import org.bukkit.entity.Player; import java.util.Arrays; import java.util.Objects; -import java.util.Optional; import java.util.UUID; /** @@ -130,7 +129,7 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { return uuid; } - public User lookupUser(UUID uuid) { + public PermissionHolder lookupUser(UUID uuid) { Objects.requireNonNull(uuid, "uuid"); // loaded already? @@ -139,6 +138,21 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { return user; } + // if the uuid is version 2, assume it is an NPC + // see: https://github.com/lucko/LuckPerms/issues/1470 + // and https://github.com/lucko/LuckPerms/issues/1470#issuecomment-475403162 + if (uuid.version() == 2) { + String npcGroupName = this.plugin.getConfiguration().get(ConfigKeys.VAULT_NPC_GROUP); + Group npcGroup = this.plugin.getGroupManager().getIfLoaded(npcGroupName); + if (npcGroup == null) { + npcGroup = this.plugin.getGroupManager().getIfLoaded(NodeFactory.DEFAULT_GROUP_NAME); + if (npcGroup == null) { + throw new IllegalStateException("unable to get default group"); + } + } + return npcGroup; + } + // are we on the main thread? if (!this.plugin.getBootstrap().isServerStarting() && Bukkit.isPrimaryThread() && !this.plugin.getConfiguration().get(ConfigKeys.VAULT_UNSAFE_LOOKUPS)) { throw new RuntimeException( @@ -167,8 +181,8 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { Objects.requireNonNull(uuid, "uuid"); Objects.requireNonNull(permission, "permission"); - User user = lookupUser(uuid); - Contexts contexts = contextForLookup(user, world); + PermissionHolder user = lookupUser(uuid); + Contexts contexts = contextForLookup(uuid, world); PermissionCache permissionData = user.getCachedData().getPermissionData(contexts); Tristate result = permissionData.getPermissionValue(permission, PermissionCheckEvent.Origin.THIRD_PARTY_API).result(); @@ -183,7 +197,10 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { Objects.requireNonNull(uuid, "uuid"); Objects.requireNonNull(permission, "permission"); - User user = lookupUser(uuid); + PermissionHolder user = lookupUser(uuid); + if (user instanceof Group) { + throw new UnsupportedOperationException("Unable to modify the permissions of NPC players"); + } return holderAddPermission(user, permission, world); } @@ -192,7 +209,10 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { Objects.requireNonNull(uuid, "uuid"); Objects.requireNonNull(permission, "permission"); - User user = lookupUser(uuid); + PermissionHolder user = lookupUser(uuid); + if (user instanceof Group) { + throw new UnsupportedOperationException("Unable to modify the permissions of NPC players"); + } return holderRemovePermission(user, permission, world); } @@ -221,8 +241,8 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { public String[] userGetGroups(String world, UUID uuid) { Objects.requireNonNull(uuid, "uuid"); - User user = lookupUser(uuid); - ContextSet contexts = contextForLookup(user, world).getContexts(); + PermissionHolder user = lookupUser(uuid); + ContextSet contexts = contextForLookup(uuid, world).getContexts(); String[] ret = user.enduringData().immutable().values().stream() .filter(Node::isGroupNode) @@ -247,8 +267,11 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { public String userGetPrimaryGroup(String world, UUID uuid) { Objects.requireNonNull(uuid, "uuid"); - User user = lookupUser(uuid); - String value = user.getPrimaryGroup().getValue(); + PermissionHolder user = lookupUser(uuid); + if (user instanceof Group) { // npc + return this.plugin.getConfiguration().get(ConfigKeys.VAULT_NPC_GROUP); + } + String value = ((User) user).getPrimaryGroup().getValue(); Group group = getGroup(value); if (group != null) { value = group.getPlainDisplayName(); @@ -339,10 +362,10 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { } // utility method for getting a contexts instance for a given vault lookup. - Contexts contextForLookup(User user, String world) { + Contexts contextForLookup(UUID uuid, String world) { MutableContextSet context; - Player player = Optional.ofNullable(user).flatMap(u -> this.plugin.getBootstrap().getPlayer(u.getUuid())).orElse(null); + Player player = this.plugin.getBootstrap().getPlayer(uuid).orElse(null); if (player != null) { context = this.plugin.getContextManager().getApplicableContext(player).mutableCopy(); } else { @@ -371,7 +394,14 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { } } - return Contexts.of(context, isIncludeGlobal(), true, true, true, true, false); + boolean op = false; + if (player != null) { + op = player.isOp(); + } else if (uuid.version() == 2) { // npc + op = this.plugin.getConfiguration().get(ConfigKeys.VAULT_NPC_OP_STATUS); + } + + return Contexts.of(context, isIncludeGlobal(), true, true, true, true, op); } // utility methods for modifying the state of PermissionHolders diff --git a/bukkit/src/main/resources/config.yml b/bukkit/src/main/resources/config.yml index dd9c7cbfa..9c1572ce0 100644 --- a/bukkit/src/main/resources/config.yml +++ b/bukkit/src/main/resources/config.yml @@ -501,6 +501,19 @@ commands-allow-op: true # option to 'true. vault-unsafe-lookups: false +# Controls which group LuckPerms should use for NPC players when handling Vault requests. +# +# - As NPCs aren't actually real players, LuckPerms does not load any user data for them. This +# becomes an issue when plugins want to check for their permissions using Vault. +# - As a solution, Vault checks for NPCs fallback to a group, which is defined below. +vault-npc-group: default + +# Controls how LuckPerms should consider the OP status of NPC players when handing Vault requests. +# +# - If you want NPCs to have the same permissions as "normal" players, set this option to false. +# - If you want NPCs to have OP status, set this option to true. +vault-npc-op-status: false + # If the vault-server option below should be used. # # - When this option is set to false, the server value defined above under "server" is used. diff --git a/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java b/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java index d8fac5c37..6618925dd 100644 --- a/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java +++ b/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java @@ -358,6 +358,16 @@ public final class ConfigKeys { */ public static final ConfigKey VAULT_UNSAFE_LOOKUPS = booleanKey("vault-unsafe-lookups", false); + /** + * Controls which group LuckPerms should use for NPC players when handling Vault requests + */ + public static final ConfigKey VAULT_NPC_GROUP = stringKey("vault-npc-group", "default"); + + /** + * Controls how LuckPerms should consider the OP status of NPC players when handing Vault requests + */ + public static final ConfigKey VAULT_NPC_OP_STATUS = booleanKey("vault-npc-op-status", false); + /** * If the vault server option should be used */