Implement special handling in the LP Vault implementation for NPC players (#1470)

This commit is contained in:
Luck 2019-04-01 15:09:58 +01:00
parent c7a0d7026c
commit 62ca2d9c79
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
4 changed files with 84 additions and 23 deletions

View File

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

View File

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

View File

@ -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.

View File

@ -358,6 +358,16 @@ public final class ConfigKeys {
*/
public static final ConfigKey<Boolean> 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<String> 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<Boolean> VAULT_NPC_OP_STATUS = booleanKey("vault-npc-op-status", false);
/**
* If the vault server option should be used
*/