Add Vault chat support using permission nodes
This commit is contained in:
@@ -22,128 +22,359 @@
|
||||
|
||||
package me.lucko.luckperms.api.vault;
|
||||
|
||||
import lombok.Setter;
|
||||
import me.lucko.luckperms.LPBukkitPlugin;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.core.PermissionHolder;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import net.milkbowl.vault.chat.Chat;
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Dummy class for hooking with Vault plugins that need both Chat + Perms
|
||||
* This doesn't return anything useful, or change anything internally
|
||||
* Provides the Vault Chat service through the use of normal permission nodes.
|
||||
*
|
||||
* Registered on the lowest priority so other plugins can override
|
||||
* Prefixes / Suffixes:
|
||||
* Normal inheritance rules apply.
|
||||
* Permission Nodes = prefix.priority.value OR suffix.priority.value
|
||||
* If a user/group has / inherits multiple prefixes and suffixes, the one with the highest priority is the one that
|
||||
* will apply.
|
||||
*
|
||||
* Meta:
|
||||
* Normal inheritance rules DO NOT apply.
|
||||
* Permission Nodes = meta.node.value
|
||||
*
|
||||
* Node that special characters used within LuckPerms are escaped:
|
||||
* See {@link #escapeCharacters(String)}
|
||||
*
|
||||
* Registered on normal priority so other plugins can override.
|
||||
*/
|
||||
class VaultChatHook extends Chat {
|
||||
private static final Pattern PREFIX_PATTERN = Pattern.compile("(?i)prefix\\.\\d+\\..*");
|
||||
private static final Pattern SUFFIX_PATTERN = Pattern.compile("(?i)suffix\\.\\d+\\..*");
|
||||
|
||||
VaultChatHook(Permission perms) {
|
||||
@Setter
|
||||
private LPBukkitPlugin plugin;
|
||||
private final VaultPermissionHook perms;
|
||||
|
||||
VaultChatHook(VaultPermissionHook perms) {
|
||||
super(perms);
|
||||
}
|
||||
|
||||
private void throwNotSupported() {
|
||||
// throw new UnsupportedOperationException("LuckPerms cannot perform this operation.");
|
||||
this.perms = perms;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "LuckPerms";
|
||||
return perms.getName();
|
||||
}
|
||||
|
||||
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
return perms.isEnabled();
|
||||
}
|
||||
|
||||
private static String escapeCharacters(String s) {
|
||||
s = s.replace(".", "{SEP}");
|
||||
s = s.replace("/", "{FSEP}");
|
||||
s = s.replace("$", "{DSEP}");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private void saveMeta(PermissionHolder holder, String world, String node, String value) {
|
||||
if (holder == null) return;
|
||||
node = escapeCharacters(node);
|
||||
value = escapeCharacters(value);
|
||||
|
||||
if (world == null || world.equals("")) {
|
||||
try {
|
||||
holder.setPermission("meta." + node + "." + value, true);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
} else {
|
||||
try {
|
||||
holder.setPermission("meta." + node + "." + value, true, "global", world);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
}
|
||||
|
||||
perms.objectSave(holder);
|
||||
}
|
||||
|
||||
private static int getMeta(PermissionHolder holder, String world, String node, int defaultValue) {
|
||||
if (holder == null) return defaultValue;
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Map.Entry<String, Boolean> e : holder.getPermissions("global", world, null, true, Collections.emptyList(), false).entrySet()) {
|
||||
if (!e.getValue()) continue;
|
||||
|
||||
String[] parts = Patterns.DOT.split(e.getKey(), 3);
|
||||
if (parts.length < 3) continue;
|
||||
|
||||
if (!parts[0].equalsIgnoreCase("meta")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!parts[1].equalsIgnoreCase(node)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
return Integer.parseInt(parts[2]);
|
||||
} catch (Throwable t) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static double getMeta(PermissionHolder holder, String world, String node, double defaultValue) {
|
||||
if (holder == null) return defaultValue;
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Map.Entry<String, Boolean> e : holder.getPermissions("global", world, null, true, Collections.emptyList(), false).entrySet()) {
|
||||
if (!e.getValue()) continue;
|
||||
|
||||
String[] parts = Patterns.DOT.split(e.getKey(), 3);
|
||||
if (parts.length < 3) continue;
|
||||
|
||||
if (!parts[0].equalsIgnoreCase("meta")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!parts[1].equalsIgnoreCase(node)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
return Double.parseDouble(parts[2]);
|
||||
} catch (Throwable t) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static boolean getMeta(PermissionHolder holder, String world, String node, boolean defaultValue) {
|
||||
if (holder == null) return defaultValue;
|
||||
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Map.Entry<String, Boolean> e : holder.getPermissions("global", world, null, true, Collections.emptyList(), false).entrySet()) {
|
||||
if (!e.getValue()) continue;
|
||||
|
||||
String[] parts = Patterns.DOT.split(e.getKey(), 3);
|
||||
if (parts.length < 3) continue;
|
||||
|
||||
if (!parts[0].equalsIgnoreCase("meta")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!parts[1].equalsIgnoreCase(node)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
return Boolean.parseBoolean(parts[2]);
|
||||
} catch (Throwable t) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static String getMeta(PermissionHolder holder, String world, String node, String defaultValue) {
|
||||
if (holder == null) return defaultValue;
|
||||
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Map.Entry<String, Boolean> e : holder.getPermissions("global", world, null, true, Collections.emptyList(), false).entrySet()) {
|
||||
if (!e.getValue()) continue;
|
||||
|
||||
String[] parts = Patterns.DOT.split(e.getKey(), 3);
|
||||
if (parts.length < 3) continue;
|
||||
|
||||
if (!parts[0].equalsIgnoreCase("meta")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!parts[1].equalsIgnoreCase(node)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return parts[2];
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static String getChatMeta(Pattern pattern, PermissionHolder holder, String world) {
|
||||
if (holder == null) return "";
|
||||
|
||||
int priority = 0;
|
||||
String meta = null;
|
||||
for (Map.Entry<String, Boolean> e : holder.getLocalPermissions("global", world, null).entrySet()) {
|
||||
if (!e.getValue()) continue;
|
||||
|
||||
if (pattern.matcher(e.getKey()).matches()) {
|
||||
String[] parts = Patterns.DOT.split(e.getKey(), 3);
|
||||
int p = Integer.parseInt(parts[1]);
|
||||
|
||||
if (meta == null || p > priority) {
|
||||
meta = parts[2];
|
||||
priority = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return meta == null ? "" : meta;
|
||||
}
|
||||
|
||||
public String getPlayerPrefix(String world, String player) {
|
||||
return "";
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return getChatMeta(PREFIX_PATTERN, user, world);
|
||||
}
|
||||
|
||||
public void setPlayerPrefix(String world, String player, String prefix) {
|
||||
throwNotSupported();
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return;
|
||||
|
||||
try {
|
||||
user.setPermission("prefix.1000." + escapeCharacters(prefix), true);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
perms.objectSave(user);
|
||||
}
|
||||
|
||||
public String getPlayerSuffix(String world, String player) {
|
||||
return "";
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return getChatMeta(SUFFIX_PATTERN, user, world);
|
||||
}
|
||||
|
||||
public void setPlayerSuffix(String world, String player, String suffix) {
|
||||
throwNotSupported();
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return;
|
||||
|
||||
try {
|
||||
user.setPermission("suffix.1000." + escapeCharacters(suffix), true);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
perms.objectSave(user);
|
||||
}
|
||||
|
||||
public String getGroupPrefix(String world, String group) {
|
||||
return "";
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
return getChatMeta(PREFIX_PATTERN, g, world);
|
||||
}
|
||||
|
||||
public void setGroupPrefix(String world, String group, String prefix) {
|
||||
throwNotSupported();
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
if (g == null) return;
|
||||
|
||||
try {
|
||||
g.setPermission("prefix.1000." + escapeCharacters(prefix), true);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
perms.objectSave(g);
|
||||
}
|
||||
|
||||
public String getGroupSuffix(String world, String group) {
|
||||
return "";
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
return getChatMeta(SUFFIX_PATTERN, g, world);
|
||||
}
|
||||
|
||||
public void setGroupSuffix(String world, String group, String suffix) {
|
||||
throwNotSupported();
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
if (g == null) return;
|
||||
|
||||
try {
|
||||
g.setPermission("suffix.1000." + escapeCharacters(suffix), true);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
perms.objectSave(g);
|
||||
}
|
||||
|
||||
public int getPlayerInfoInteger(String world, String player, String node, int defaultValue) {
|
||||
return defaultValue;
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return getMeta(user, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setPlayerInfoInteger(String world, String player, String node, int value) {
|
||||
throwNotSupported();
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
saveMeta(user, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public int getGroupInfoInteger(String world, String group, String node, int defaultValue) {
|
||||
return defaultValue;
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
return getMeta(g, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setGroupInfoInteger(String world, String group, String node, int value) {
|
||||
throwNotSupported();
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
saveMeta(g, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public double getPlayerInfoDouble(String world, String player, String node, double defaultValue) {
|
||||
return defaultValue;
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return getMeta(user, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setPlayerInfoDouble(String world, String player, String node, double value) {
|
||||
throwNotSupported();
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
saveMeta(user, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public double getGroupInfoDouble(String world, String group, String node, double defaultValue) {
|
||||
return defaultValue;
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
return getMeta(g, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setGroupInfoDouble(String world, String group, String node, double value) {
|
||||
throwNotSupported();
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
saveMeta(g, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public boolean getPlayerInfoBoolean(String world, String player, String node, boolean defaultValue) {
|
||||
return defaultValue;
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return getMeta(user, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setPlayerInfoBoolean(String world, String player, String node, boolean value) {
|
||||
throwNotSupported();
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
saveMeta(user, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public boolean getGroupInfoBoolean(String world, String group, String node, boolean defaultValue) {
|
||||
return defaultValue;
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
return getMeta(g, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setGroupInfoBoolean(String world, String group, String node, boolean value) {
|
||||
throwNotSupported();
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
saveMeta(g, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public String getPlayerInfoString(String world, String player, String node, String defaultValue) {
|
||||
return defaultValue;
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return getMeta(user, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setPlayerInfoString(String world, String player, String node, String value) {
|
||||
throwNotSupported();
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
saveMeta(user, world, node, value);
|
||||
}
|
||||
|
||||
public String getGroupInfoString(String world, String group, String node, String defaultValue) {
|
||||
return defaultValue;
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
return getMeta(g, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setGroupInfoString(String world, String group, String node, String value) {
|
||||
throwNotSupported();
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
saveMeta(g, world, node, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -43,11 +43,12 @@ public class VaultHook {
|
||||
if (chatHook == null) {
|
||||
chatHook = new VaultChatHook(permissionHook);
|
||||
}
|
||||
chatHook.setPlugin(plugin);
|
||||
|
||||
final ServicesManager sm = plugin.getServer().getServicesManager();
|
||||
sm.unregisterAll(plugin);
|
||||
sm.register(Permission.class, permissionHook, plugin, ServicePriority.High);
|
||||
sm.register(Chat.class, chatHook, plugin, ServicePriority.Lowest);
|
||||
sm.register(Chat.class, chatHook, plugin, ServicePriority.Low);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -93,7 +93,7 @@ class VaultPermissionHook extends Permission {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void objectSave(PermissionHolder t) {
|
||||
void objectSave(PermissionHolder t) {
|
||||
if (t instanceof User) {
|
||||
((User) t).refreshPermissions();
|
||||
plugin.getDatastore().saveUser(((User) t), Callback.empty());
|
||||
|
||||
@@ -566,7 +566,11 @@ public abstract class PermissionHolder {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
protected Map<String, Boolean> getPermissions(String server, String world, List<String> excludedGroups, boolean includeGlobal, List<String> possibleNodes) {
|
||||
public Map<String, Boolean> getPermissions(String server, String world, List<String> excludedGroups, boolean includeGlobal, List<String> possibleNodes) {
|
||||
return getPermissions(server, world, excludedGroups, includeGlobal, possibleNodes, true);
|
||||
}
|
||||
|
||||
public Map<String, Boolean> getPermissions(String server, String world, List<String> excludedGroups, boolean includeGlobal, List<String> possibleNodes, boolean applyGroups) {
|
||||
if (excludedGroups == null) {
|
||||
excludedGroups = new ArrayList<>();
|
||||
}
|
||||
@@ -686,40 +690,16 @@ public abstract class PermissionHolder {
|
||||
groupNodes.remove(Patterns.SERVER_DELIMITER.split(node.getKey(), 2)[1]);
|
||||
});
|
||||
|
||||
// Apply lowest priority: groupNodes
|
||||
for (Map.Entry<String, Boolean> groupNode : groupNodes.entrySet()) {
|
||||
// Add the actual group perm node, so other plugins can hook
|
||||
perms.put(groupNode.getKey(), groupNode.getValue());
|
||||
|
||||
// Don't add negated groups
|
||||
if (!groupNode.getValue()) continue;
|
||||
|
||||
String groupName = Patterns.DOT.split(groupNode.getKey(), 2)[1];
|
||||
if (!excludedGroups.contains(groupName)) {
|
||||
Group group = plugin.getGroupManager().get(groupName);
|
||||
if (group != null) {
|
||||
perms.putAll(group.getLocalPermissions(server, excludedGroups));
|
||||
} else {
|
||||
plugin.getLog().warn("Error whilst refreshing the permissions of '" + objectName + "'." +
|
||||
"\n The group '" + groupName + "' is not loaded.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
applyShorthandIfEnabled(perms);
|
||||
|
||||
// Apply next priorities: serverSpecificGroups and then serverWorldSpecificGroups
|
||||
for (Map<String, Boolean> m : Arrays.asList(serverSpecificGroups, serverWorldSpecificGroups)) {
|
||||
for (Map.Entry<String, Boolean> groupNode : m.entrySet()) {
|
||||
final String rawNode = Patterns.SERVER_DELIMITER.split(groupNode.getKey())[1];
|
||||
|
||||
if (applyGroups) {
|
||||
// Apply lowest priority: groupNodes
|
||||
for (Map.Entry<String, Boolean> groupNode : groupNodes.entrySet()) {
|
||||
// Add the actual group perm node, so other plugins can hook
|
||||
perms.put(rawNode, groupNode.getValue());
|
||||
perms.put(groupNode.getKey(), groupNode.getValue());
|
||||
|
||||
// Don't add negated groups
|
||||
if (!groupNode.getValue()) continue;
|
||||
|
||||
String groupName = Patterns.DOT.split(rawNode, 2)[1];
|
||||
String groupName = Patterns.DOT.split(groupNode.getKey(), 2)[1];
|
||||
if (!excludedGroups.contains(groupName)) {
|
||||
Group group = plugin.getGroupManager().get(groupName);
|
||||
if (group != null) {
|
||||
@@ -730,7 +710,33 @@ public abstract class PermissionHolder {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
applyShorthandIfEnabled(perms);
|
||||
|
||||
// Apply next priorities: serverSpecificGroups and then serverWorldSpecificGroups
|
||||
for (Map<String, Boolean> m : Arrays.asList(serverSpecificGroups, serverWorldSpecificGroups)) {
|
||||
for (Map.Entry<String, Boolean> groupNode : m.entrySet()) {
|
||||
final String rawNode = Patterns.SERVER_DELIMITER.split(groupNode.getKey())[1];
|
||||
|
||||
// Add the actual group perm node, so other plugins can hook
|
||||
perms.put(rawNode, groupNode.getValue());
|
||||
|
||||
// Don't add negated groups
|
||||
if (!groupNode.getValue()) continue;
|
||||
|
||||
String groupName = Patterns.DOT.split(rawNode, 2)[1];
|
||||
if (!excludedGroups.contains(groupName)) {
|
||||
Group group = plugin.getGroupManager().get(groupName);
|
||||
if (group != null) {
|
||||
perms.putAll(group.getLocalPermissions(server, excludedGroups));
|
||||
} else {
|
||||
plugin.getLog().warn("Error whilst refreshing the permissions of '" + objectName + "'." +
|
||||
"\n The group '" + groupName + "' is not loaded.");
|
||||
}
|
||||
}
|
||||
}
|
||||
applyShorthandIfEnabled(perms);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply next priority: userNodes
|
||||
|
||||
Reference in New Issue
Block a user