Add logging, prepare for import/export system
This commit is contained in:
@@ -24,6 +24,8 @@ package me.lucko.luckperms.utils;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.data.Callback;
|
||||
import me.lucko.luckperms.core.UuidCache;
|
||||
import me.lucko.luckperms.users.User;
|
||||
|
||||
import java.util.UUID;
|
||||
@@ -43,11 +45,11 @@ public class AbstractListener {
|
||||
} else {
|
||||
// No previous data for this player
|
||||
cache.addToCache(u, u);
|
||||
plugin.getDatastore().saveUUIDData(username, u, b -> {});
|
||||
plugin.getDatastore().saveUUIDData(username, u, Callback.empty());
|
||||
}
|
||||
} else {
|
||||
// Online mode, no cache needed. This is just for name -> uuid lookup.
|
||||
plugin.getDatastore().saveUUIDData(username, u, b -> {});
|
||||
plugin.getDatastore().saveUUIDData(username, u, Callback.empty());
|
||||
}
|
||||
|
||||
plugin.getDatastore().loadOrCreateUser(cache.getUUID(u), username);
|
||||
@@ -63,12 +65,12 @@ public class AbstractListener {
|
||||
// Unload the user from memory when they disconnect;
|
||||
cache.clearCache(uuid);
|
||||
|
||||
final User user = plugin.getUserManager().getUser(cache.getUUID(uuid));
|
||||
plugin.getUserManager().unloadUser(user);
|
||||
final User user = plugin.getUserManager().get(cache.getUUID(uuid));
|
||||
plugin.getUserManager().unload(user);
|
||||
}
|
||||
|
||||
protected void refreshPlayer(UUID uuid) {
|
||||
final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(uuid));
|
||||
final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(uuid));
|
||||
if (user != null) {
|
||||
user.refreshPermissions();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* 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.utils;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* An abstract manager class
|
||||
* @param <I> the class used to identify each object held in this manager
|
||||
* @param <T> the class this manager is "managing"
|
||||
*/
|
||||
public abstract class AbstractManager<I, T extends Identifiable<I>> {
|
||||
protected final Map<I, T> objects = new ConcurrentHashMap<>();
|
||||
|
||||
public Map<I, T> getAll() {
|
||||
return objects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an object by id
|
||||
* @param id The id to search by
|
||||
* @return a {@link T} object if the object is loaded, returns null if the object is not loaded
|
||||
*/
|
||||
public T get(I id) {
|
||||
return objects.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a object to the loaded objects map
|
||||
* @param t The object to add
|
||||
*/
|
||||
public void set(T t) {
|
||||
objects.put(t.getId(), t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates (or sets if the object wasn't already loaded) an object in the objects map
|
||||
* @param t The object to update or set
|
||||
*/
|
||||
public void updateOrSet(T t) {
|
||||
if (!isLoaded(t.getId())) {
|
||||
// The object isn't already loaded
|
||||
objects.put(t.getId(), t);
|
||||
} else {
|
||||
copy(t, objects.get(t.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void copy(T from, T to);
|
||||
|
||||
/**
|
||||
* Check to see if a object is loaded or not
|
||||
* @param id The id of the object
|
||||
* @return true if the object is loaded
|
||||
*/
|
||||
public boolean isLoaded(I id) {
|
||||
return objects.containsKey(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes and unloads the object from the manager
|
||||
* @param t The object to unload
|
||||
*/
|
||||
public void unload(T t) {
|
||||
if (t != null) {
|
||||
objects.remove(t.getId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unloads all objects from the manager
|
||||
*/
|
||||
public void unloadAll() {
|
||||
objects.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a new object
|
||||
* @param id the id of the object
|
||||
* @return a new {@link T} object
|
||||
*/
|
||||
public abstract T make(I id);
|
||||
|
||||
}
|
||||
@@ -23,29 +23,29 @@
|
||||
package me.lucko.luckperms.utils;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
|
||||
@UtilityClass
|
||||
public class ArgumentChecker {
|
||||
|
||||
public static boolean checkUsername(String s) {
|
||||
return !(s.length() > 16 || Patterns.NON_USERNAME.matcher(s).find());
|
||||
return (s.length() > 16 || Patterns.NON_USERNAME.matcher(s).find());
|
||||
}
|
||||
|
||||
public static boolean checkName(String s) {
|
||||
return !(s.length() > 36 || Patterns.NON_ALPHA_NUMERIC.matcher(s).find());
|
||||
return (s.length() > 36 || Patterns.NON_ALPHA_NUMERIC.matcher(s).find());
|
||||
}
|
||||
|
||||
public static boolean checkServer(String s) {
|
||||
return !s.toLowerCase().startsWith("r=") && !Patterns.NON_ALPHA_NUMERIC.matcher(s).find();
|
||||
return s.toLowerCase().startsWith("r=") || Patterns.NON_ALPHA_NUMERIC.matcher(s).find();
|
||||
}
|
||||
|
||||
public static boolean checkNode(String s) {
|
||||
return !(s.contains("/") || s.contains("$"));
|
||||
return (s.contains("/") || s.contains("$"));
|
||||
}
|
||||
|
||||
public static boolean checkTime(long l) {
|
||||
return !DateUtil.shouldExpire(l);
|
||||
return DateUtil.shouldExpire(l);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* 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.utils;
|
||||
|
||||
public interface Identifiable<T> {
|
||||
|
||||
T getId();
|
||||
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* 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.utils;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.data.MySQLConfiguration;
|
||||
|
||||
public abstract class LPConfiguration<T extends LuckPermsPlugin> {
|
||||
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
private final T plugin;
|
||||
|
||||
private final String defaultServerName;
|
||||
private final boolean defaultIncludeGlobal;
|
||||
private final String defaultStorage;
|
||||
|
||||
public LPConfiguration(T plugin, String defaultServerName, boolean defaultIncludeGlobal, String defaultStorage) {
|
||||
this.plugin = plugin;
|
||||
this.defaultServerName = defaultServerName;
|
||||
this.defaultIncludeGlobal = defaultIncludeGlobal;
|
||||
this.defaultStorage = defaultStorage;
|
||||
init();
|
||||
|
||||
if (Patterns.NON_ALPHA_NUMERIC.matcher(getServer()).find()) {
|
||||
plugin.getLog().severe("Server name defined in config.yml contains invalid characters. Server names can " +
|
||||
"only contain alphanumeric characters.\nDefined server name '" + getServer() + "' will be replaced with '" +
|
||||
defaultServerName + "' (the default)");
|
||||
set("server", defaultServerName);
|
||||
}
|
||||
|
||||
if (Patterns.NON_ALPHA_NUMERIC.matcher(getDefaultGroupName()).find()) {
|
||||
plugin.getLog().severe("Default group defined in config.yml contains invalid characters. Group names can " +
|
||||
"only contain alphanumeric characters.\nDefined default group name '" + getDefaultGroupName() +
|
||||
"' will be replaced with 'default' (the default)");
|
||||
set("default-group", "default");
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void init();
|
||||
protected abstract void set(String path, Object value);
|
||||
protected abstract String getString(String path, String def);
|
||||
protected abstract int getInt(String path, int def);
|
||||
protected abstract boolean getBoolean(String path, boolean def);
|
||||
|
||||
public String getServer() {
|
||||
return getString("server", defaultServerName);
|
||||
}
|
||||
|
||||
public int getSyncTime() {
|
||||
return getInt("sql.sync-minutes", 3);
|
||||
}
|
||||
|
||||
public String getDefaultGroupNode() {
|
||||
return "group." + getDefaultGroupName();
|
||||
}
|
||||
|
||||
public String getDefaultGroupName() {
|
||||
return getString("default-group", "default");
|
||||
}
|
||||
|
||||
public boolean getIncludeGlobalPerms() {
|
||||
return getBoolean("include-global", defaultIncludeGlobal);
|
||||
}
|
||||
|
||||
public boolean getOnlineMode() {
|
||||
return getBoolean("online-mode", true);
|
||||
}
|
||||
|
||||
public boolean getApplyWildcards() {
|
||||
return getBoolean("apply-wildcards", true);
|
||||
}
|
||||
|
||||
public boolean getApplyRegex() {
|
||||
return getBoolean("apply-regex", true);
|
||||
}
|
||||
|
||||
public boolean getApplyShorthand() {
|
||||
return getBoolean("apply-shorthand", true);
|
||||
}
|
||||
|
||||
public MySQLConfiguration getDatabaseValues() {
|
||||
return new MySQLConfiguration(
|
||||
getString("sql.address", null),
|
||||
getString("sql.database", null),
|
||||
getString("sql.username", null),
|
||||
getString("sql.password", null)
|
||||
);
|
||||
}
|
||||
|
||||
public String getStorageMethod() {
|
||||
return getString("storage-method", defaultStorage);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -26,7 +26,7 @@ import lombok.experimental.UtilityClass;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
|
||||
@UtilityClass
|
||||
public class LogUtil {
|
||||
public class LogFactory {
|
||||
public static Logger wrap(org.slf4j.Logger l) {
|
||||
return new Logger() {
|
||||
private final org.slf4j.Logger logger = l;
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* 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.utils;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
@UtilityClass
|
||||
public class Patterns {
|
||||
private static final Map<String, Pattern> CACHE = new ConcurrentHashMap<>();
|
||||
|
||||
public static final Pattern SPACE = Pattern.compile(" ");
|
||||
public static final Pattern SERVER_DELIMITER = Pattern.compile("\\/");
|
||||
public static final Pattern WORLD_DELIMITER = Pattern.compile("\\-");
|
||||
public static final Pattern TEMP_DELIMITER = Pattern.compile("\\$");
|
||||
public static final Pattern DOT = Pattern.compile("\\.");
|
||||
public static final Pattern VERTICAL_BAR = Pattern.compile("\\|");
|
||||
public static final Pattern GROUP_MATCH = Pattern.compile("group\\..*");
|
||||
public static final Pattern NON_ALPHA_NUMERIC = Pattern.compile("[^A-Za-z0-9]");
|
||||
public static final Pattern NON_USERNAME = Pattern.compile("[^A-Za-z0-9_]");
|
||||
public static final Pattern SHORTHAND_NODE = Pattern.compile("\\.\\([^.]+\\)");
|
||||
|
||||
public static Pattern compile(String regex) throws PatternSyntaxException {
|
||||
if (!CACHE.containsKey(regex)) {
|
||||
Pattern p;
|
||||
try {
|
||||
p = Pattern.compile(regex);
|
||||
} catch (PatternSyntaxException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CACHE.put(regex, p);
|
||||
}
|
||||
|
||||
return CACHE.get(regex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,824 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* 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.utils;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Represents an object that can hold permissions
|
||||
* For example a User or a Group
|
||||
*/
|
||||
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public abstract class PermissionHolder {
|
||||
|
||||
/**
|
||||
* The UUID of the user / name of the group.
|
||||
* Used to prevent circular inheritance issues
|
||||
*/
|
||||
@Getter
|
||||
private final String objectName;
|
||||
|
||||
/**
|
||||
* Reference to the main plugin instance
|
||||
*/
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
private final LuckPermsPlugin plugin;
|
||||
|
||||
/**
|
||||
* The user/group's permissions
|
||||
*/
|
||||
@Getter
|
||||
private Map<String, Boolean> nodes = new ConcurrentHashMap<>();
|
||||
|
||||
public void setNodes(Map<String, Boolean> nodes) {
|
||||
this.nodes.clear();
|
||||
this.nodes.putAll(nodes);
|
||||
auditTemporaryPermissions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for checking if a map has a certain permission. Used by both #hasPermission and #inheritsPermission
|
||||
*/
|
||||
private static boolean hasPermission(Map<String, Boolean> toQuery, String node, boolean b) {
|
||||
// Not temporary
|
||||
if (!node.contains("$")) {
|
||||
return b ? toQuery.containsKey(node) && toQuery.get(node) : toQuery.containsKey(node) && !toQuery.get(node);
|
||||
}
|
||||
|
||||
node = Patterns.TEMP_DELIMITER.split(node)[0];
|
||||
|
||||
for (Map.Entry<String, Boolean> e : toQuery.entrySet()) {
|
||||
if (e.getKey().contains("$")) {
|
||||
String[] parts = Patterns.TEMP_DELIMITER.split(e.getKey());
|
||||
if (parts[0].equalsIgnoreCase(node)) {
|
||||
return b ? e.getValue() : !e.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the object has a certain permission
|
||||
* @param node The permission node
|
||||
* @param b If the node is true/false(negated)
|
||||
* @return true if the user has the permission
|
||||
*/
|
||||
public boolean hasPermission(String node, boolean b) {
|
||||
if (node.startsWith("global/")) node = node.replace("global/", "");
|
||||
return hasPermission(this.nodes, node, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see the the object has a permission on a certain server
|
||||
* @param node The permission node
|
||||
* @param b If the node is true/false(negated)
|
||||
* @param server The server
|
||||
* @return true if the user has the permission
|
||||
*/
|
||||
public boolean hasPermission(String node, boolean b, String server) {
|
||||
return hasPermission(server + "/" + node, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see the the object has a permission on a certain server
|
||||
* @param node The permission node
|
||||
* @param b If the node is true/false(negated)
|
||||
* @param server The server
|
||||
* @param world The world
|
||||
* @return true if the user has the permission
|
||||
*/
|
||||
public boolean hasPermission(String node, boolean b, String server, String world) {
|
||||
return hasPermission(server + "-" + world + "/" + node, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see the the object has a permission on a certain server
|
||||
* @param node The permission node
|
||||
* @param b If the node is true/false(negated)
|
||||
* @param temporary if the permission is temporary
|
||||
* @return true if the user has the permission
|
||||
*/
|
||||
public boolean hasPermission(String node, boolean b, boolean temporary) {
|
||||
return hasPermission(node + (temporary ? "$a" : ""), b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see the the object has a permission on a certain server
|
||||
* @param node The permission node
|
||||
* @param b If the node is true/false(negated)
|
||||
* @param server The server to check on
|
||||
* @param temporary if the permission is temporary
|
||||
* @return true if the user has the permission
|
||||
*/
|
||||
public boolean hasPermission(String node, boolean b, String server, boolean temporary) {
|
||||
return hasPermission(server + "/" + node + (temporary ? "$a" : ""), b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see the the object has a permission on a certain server
|
||||
* @param node The permission node
|
||||
* @param b If the node is true/false(negated)
|
||||
* @param server The server to check on
|
||||
* @param world The world to check on
|
||||
* @param temporary if the permission is temporary
|
||||
* @return true if the user has the permission
|
||||
*/
|
||||
public boolean hasPermission(String node, boolean b, String server, String world, boolean temporary) {
|
||||
return hasPermission(server + "-" + world + "/" + node + (temporary ? "$a" : ""), b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the object inherits a certain permission
|
||||
* @param node The permission node
|
||||
* @param b If the node is true/false(negated)
|
||||
* @return true if the user inherits the permission
|
||||
*/
|
||||
public boolean inheritsPermission(String node, boolean b) {
|
||||
if (node.contains("/")) {
|
||||
// Use other method
|
||||
final String[] parts = Patterns.SERVER_DELIMITER.split(node, 2);
|
||||
return inheritsPermission(parts[1], b, parts[0]);
|
||||
}
|
||||
|
||||
return inheritsPermission(node, b, "global");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see the the object inherits a permission on a certain server
|
||||
* @param node The permission node
|
||||
* @param b If the node is true/false(negated)
|
||||
* @param server The server
|
||||
* @return true if the user inherits the permission
|
||||
*/
|
||||
public boolean inheritsPermission(String node, boolean b, String server) {
|
||||
if (server.contains("-")) {
|
||||
// Use other method
|
||||
final String[] parts = Patterns.WORLD_DELIMITER.split(server, 2);
|
||||
return inheritsPermission(node, b, parts[0], parts[1]);
|
||||
}
|
||||
|
||||
final Map<String, Boolean> local = getLocalPermissions(server, null);
|
||||
return hasPermission(local, node, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see the the object inherits a permission on a certain server
|
||||
* @param node The permission node
|
||||
* @param b If the node is true/false(negated)
|
||||
* @param server The server
|
||||
* @param world The world
|
||||
* @return true if the user inherits the permission
|
||||
*/
|
||||
public boolean inheritsPermission(String node, boolean b, String server, String world) {
|
||||
final Map<String, Boolean> local = getLocalPermissions(server, world, null);
|
||||
return hasPermission(local, node, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the object inherits a certain permission
|
||||
* @param node The permission node
|
||||
* @param b If the node is true/false(negated)
|
||||
* @param temporary if the permission is temporary
|
||||
* @return true if the user inherits the permission
|
||||
*/
|
||||
public boolean inheritsPermission(String node, boolean b, boolean temporary) {
|
||||
return inheritsPermission(node + (temporary ? "$a" : ""), b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the object inherits a certain permission
|
||||
* @param node The permission node
|
||||
* @param b If the node is true/false(negated)
|
||||
* @param server The server
|
||||
* @param temporary if the permission is temporary
|
||||
* @return true if the user inherits the permission
|
||||
*/
|
||||
public boolean inheritsPermission(String node, boolean b, String server, boolean temporary) {
|
||||
return inheritsPermission(server + "/" + node + (temporary ? "$a" : ""), b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the object inherits a certain permission
|
||||
* @param node The permission node
|
||||
* @param b If the node is true/false(negated)
|
||||
* @param server The server
|
||||
* @param world The world
|
||||
* @param temporary if the permission is temporary
|
||||
* @return true if the user inherits the permission
|
||||
*/
|
||||
public boolean inheritsPermission(String node, boolean b, String server, String world, boolean temporary) {
|
||||
return inheritsPermission(server + "-" + world + "/" + node + (temporary ? "$a" : ""), b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a permission for the object
|
||||
* @param node The node to be set
|
||||
* @param value What to set the node to - true/false(negated)
|
||||
* @throws ObjectAlreadyHasException if the object already has the permission
|
||||
*/
|
||||
public void setPermission(String node, boolean value) throws ObjectAlreadyHasException {
|
||||
if (node.startsWith("global/")) node = node.replace("global/", "");
|
||||
if (hasPermission(node, value)) {
|
||||
throw new ObjectAlreadyHasException();
|
||||
}
|
||||
this.nodes.put(node, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a permission for the object
|
||||
* @param node The node to set
|
||||
* @param value What to set the node to - true/false(negated)
|
||||
* @param server The server to set the permission on
|
||||
* @throws ObjectAlreadyHasException if the object already has the permission
|
||||
*/
|
||||
public void setPermission(String node, boolean value, String server) throws ObjectAlreadyHasException {
|
||||
setPermission(server + "/" + node, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a permission for the object
|
||||
* @param node The node to set
|
||||
* @param value What to set the node to - true/false(negated)
|
||||
* @param server The server to set the permission on
|
||||
* @param world The world to set the permission on
|
||||
* @throws ObjectAlreadyHasException if the object already has the permission
|
||||
*/
|
||||
public void setPermission(String node, boolean value, String server, String world) throws ObjectAlreadyHasException {
|
||||
setPermission(server + "-" + world + "/" + node, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a permission for the object
|
||||
* @param node The node to set
|
||||
* @param value What to set the node to - true/false(negated)
|
||||
* @param expireAt The time in unixtime when the permission will expire
|
||||
* @throws ObjectAlreadyHasException if the object already has the permission
|
||||
*/
|
||||
public void setPermission(String node, boolean value, long expireAt) throws ObjectAlreadyHasException {
|
||||
setPermission(node + "$" + expireAt, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a permission for the object
|
||||
* @param node The node to set
|
||||
* @param value What to set the node to - true/false(negated)
|
||||
* @param server The server to set the permission on
|
||||
* @param expireAt The time in unixtime when the permission will expire
|
||||
* @throws ObjectAlreadyHasException if the object already has the permission
|
||||
*/
|
||||
public void setPermission(String node, boolean value, String server, long expireAt) throws ObjectAlreadyHasException {
|
||||
setPermission(node + "$" + expireAt, value, server);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a permission for the object
|
||||
* @param node The node to set
|
||||
* @param value What to set the node to - true/false(negated)
|
||||
* @param server The server to set the permission on
|
||||
* @param world The world to set the permission on
|
||||
* @param expireAt The time in unixtime when the permission will expire
|
||||
* @throws ObjectAlreadyHasException if the object already has the permission
|
||||
*/
|
||||
public void setPermission(String node, boolean value, String server, String world, long expireAt) throws ObjectAlreadyHasException {
|
||||
setPermission(node + "$" + expireAt, value, server, world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets a permission for the object
|
||||
* @param node The node to be unset
|
||||
* @param temporary if the permission being removed is temporary
|
||||
* @throws ObjectLacksException if the node wasn't already set
|
||||
*/
|
||||
public void unsetPermission(String node, boolean temporary) throws ObjectLacksException {
|
||||
if (node.startsWith("global/")) node = node.replace("global/", "");
|
||||
final String fNode = node;
|
||||
Optional<String> match = Optional.empty();
|
||||
|
||||
if (temporary) {
|
||||
match = this.nodes.keySet().stream()
|
||||
.filter(n -> n.contains("$")).filter(n -> Patterns.TEMP_DELIMITER.split(n)[0].equalsIgnoreCase(fNode))
|
||||
.findFirst();
|
||||
} else {
|
||||
if (this.nodes.containsKey(fNode)) {
|
||||
match = Optional.of(fNode);
|
||||
}
|
||||
}
|
||||
|
||||
if (match.isPresent()) {
|
||||
this.nodes.remove(match.get());
|
||||
} else {
|
||||
throw new ObjectLacksException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets a permission for the object
|
||||
* @param node The node to be unset
|
||||
* @throws ObjectLacksException if the node wasn't already set
|
||||
*/
|
||||
public void unsetPermission(String node) throws ObjectLacksException {
|
||||
unsetPermission(node, node.contains("$"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets a permission for the object
|
||||
* @param node The node to be unset
|
||||
* @param server The server to unset the node on
|
||||
* @throws ObjectLacksException if the node wasn't already set
|
||||
*/
|
||||
public void unsetPermission(String node, String server) throws ObjectLacksException {
|
||||
unsetPermission(server + "/" + node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets a permission for the object
|
||||
* @param node The node to be unset
|
||||
* @param server The server to unset the node on
|
||||
* @param world The world to unset the node on
|
||||
* @throws ObjectLacksException if the node wasn't already set
|
||||
*/
|
||||
public void unsetPermission(String node, String server, String world) throws ObjectLacksException {
|
||||
unsetPermission(server + "-" + world + "/" + node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets a permission for the object
|
||||
* @param node The node to be unset
|
||||
* @param server The server to unset the node on
|
||||
* @param temporary if the permission being unset is temporary
|
||||
* @throws ObjectLacksException if the node wasn't already set
|
||||
*/
|
||||
public void unsetPermission(String node, String server, boolean temporary) throws ObjectLacksException {
|
||||
unsetPermission(server + "/" + node, temporary);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets a permission for the object
|
||||
* @param node The node to be unset
|
||||
* @param server The server to unset the node on
|
||||
* @param world The world to unset the node on
|
||||
* @param temporary if the permission being unset is temporary
|
||||
* @throws ObjectLacksException if the node wasn't already set
|
||||
*/
|
||||
public void unsetPermission(String node, String server, String world, boolean temporary) throws ObjectLacksException {
|
||||
unsetPermission(server + "-" + world + "/" + node, temporary);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the permissions and inherited permissions that apply to a specific server
|
||||
* @param server The server to get nodes for
|
||||
* @param world The world to get nodes for
|
||||
* @param excludedGroups Groups that shouldn't be inherited (to prevent circular inheritance issues)
|
||||
* @param possibleNodes A list of possible permission nodes for wildcard permission handling
|
||||
* @return a {@link Map} of the permissions
|
||||
*/
|
||||
public Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups, List<String> possibleNodes) {
|
||||
return getPermissions(server, world, excludedGroups, plugin.getConfiguration().getIncludeGlobalPerms(), possibleNodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the permissions and inherited permissions that apply to a specific server
|
||||
* @param server The server to get nodes for
|
||||
* @param world The world to get nodes for
|
||||
* @param excludedGroups Groups that shouldn't be inherited (to prevent circular inheritance issues)
|
||||
* @return a {@link Map} of the permissions
|
||||
*/
|
||||
public Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups) {
|
||||
return getPermissions(server, world, excludedGroups, plugin.getConfiguration().getIncludeGlobalPerms(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the permissions and inherited permissions that apply to a specific server
|
||||
* @param server The server to get nodes for
|
||||
* @param excludedGroups Groups that shouldn't be inherited (to prevent circular inheritance issues)
|
||||
* @param possibleNodes A list of possible permission nodes for wildcard permission handling
|
||||
* @return a {@link Map} of the permissions
|
||||
*/
|
||||
public Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups, List<String> possibleNodes) {
|
||||
return getLocalPermissions(server, null, excludedGroups, possibleNodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the permissions and inherited permissions that apply to a specific server
|
||||
* @param server The server to get nodes for
|
||||
* @param excludedGroups Groups that shouldn't be inherited (to prevent circular inheritance issues)
|
||||
* @return a {@link Map} of the permissions
|
||||
*/
|
||||
public Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups) {
|
||||
return getLocalPermissions(server, null, excludedGroups, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the objects and returns the temporary ones.
|
||||
* @return a map of temporary nodes
|
||||
*/
|
||||
public Map<Map.Entry<String, Boolean>, Long> getTemporaryNodes() {
|
||||
return this.nodes.entrySet().stream().filter(e -> e.getKey().contains("$")).map(e -> {
|
||||
final String[] parts = Patterns.TEMP_DELIMITER.split(e.getKey());
|
||||
final long expiry = Long.parseLong(parts[1]);
|
||||
return new AbstractMap.SimpleEntry<Map.Entry<String, Boolean>, Long>(new AbstractMap.SimpleEntry<>(parts[0], e.getValue()), expiry);
|
||||
|
||||
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the objects and returns the non-temporary ones.
|
||||
* @return a map of permanent nodes
|
||||
*/
|
||||
public Map<String, Boolean> getPermanentNodes() {
|
||||
return this.nodes.entrySet().stream().filter(e -> !e.getKey().contains("$"))
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes temporary permissions that have expired
|
||||
*/
|
||||
public void auditTemporaryPermissions() {
|
||||
this.nodes.keySet().stream()
|
||||
.filter(s -> s.contains("$"))
|
||||
.filter(s -> DateUtil.shouldExpire(Long.parseLong(Patterns.TEMP_DELIMITER.split(s)[1])))
|
||||
.forEach(s -> this.nodes.remove(s));
|
||||
}
|
||||
|
||||
private Map<String, Boolean> convertTemporaryPerms() {
|
||||
auditTemporaryPermissions();
|
||||
|
||||
Map<String, Boolean> nodes = new HashMap<>();
|
||||
Map<String, Boolean> tempNodes = new HashMap<>();
|
||||
|
||||
for (Map.Entry<String, Boolean> e : this.nodes.entrySet()) {
|
||||
if (e.getKey().contains("$")) {
|
||||
tempNodes.put(e.getKey(), e.getValue());
|
||||
} else {
|
||||
nodes.put(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
// temporary permissions override non-temporary permissions
|
||||
tempNodes.entrySet().forEach(e -> nodes.put(stripTime(e.getKey()), e.getValue()));
|
||||
return nodes;
|
||||
}
|
||||
|
||||
protected Map<String, Boolean> getPermissions(String server, String world, List<String> excludedGroups, boolean includeGlobal, List<String> possibleNodes) {
|
||||
if (excludedGroups == null) {
|
||||
excludedGroups = new ArrayList<>();
|
||||
}
|
||||
|
||||
excludedGroups.add(getObjectName());
|
||||
Map<String, Boolean> perms = new HashMap<>();
|
||||
|
||||
if (server == null || server.equals("")) {
|
||||
server = "global";
|
||||
}
|
||||
|
||||
if (world != null && world.equalsIgnoreCase("")) {
|
||||
world = null;
|
||||
}
|
||||
|
||||
/*
|
||||
Priority:
|
||||
|
||||
1. server+world specific nodes
|
||||
2. server specific nodes
|
||||
3. user nodes
|
||||
4. server+world specific group nodes
|
||||
5. server specific group nodes
|
||||
6. group nodes
|
||||
*/
|
||||
|
||||
final Map<String, Boolean> serverWorldSpecificNodes = new HashMap<>();
|
||||
final Map<String, Boolean> serverSpecificNodes = new HashMap<>();
|
||||
final Map<String, Boolean> userNodes = new HashMap<>();
|
||||
final Map<String, Boolean> serverWorldSpecificGroups = new HashMap<>();
|
||||
final Map<String, Boolean> serverSpecificGroups = new HashMap<>();
|
||||
final Map<String, Boolean> groupNodes = new HashMap<>();
|
||||
|
||||
// Sorts the permissions and puts them into a priority order
|
||||
for (Map.Entry<String, Boolean> node : convertTemporaryPerms().entrySet()) {
|
||||
serverSpecific:
|
||||
if (node.getKey().contains("/")) {
|
||||
String[] parts = Patterns.SERVER_DELIMITER.split(node.getKey(), 2);
|
||||
// 0=server(+world) 1=node
|
||||
|
||||
// WORLD SPECIFIC
|
||||
if (parts[0].contains("-")) {
|
||||
String[] serverParts = Patterns.WORLD_DELIMITER.split(parts[0], 2);
|
||||
// 0=server 1=world
|
||||
|
||||
if ((!serverParts[0].equalsIgnoreCase("global") || !includeGlobal) && (!matches(server, serverParts[0]))) {
|
||||
// GLOBAL AND UNWANTED OR SERVER SPECIFIC BUT DOES NOT APPLY :(((
|
||||
continue;
|
||||
}
|
||||
|
||||
if (world != null && !matches(world, serverParts[1])) {
|
||||
// WORLD SPECIFIC BUT DOES NOT APPLY
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Patterns.GROUP_MATCH.matcher(parts[1]).matches()) {
|
||||
// SERVER+WORLD SPECIFIC AND GROUP
|
||||
serverWorldSpecificGroups.put(node.getKey(), node.getValue());
|
||||
continue;
|
||||
}
|
||||
|
||||
// SERVER+WORLD SPECIFIC
|
||||
serverWorldSpecificNodes.put(node.getKey(), node.getValue());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parts[0].equalsIgnoreCase("global")) {
|
||||
// REGULAR
|
||||
break serverSpecific;
|
||||
}
|
||||
|
||||
if (!matches(server, parts[0])) {
|
||||
// SERVER SPECIFIC BUT DOES NOT APPLY
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Patterns.GROUP_MATCH.matcher(parts[1]).matches()) {
|
||||
// SERVER SPECIFIC AND GROUP
|
||||
serverSpecificGroups.put(node.getKey(), node.getValue());
|
||||
continue;
|
||||
}
|
||||
|
||||
// SERVER SPECIFIC
|
||||
serverSpecificNodes.put(node.getKey(), node.getValue());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip adding global permissions if they are not requested
|
||||
if (!includeGlobal) continue;
|
||||
|
||||
// Could be here if the server was set to global.
|
||||
String n = node.getKey();
|
||||
if (n.contains("/")) {
|
||||
n = Patterns.SERVER_DELIMITER.split(n, 2)[1];
|
||||
}
|
||||
|
||||
if (Patterns.GROUP_MATCH.matcher(n).matches()) {
|
||||
// GROUP
|
||||
groupNodes.put(n, node.getValue());
|
||||
continue;
|
||||
}
|
||||
|
||||
// JUST NORMAL
|
||||
userNodes.put(n, node.getValue());
|
||||
}
|
||||
|
||||
// If a group is negated at a higher priority, the group should not then be applied at a lower priority
|
||||
serverWorldSpecificGroups.entrySet().stream().filter(node -> !node.getValue()).forEach(node -> {
|
||||
groupNodes.remove(node.getKey());
|
||||
groupNodes.remove(Patterns.SERVER_DELIMITER.split(node.getKey(), 2)[1]);
|
||||
serverSpecificGroups.remove(node.getKey());
|
||||
serverSpecificGroups.remove(Patterns.SERVER_DELIMITER.split(node.getKey(), 2)[1]);
|
||||
serverSpecificGroups.remove(Patterns.WORLD_DELIMITER.split(node.getKey(), 2)[0] + "/" + Patterns.SERVER_DELIMITER.split(node.getKey(), 2)[1]);
|
||||
});
|
||||
serverSpecificGroups.entrySet().stream().filter(node -> !node.getValue()).forEach(node -> {
|
||||
groupNodes.remove(node.getKey());
|
||||
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().getGroup(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];
|
||||
|
||||
// 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().getGroup(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
|
||||
perms.putAll(userNodes);
|
||||
applyShorthandIfEnabled(perms);
|
||||
|
||||
// Apply final priorities: serverSpecificNodes and then serverWorldSpecificNodes
|
||||
for (Map<String, Boolean> m : Arrays.asList(serverSpecificNodes, serverWorldSpecificNodes)) {
|
||||
for (Map.Entry<String, Boolean> node : m.entrySet()) {
|
||||
final String rawNode = Patterns.SERVER_DELIMITER.split(node.getKey())[1];
|
||||
perms.put(rawNode, node.getValue());
|
||||
}
|
||||
applyShorthandIfEnabled(perms);
|
||||
}
|
||||
|
||||
if (plugin.getConfiguration().getApplyRegex()) {
|
||||
if (possibleNodes != null && !possibleNodes.isEmpty()) {
|
||||
perms = applyRegex(perms, possibleNodes);
|
||||
} else {
|
||||
perms = applyRegex(perms, plugin.getPossiblePermissions());
|
||||
}
|
||||
}
|
||||
|
||||
applyShorthandIfEnabled(perms);
|
||||
|
||||
if (plugin.getConfiguration().getApplyWildcards()) {
|
||||
if (possibleNodes != null && !possibleNodes.isEmpty()) {
|
||||
perms = applyWildcards(perms, possibleNodes);
|
||||
} else {
|
||||
perms = applyWildcards(perms, plugin.getPossiblePermissions());
|
||||
}
|
||||
}
|
||||
|
||||
return perms;
|
||||
}
|
||||
|
||||
private boolean matches(String entry, String possibleRegex) {
|
||||
if (!possibleRegex.toLowerCase().startsWith("r=") || !plugin.getConfiguration().getApplyRegex()) {
|
||||
return entry.equalsIgnoreCase(possibleRegex);
|
||||
}
|
||||
|
||||
Pattern p = Patterns.compile(possibleRegex.substring(2));
|
||||
if (p == null) {
|
||||
return false;
|
||||
}
|
||||
return p.matcher(entry).matches();
|
||||
}
|
||||
|
||||
private Map<String, Boolean> applyRegex(Map<String, Boolean> input, List<String> possibleNodes) {
|
||||
for (Map.Entry<String, Boolean> e : input.entrySet()) {
|
||||
if (!e.getKey().startsWith("r=") && !e.getKey().startsWith("R=")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final Pattern node = Patterns.compile(e.getKey().substring(2));
|
||||
if (node == null) continue;
|
||||
possibleNodes.stream()
|
||||
.filter(n -> node.matcher(n).matches())
|
||||
.filter(n -> !input.containsKey(n))
|
||||
.forEach(n -> input.put(n, e.getValue()));
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
private static Map<String, Boolean> applyWildcards(Map<String, Boolean> input, List<String> possibleNodes) {
|
||||
SortedMap<Integer, Map<String, Boolean>> wildcards = new TreeMap<>(Collections.reverseOrder());
|
||||
for (Map.Entry<String, Boolean> e : input.entrySet()) {
|
||||
if (e.getKey().equals("*") || e.getKey().equals("'*'")) {
|
||||
wildcards.put(0, Collections.singletonMap("*", e.getValue()));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!e.getKey().endsWith(".*")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final String node = e.getKey().substring(0, e.getKey().length() - 2);
|
||||
final String[] parts = Patterns.DOT.split(node);
|
||||
|
||||
if (!wildcards.containsKey(parts.length)) {
|
||||
wildcards.put(parts.length, new HashMap<>());
|
||||
}
|
||||
|
||||
wildcards.get(parts.length).put(node, e.getValue());
|
||||
}
|
||||
|
||||
for (Map.Entry<Integer, Map<String, Boolean>> e : wildcards.entrySet()) {
|
||||
if (e.getKey() == 0) {
|
||||
// Apply all permissions
|
||||
possibleNodes.stream()
|
||||
.filter(n -> !input.containsKey(n)) // Don't override existing nodes
|
||||
.forEach(n -> input.put(n, e.getValue().get("*")));
|
||||
break;
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Boolean> wc : e.getValue().entrySet()) {
|
||||
possibleNodes.stream()
|
||||
.filter(n -> n.startsWith(wc.getKey() + ".")) // Only nodes that match the wildcard are applied
|
||||
.filter(n -> !input.containsKey(n)) // Don't override existing nodes
|
||||
.forEach(n -> input.put(n, wc.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
private void applyShorthandIfEnabled(Map<String, Boolean> map) {
|
||||
if (plugin.getConfiguration().getApplyShorthand()) {
|
||||
applyShorthand(map);
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, Boolean> applyShorthand(Map<String, Boolean> input) {
|
||||
for (Map.Entry<String, Boolean> e : input.entrySet()) {
|
||||
if (!Patterns.SHORTHAND_NODE.matcher(e.getKey()).find()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!e.getKey().contains(".")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] parts = Patterns.DOT.split(e.getKey());
|
||||
List<Set<String>> nodeParts = new ArrayList<>();
|
||||
|
||||
for (String s : parts) {
|
||||
if ((!s.startsWith("(") || !s.endsWith(")")) || !s.contains("|")) {
|
||||
nodeParts.add(Collections.singleton(s));
|
||||
continue;
|
||||
}
|
||||
|
||||
final String bits = s.substring(1, s.length() - 1);
|
||||
nodeParts.add(new HashSet<>(Arrays.asList(Patterns.VERTICAL_BAR.split(bits))));
|
||||
}
|
||||
|
||||
Set<String> nodes = new HashSet<>();
|
||||
for (Set<String> set : nodeParts) {
|
||||
final Set<String> newNodes = new HashSet<>();
|
||||
if (nodes.isEmpty()) {
|
||||
newNodes.addAll(set);
|
||||
} else {
|
||||
nodes.forEach(str -> newNodes.addAll(set.stream()
|
||||
.map(add -> str + "." + add)
|
||||
.collect(Collectors.toList()))
|
||||
);
|
||||
}
|
||||
nodes = newNodes;
|
||||
}
|
||||
|
||||
nodes.stream()
|
||||
.filter(n -> !input.containsKey(n)) // Don't override existing nodes
|
||||
.forEach(n -> input.put(n, e.getValue()));
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
private static String stripTime(String s) {
|
||||
if (s.contains("$")) {
|
||||
return Patterns.TEMP_DELIMITER.split(s)[0];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* 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.utils;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* This UuidCache is a means of allowing users to have the same internal UUID across a network of offline mode servers
|
||||
* or mixed offline mode and online mode servers. Platforms running in offline mode generate a random UUID for a user when
|
||||
* they first join the server, but this UUID will then not be consistent across the network. LuckPerms will instead check
|
||||
* the datastore cache, to get a UUID for a user that is consistent across an entire network.
|
||||
*
|
||||
* If you want to get a user object from the datastore using the api on a server in offline mode, you will need to use this cache,
|
||||
* OR use Datastore#getUUID, for users that are not online.
|
||||
*/
|
||||
public class UuidCache {
|
||||
|
||||
// External UUID --> Internal UUID
|
||||
private Map<UUID, UUID> cache;
|
||||
|
||||
@Getter
|
||||
private final boolean onlineMode;
|
||||
|
||||
public UuidCache(boolean onlineMode) {
|
||||
this.onlineMode = onlineMode;
|
||||
|
||||
if (!onlineMode) {
|
||||
cache = new ConcurrentHashMap<>();
|
||||
}
|
||||
}
|
||||
|
||||
public UUID getUUID(UUID external) {
|
||||
return onlineMode ? external : (cache.containsKey(external) ? cache.get(external) : external);
|
||||
}
|
||||
|
||||
public UUID getExternalUUID(UUID internal) {
|
||||
if (onlineMode) return internal;
|
||||
|
||||
Optional<UUID> external = cache.entrySet().stream().filter(e -> e.getValue().equals(internal)).map(Map.Entry::getKey).findFirst();
|
||||
return external.isPresent() ? external.get() : internal;
|
||||
}
|
||||
|
||||
public void addToCache(UUID external, UUID internal) {
|
||||
if (onlineMode) return;
|
||||
cache.put(external, internal);
|
||||
}
|
||||
|
||||
public void clearCache(UUID external) {
|
||||
if (onlineMode) return;
|
||||
cache.remove(external);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user