mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-24 11:38:40 +01:00
More progress towards 1.6: add transient permissions
This commit is contained in:
parent
2ea9b36c77
commit
2a305b1c55
@ -44,11 +44,23 @@ public interface Node extends Map.Entry<String, Boolean> {
|
||||
@Override
|
||||
Boolean getValue();
|
||||
|
||||
/**
|
||||
* @return the value of this node as a Tristate
|
||||
*/
|
||||
Tristate getTristate();
|
||||
|
||||
/**
|
||||
* @return true if the node is negated
|
||||
*/
|
||||
boolean isNegated();
|
||||
|
||||
/**
|
||||
* If this node is set to override explicitly.
|
||||
* This value does not persist across saves, and is therefore only useful for transient nodes
|
||||
* @return true if this node is set to override explicitly
|
||||
*/
|
||||
boolean isOverride();
|
||||
|
||||
/**
|
||||
* Gets the server this node applies on, if the node is server specific
|
||||
* @return an {@link Optional} containing the server, if one is defined
|
||||
@ -189,6 +201,13 @@ public interface Node extends Map.Entry<String, Boolean> {
|
||||
*/
|
||||
int getWildcardLevel();
|
||||
|
||||
/**
|
||||
* Similar to {@link #equals(Object)}, except doesn't take note of the value
|
||||
* @param node the other node
|
||||
* @return true if the two nodes are almost equal
|
||||
*/
|
||||
boolean equalsIgnoringValue(Node node);
|
||||
|
||||
/**
|
||||
* Similar to {@link #equals(Object)}, except doesn't take note of the expiry time or value
|
||||
* @param node the other node
|
||||
@ -199,6 +218,13 @@ public interface Node extends Map.Entry<String, Boolean> {
|
||||
interface Builder {
|
||||
Builder setNegated(boolean negated);
|
||||
Builder setValue(boolean value);
|
||||
|
||||
/**
|
||||
* Warning: this value does not persist, and disappears when the holder is re-loaded.
|
||||
* It is therefore only useful for transient nodes.
|
||||
*/
|
||||
Builder setOverride(boolean override);
|
||||
|
||||
Builder setExpiry(long expireAt);
|
||||
Builder setWorld(String world);
|
||||
Builder setServer(String server) throws IllegalArgumentException;
|
||||
|
@ -28,6 +28,7 @@ import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
|
||||
/**
|
||||
* Wrapper interface for internal PermissionHolder (object/group) instances
|
||||
@ -43,10 +44,25 @@ public interface PermissionHolder {
|
||||
|
||||
/**
|
||||
* Gets an immutable Set of the objects permission nodes
|
||||
* @return an immutable set of permissions
|
||||
* @return an immutable set of permissions in priority order
|
||||
* @since 1.6
|
||||
*/
|
||||
Set<Node> getPermissionNodes();
|
||||
SortedSet<Node> getPermissions();
|
||||
|
||||
/**
|
||||
* Similar to {@link #getPermissions()}, except excluding transient permissions
|
||||
* @return a set of nodes
|
||||
* @since 1.6
|
||||
*/
|
||||
Set<Node> getEnduringPermissions();
|
||||
|
||||
/**
|
||||
* Similar to {@link #getPermissions()}, except excluding non-transient permissions
|
||||
* @return a set of nodes
|
||||
* @since 1.6
|
||||
*/
|
||||
Set<Node> getTransientPermissions();
|
||||
|
||||
|
||||
/**
|
||||
* Gets an immutable set of the nodes that this object has and inherits
|
||||
@ -58,7 +74,7 @@ public interface PermissionHolder {
|
||||
/**
|
||||
* Gets an immutable Map of the objects permission nodes
|
||||
* @return an immutable map of permissions
|
||||
* @deprecated in favour of {@link #getPermissionNodes()}
|
||||
* @deprecated in favour of {@link #getPermissions()}
|
||||
*/
|
||||
@Deprecated
|
||||
Map<String, Boolean> getNodes();
|
||||
@ -66,11 +82,20 @@ public interface PermissionHolder {
|
||||
/**
|
||||
* Checks to see if the object has a certain permission
|
||||
* @param node the node to check for
|
||||
* @return true if the object has the permission
|
||||
* @return a Tristate for the holders permission status for the node
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
*/
|
||||
boolean hasPermission(Node node);
|
||||
Tristate hasPermission(Node node);
|
||||
|
||||
/**
|
||||
* Checks to see if the object has a certain permission
|
||||
* @param node the node to check for
|
||||
* @return a Tristate for the holders permission status for the node
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
*/
|
||||
Tristate hasTransientPermission(Node node);
|
||||
|
||||
/**
|
||||
* Checks to see if the object has a certain permission
|
||||
@ -79,9 +104,7 @@ public interface PermissionHolder {
|
||||
* @return true if the object has the permission
|
||||
* @throws NullPointerException if the node is null
|
||||
* @throws IllegalArgumentException if the node is invalid
|
||||
* @deprecated in favour of {@link #hasPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
boolean hasPermission(String node, boolean b);
|
||||
|
||||
/**
|
||||
@ -92,9 +115,7 @@ public interface PermissionHolder {
|
||||
* @return true if the object has the permission
|
||||
* @throws NullPointerException if the node or server is null
|
||||
* @throws IllegalArgumentException if the node or server is invalid
|
||||
* @deprecated in favour of {@link #hasPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
boolean hasPermission(String node, boolean b, String server);
|
||||
|
||||
/**
|
||||
@ -106,9 +127,7 @@ public interface PermissionHolder {
|
||||
* @return true if the object has the permission
|
||||
* @throws NullPointerException if the node, server or world is null
|
||||
* @throws IllegalArgumentException if the node, server or world is invalid
|
||||
* @deprecated in favour of {@link #hasPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
boolean hasPermission(String node, boolean b, String server, String world);
|
||||
|
||||
/**
|
||||
@ -119,9 +138,7 @@ public interface PermissionHolder {
|
||||
* @return true if the object has the permission
|
||||
* @throws NullPointerException if the node is null
|
||||
* @throws IllegalArgumentException if the node is invalid
|
||||
* @deprecated in favour of {@link #hasPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
boolean hasPermission(String node, boolean b, boolean temporary);
|
||||
|
||||
/**
|
||||
@ -133,9 +150,7 @@ public interface PermissionHolder {
|
||||
* @return true if the object has the permission
|
||||
* @throws NullPointerException if the node or server is null
|
||||
* @throws IllegalArgumentException if the node or server is invalid
|
||||
* @deprecated in favour of {@link #hasPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
boolean hasPermission(String node, boolean b, String server, boolean temporary);
|
||||
|
||||
/**
|
||||
@ -148,19 +163,17 @@ public interface PermissionHolder {
|
||||
* @return true if the object has the permission
|
||||
* @throws NullPointerException if the node, server or world is null
|
||||
* @throws IllegalArgumentException if the node, server or world is invalid
|
||||
* @deprecated in favour of {@link #hasPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
boolean hasPermission(String node, boolean b, String server, String world, boolean temporary);
|
||||
|
||||
/**
|
||||
* Cheks to see if the object inherits a certain permission
|
||||
* @param node the node to check for
|
||||
* @return true if the object inherits the permission
|
||||
* @return a Tristate for the holders inheritance status for the node
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
*/
|
||||
boolean inheritsPermission(Node node);
|
||||
Tristate inheritsPermission(Node node);
|
||||
|
||||
/**
|
||||
* Checks to see if the object inherits a certain permission
|
||||
@ -169,9 +182,7 @@ public interface PermissionHolder {
|
||||
* @return true if the object inherits the permission
|
||||
* @throws NullPointerException if the node is null
|
||||
* @throws IllegalArgumentException if the node is invalid
|
||||
* @deprecated in favour of {@link #inheritsPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
boolean inheritsPermission(String node, boolean b);
|
||||
|
||||
/**
|
||||
@ -182,9 +193,7 @@ public interface PermissionHolder {
|
||||
* @return true if the object inherits the permission
|
||||
* @throws NullPointerException if the node or server is null
|
||||
* @throws IllegalArgumentException if the node or server is invalid
|
||||
* @deprecated in favour of {@link #inheritsPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
boolean inheritsPermission(String node, boolean b, String server);
|
||||
|
||||
/**
|
||||
@ -196,9 +205,7 @@ public interface PermissionHolder {
|
||||
* @return true if the object inherits the permission
|
||||
* @throws NullPointerException if the node, server or world is null
|
||||
* @throws IllegalArgumentException if the node server or world is invalid
|
||||
* @deprecated in favour of {@link #inheritsPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
boolean inheritsPermission(String node, boolean b, String server, String world);
|
||||
|
||||
/**
|
||||
@ -209,9 +216,7 @@ public interface PermissionHolder {
|
||||
* @return true if the object inherits the permission
|
||||
* @throws NullPointerException if the node is null
|
||||
* @throws IllegalArgumentException if the node is invalid
|
||||
* @deprecated in favour of {@link #inheritsPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
boolean inheritsPermission(String node, boolean b, boolean temporary);
|
||||
|
||||
/**
|
||||
@ -223,9 +228,7 @@ public interface PermissionHolder {
|
||||
* @return true if the object inherits the permission
|
||||
* @throws NullPointerException if the node or server is null
|
||||
* @throws IllegalArgumentException if the node or server is invalid
|
||||
* @deprecated in favour of {@link #inheritsPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
boolean inheritsPermission(String node, boolean b, String server, boolean temporary);
|
||||
|
||||
/**
|
||||
@ -238,9 +241,7 @@ public interface PermissionHolder {
|
||||
* @return true if the object inherits the permission
|
||||
* @throws NullPointerException if the node, server or world is null
|
||||
* @throws IllegalArgumentException if the node, server or world if invalid
|
||||
* @deprecated in favour of {@link #inheritsPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
boolean inheritsPermission(String node, boolean b, String server, String world, boolean temporary);
|
||||
|
||||
/**
|
||||
@ -252,6 +253,25 @@ public interface PermissionHolder {
|
||||
*/
|
||||
void setPermission(Node node) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* Sets a transient permission for the object
|
||||
*
|
||||
* <p> A transient node is a permission that does not persist.
|
||||
* Whenever a user logs out of the server, or the server restarts, this permission will disappear.
|
||||
* It is never saved to the datastore, and therefore will not apply on other servers.
|
||||
*
|
||||
* This is useful if you want to temporarily set a permission for a user while they're online, but don't
|
||||
* want it to persist, and have to worry about removing it when they log out.
|
||||
*
|
||||
* For unsetting a transient permission, see {@link #unsetTransientPermission(Node)}
|
||||
*
|
||||
* @param node The node to be set
|
||||
* @throws ObjectAlreadyHasException if the object already has the permission
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
*/
|
||||
void setTransientPermission(Node node) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* Sets a permission for the object
|
||||
* @param node The node to be set
|
||||
@ -342,6 +362,15 @@ public interface PermissionHolder {
|
||||
*/
|
||||
void unsetPermission(Node node) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* Unsets a transient permission for the object
|
||||
* @param node The node to be unset
|
||||
* @throws ObjectLacksException if the node wasn't already set
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
*/
|
||||
void unsetTransientPermission(Node node) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* Unsets a permission for the object
|
||||
* @param node The node to be unset
|
||||
|
47
api/src/main/java/me/lucko/luckperms/api/Tristate.java
Normal file
47
api/src/main/java/me/lucko/luckperms/api/Tristate.java
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.api;
|
||||
|
||||
/**
|
||||
* Represents a permission value
|
||||
*/
|
||||
public enum Tristate {
|
||||
|
||||
TRUE(true),
|
||||
FALSE(false),
|
||||
UNDEFINED(false);
|
||||
|
||||
private final boolean booleanValue;
|
||||
|
||||
Tristate(boolean booleanValue) {
|
||||
this.booleanValue = booleanValue;
|
||||
}
|
||||
|
||||
public boolean asBoolean() {
|
||||
return booleanValue;
|
||||
}
|
||||
|
||||
public static Tristate fromBoolean(boolean b) {
|
||||
return b ? TRUE : FALSE;
|
||||
}
|
||||
}
|
@ -103,7 +103,7 @@ class VaultChatHook extends Chat {
|
||||
if (node.equals("")) return defaultValue;
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Map.Entry<String, Boolean> e : holder.getPermissions("global", world, null, true, Collections.emptyList(), false).entrySet()) {
|
||||
for (Map.Entry<String, Boolean> e : holder.exportNodes("global", world, null, true, false, Collections.emptyList()).entrySet()) {
|
||||
if (!e.getValue()) continue;
|
||||
|
||||
String[] parts = Patterns.DOT.split(e.getKey(), 3);
|
||||
@ -132,7 +132,7 @@ class VaultChatHook extends Chat {
|
||||
if (node.equals("")) return defaultValue;
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Map.Entry<String, Boolean> e : holder.getPermissions("global", world, null, true, Collections.emptyList(), false).entrySet()) {
|
||||
for (Map.Entry<String, Boolean> e : holder.exportNodes("global", world, null, true, false, Collections.emptyList()).entrySet()) {
|
||||
if (!e.getValue()) continue;
|
||||
|
||||
String[] parts = Patterns.DOT.split(e.getKey(), 3);
|
||||
@ -161,7 +161,7 @@ class VaultChatHook extends Chat {
|
||||
if (node.equals("")) return defaultValue;
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Map.Entry<String, Boolean> e : holder.getPermissions("global", world, null, true, Collections.emptyList(), false).entrySet()) {
|
||||
for (Map.Entry<String, Boolean> e : holder.exportNodes("global", world, null, true, false, Collections.emptyList()).entrySet()) {
|
||||
if (!e.getValue()) continue;
|
||||
|
||||
String[] parts = Patterns.DOT.split(e.getKey(), 3);
|
||||
@ -190,7 +190,7 @@ class VaultChatHook extends Chat {
|
||||
if (node.equals("")) return defaultValue;
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Map.Entry<String, Boolean> e : holder.getPermissions("global", world, null, true, Collections.emptyList(), false).entrySet()) {
|
||||
for (Map.Entry<String, Boolean> e : holder.exportNodes("global", world, null, true, false, Collections.emptyList()).entrySet()) {
|
||||
if (!e.getValue()) continue;
|
||||
|
||||
String[] parts = Patterns.DOT.split(e.getKey(), 3);
|
||||
|
@ -26,18 +26,19 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.PermissionHolder;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static me.lucko.luckperms.api.implementation.internal.Utils.*;
|
||||
import static me.lucko.luckperms.core.PermissionHolder.convertToLegacy;
|
||||
import static me.lucko.luckperms.core.PermissionHolder.exportToLegacy;
|
||||
|
||||
/**
|
||||
* Provides a link between {@link PermissionHolder} and {@link me.lucko.luckperms.core.PermissionHolder}
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@SuppressWarnings({"unused", "deprecation"})
|
||||
@AllArgsConstructor
|
||||
public class PermissionHolderLink implements PermissionHolder {
|
||||
|
||||
@ -50,10 +51,20 @@ public class PermissionHolderLink implements PermissionHolder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Node> getPermissionNodes() {
|
||||
public SortedSet<Node> getPermissions() {
|
||||
return Collections.unmodifiableSortedSet(master.getPermissions());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Node> getEnduringPermissions() {
|
||||
return Collections.unmodifiableSet(master.getNodes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Node> getTransientPermissions() {
|
||||
return Collections.unmodifiableSet(master.getTransientNodes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Node> getAllNodes() {
|
||||
return Collections.unmodifiableSet(master.getAllNodes(null));
|
||||
@ -61,12 +72,17 @@ public class PermissionHolderLink implements PermissionHolder {
|
||||
|
||||
@Override
|
||||
public Map<String, Boolean> getNodes() {
|
||||
return convertToLegacy(master.getNodes());
|
||||
return exportToLegacy(master.getNodes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NonNull Node node) {
|
||||
return master.hasPermission(node);
|
||||
public Tristate hasPermission(@NonNull Node node) {
|
||||
return master.hasPermission(node, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tristate hasTransientPermission(@NonNull Node node) {
|
||||
return master.hasPermission(node, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -100,7 +116,7 @@ public class PermissionHolderLink implements PermissionHolder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean inheritsPermission(@NonNull Node node) {
|
||||
public Tristate inheritsPermission(@NonNull Node node) {
|
||||
return master.inheritsPermission(node);
|
||||
}
|
||||
|
||||
@ -139,6 +155,11 @@ public class PermissionHolderLink implements PermissionHolder {
|
||||
master.setPermission(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransientPermission(@NonNull Node node) throws ObjectAlreadyHasException {
|
||||
master.setTransientPermission(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPermission(@NonNull String node, @NonNull boolean value) throws ObjectAlreadyHasException {
|
||||
master.setPermission(checkNode(node), value);
|
||||
@ -174,6 +195,11 @@ public class PermissionHolderLink implements PermissionHolder {
|
||||
master.unsetPermission(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsetTransientPermission(@NonNull Node node) throws ObjectLacksException {
|
||||
master.unsetTransientPermission(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsetPermission(@NonNull String node, @NonNull boolean temporary) throws ObjectLacksException {
|
||||
master.unsetPermission(checkNode(node), temporary);
|
||||
@ -226,7 +252,7 @@ public class PermissionHolderLink implements PermissionHolder {
|
||||
|
||||
@Override
|
||||
public Map<String, Boolean> getPermissions(String server, String world, Map<String, String> extraContext, boolean includeGlobal, List<String> possibleNodes, boolean applyGroups) {
|
||||
return master.getPermissions(server, world, extraContext, includeGlobal, possibleNodes, applyGroups);
|
||||
return master.exportNodes(server, world, extraContext, includeGlobal, applyGroups, possibleNodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -247,7 +273,7 @@ public class PermissionHolderLink implements PermissionHolder {
|
||||
|
||||
@Override
|
||||
public Map<String, Boolean> getPermanentNodes() {
|
||||
return convertToLegacy(master.getPermanentNodes());
|
||||
return exportToLegacy(master.getPermanentNodes());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -30,7 +30,7 @@ import me.lucko.luckperms.groups.Group;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static me.lucko.luckperms.core.PermissionHolder.convertToLegacy;
|
||||
import static me.lucko.luckperms.core.PermissionHolder.exportToLegacy;
|
||||
|
||||
public class GroupListNodes extends SubCommand<Group> {
|
||||
public GroupListNodes() {
|
||||
@ -40,7 +40,7 @@ public class GroupListNodes extends SubCommand<Group> {
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
|
||||
Message.LISTNODES.send(sender, group.getName(), Util.permNodesToString(convertToLegacy(group.getPermanentNodes())));
|
||||
Message.LISTNODES.send(sender, group.getName(), Util.permNodesToString(exportToLegacy(group.getPermanentNodes())));
|
||||
Message.LISTNODES_TEMP.send(sender, group.getName(), Util.tempNodesToString(group.getTemporaryNodesLegacy()));
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.*;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.core.PermissionHolder;
|
||||
import me.lucko.luckperms.users.User;
|
||||
|
||||
import java.util.List;
|
||||
@ -41,7 +40,7 @@ public class UserListNodes extends SubCommand<User> {
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
Message.LISTNODES.send(sender, user.getName(), Util.permNodesToString(convertToLegacy(user.getPermanentNodes())));
|
||||
Message.LISTNODES.send(sender, user.getName(), Util.permNodesToString(exportToLegacy(user.getPermanentNodes())));
|
||||
Message.LISTNODES_TEMP.send(sender, user.getName(), Util.tempNodesToString(user.getTemporaryNodesLegacy()));
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.event.events.GroupRemoveEvent;
|
||||
import me.lucko.luckperms.api.event.events.PermissionNodeExpireEvent;
|
||||
import me.lucko.luckperms.api.event.events.PermissionNodeSetEvent;
|
||||
@ -38,6 +39,7 @@ import me.lucko.luckperms.groups.Group;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -66,14 +68,195 @@ public abstract class PermissionHolder {
|
||||
@Getter
|
||||
private Set<Node> nodes = ConcurrentHashMap.newKeySet();
|
||||
|
||||
/**
|
||||
* The user/group's transient permissions
|
||||
*/
|
||||
@Getter
|
||||
private Set<Node> transientNodes = ConcurrentHashMap.newKeySet();
|
||||
|
||||
/**
|
||||
* Returns a Set of nodes in priority order
|
||||
* @return the holders transient and permanent nodes
|
||||
*/
|
||||
public SortedSet<Node> getPermissions() {
|
||||
// Returns no duplicate nodes. as in, nodes with the same value.
|
||||
|
||||
TreeSet<Node> permissions = new TreeSet<>(PRIORITY_COMPARATOR);
|
||||
permissions.addAll(nodes);
|
||||
permissions.addAll(transientNodes);
|
||||
|
||||
Iterator<Node> iterator = permissions.descendingIterator(); // TODO check this
|
||||
while (iterator.hasNext()) {
|
||||
Node entry = iterator.next();
|
||||
|
||||
permissions.stream()
|
||||
.filter(entry::equalsIgnoringValue) // The node appears again at a higher priority
|
||||
.forEachOrdered(other -> iterator.remove()); // Remove it.
|
||||
}
|
||||
|
||||
return permissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes temporary permissions that have expired
|
||||
* @return true if permissions had expired and were removed
|
||||
*/
|
||||
public boolean auditTemporaryPermissions() {
|
||||
boolean work = false;
|
||||
|
||||
Iterator<Node> iterator = nodes.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Node element = iterator.next();
|
||||
if (element.hasExpired()) {
|
||||
iterator.remove();
|
||||
|
||||
work = true;
|
||||
plugin.getApiProvider().fireEventAsync(new PermissionNodeExpireEvent(new PermissionHolderLink(this), element));
|
||||
}
|
||||
}
|
||||
|
||||
Iterator<Node> iterator2 = transientNodes.iterator();
|
||||
while (iterator2.hasNext()) {
|
||||
Node element = iterator2.next();
|
||||
if (element.hasExpired()) {
|
||||
iterator2.remove();
|
||||
|
||||
work = true;
|
||||
plugin.getApiProvider().fireEventAsync(new PermissionNodeExpireEvent(new PermissionHolderLink(this), element));
|
||||
}
|
||||
}
|
||||
|
||||
return work;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all of the nodes that this holder has and inherits
|
||||
* @param excludedGroups a list of groups to exclude
|
||||
* @return a set of nodes
|
||||
*/
|
||||
public SortedSet<Node> getAllNodes(List<String> excludedGroups) {
|
||||
SortedSet<Node> all = new ConcurrentSkipListSet<>(PRIORITY_COMPARATOR);
|
||||
all.addAll(getPermissions());
|
||||
|
||||
if (excludedGroups == null) {
|
||||
excludedGroups = new ArrayList<>();
|
||||
}
|
||||
|
||||
excludedGroups.add(getObjectName().toLowerCase());
|
||||
|
||||
Set<String> parents = getPermissions().stream()
|
||||
.filter(Node::isGroupNode)
|
||||
.map(Node::getGroupName)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
for (String parent : parents) {
|
||||
Group group = plugin.getGroupManager().get(parent);
|
||||
if (group == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (excludedGroups.contains(group.getObjectName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
inherited:
|
||||
for (Node inherited : group.getAllNodes(excludedGroups)) {
|
||||
for (Node existing : all) {
|
||||
if (existing.almostEquals(inherited)) {
|
||||
continue inherited;
|
||||
}
|
||||
}
|
||||
|
||||
all.add(inherited);
|
||||
}
|
||||
}
|
||||
|
||||
return all;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all of the nodes that this holder has (and inherits), given the context
|
||||
* @param server the server
|
||||
* @param world the world
|
||||
* @param extraContext any extra context to filter by
|
||||
* @param includeGlobal whether to include global nodes
|
||||
* @param applyGroups if inherited group permissions should be included
|
||||
* @return a map of permissions
|
||||
*/
|
||||
public Set<Node> getAllNodesFiltered(String server, String world, Map<String, String> extraContext, boolean includeGlobal, boolean applyGroups) {
|
||||
Set<Node> perms = ConcurrentHashMap.newKeySet();
|
||||
SortedSet<Node> allNodes;
|
||||
|
||||
if (applyGroups) {
|
||||
allNodes = sort(getAllNodes(null), true);
|
||||
} else {
|
||||
allNodes = sort(getPermissions(), true);
|
||||
}
|
||||
|
||||
for (Node node : allNodes) {
|
||||
if (!node.shouldApplyOnServer(server, includeGlobal, plugin.getConfiguration().getApplyRegex())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!node.shouldApplyOnWorld(world, includeGlobal, plugin.getConfiguration().getApplyRegex())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!node.shouldApplyWithContext(extraContext)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
perms.add(node);
|
||||
}
|
||||
|
||||
return perms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the output of {@link #getAllNodesFiltered(String, String, Map, boolean, boolean)}, and expands wildcards/regex/shorthand perms
|
||||
* @param server the server
|
||||
* @param world the world
|
||||
* @param extraContext any extra context to filter by
|
||||
* @param includeGlobal whether to include global nodes
|
||||
* @param applyGroups if inherited group permissions should be included
|
||||
* @param possibleNodes a list of possible nodes for wildcards and regex permissions
|
||||
* @return a map of permissions
|
||||
*/
|
||||
public Map<String, Boolean> exportNodes(String server, String world, Map<String, String> extraContext, boolean includeGlobal, boolean applyGroups, List<String> possibleNodes) {
|
||||
Map<String, Boolean> perms = new HashMap<>();
|
||||
|
||||
for (Node node : getAllNodesFiltered(server, world, extraContext, includeGlobal, applyGroups)) {
|
||||
perms.put(node.getPermission(), node.getValue());
|
||||
|
||||
if (plugin.getConfiguration().getApplyShorthand()) {
|
||||
node.resolveShorthand().stream()
|
||||
.filter(s -> !perms.containsKey(s))
|
||||
.forEach(s -> perms.put(s, node.getValue()));
|
||||
}
|
||||
|
||||
if (plugin.getConfiguration().getApplyWildcards()) {
|
||||
node.resolveWildcard(possibleNodes).stream()
|
||||
.filter(s -> !perms.containsKey(s))
|
||||
.forEach(s -> perms.put(s, node.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap(perms);
|
||||
}
|
||||
|
||||
public void setNodes(Set<Node> nodes) {
|
||||
this.nodes.clear();
|
||||
this.nodes.addAll(nodes);
|
||||
auditTemporaryPermissions();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static Map<String, Boolean> convertToLegacy(Set<Node> nodes) {
|
||||
public void setTransiestNodes(Set<Node> nodes) {
|
||||
this.transientNodes.clear();
|
||||
this.transientNodes.addAll(nodes);
|
||||
auditTemporaryPermissions();
|
||||
}
|
||||
|
||||
public static Map<String, Boolean> exportToLegacy(Set<Node> nodes) {
|
||||
Map<String, Boolean> m = new HashMap<>();
|
||||
for (Node node : nodes) {
|
||||
m.put(node.toSerializedNode(), node.getValue());
|
||||
@ -81,6 +264,7 @@ public abstract class PermissionHolder {
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
|
||||
// Convenience method
|
||||
private static Node.Builder buildNode(String permission) {
|
||||
return new me.lucko.luckperms.utils.Node.Builder(permission);
|
||||
}
|
||||
@ -96,84 +280,94 @@ public abstract class PermissionHolder {
|
||||
auditTemporaryPermissions();
|
||||
}
|
||||
|
||||
private static boolean hasPermission(Set<Node> toQuery, Node node) {
|
||||
private static Tristate hasPermission(Set<Node> toQuery, Node node) {
|
||||
for (Node n : toQuery) {
|
||||
if (n.almostEquals(node)) {
|
||||
return true;
|
||||
if (n.equalsIgnoringValue(node)) {
|
||||
n.getTristate();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return Tristate.UNDEFINED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the holder has a permission node
|
||||
* @param node the node to check
|
||||
* @return true if the holder has the node
|
||||
* @param t whether to check transient nodes
|
||||
* @return a tristate
|
||||
*/
|
||||
public boolean hasPermission(Node node) {
|
||||
return hasPermission(this.nodes, node);
|
||||
public Tristate hasPermission(Node node, boolean t) {
|
||||
return hasPermission(t ? transientNodes : nodes, node);
|
||||
}
|
||||
|
||||
public Tristate hasPermission(Node node) {
|
||||
return hasPermission(node, false);
|
||||
}
|
||||
|
||||
public boolean hasPermission(String node, boolean b) {
|
||||
return hasPermission(buildNode(node).setValue(b).build());
|
||||
return hasPermission(buildNode(node).setValue(b).build()).asBoolean() == b;
|
||||
}
|
||||
|
||||
public boolean hasPermission(String node, boolean b, String server) {
|
||||
return hasPermission(buildNode(node).setValue(b).setServer(server).build());
|
||||
return hasPermission(buildNode(node).setValue(b).setServer(server).build()).asBoolean() == b;
|
||||
}
|
||||
|
||||
public boolean hasPermission(String node, boolean b, String server, String world) {
|
||||
return hasPermission(buildNode(node).setValue(b).setServer(server).setWorld(world).build());
|
||||
return hasPermission(buildNode(node).setValue(b).setServer(server).setWorld(world).build()).asBoolean() == b;
|
||||
}
|
||||
|
||||
public boolean hasPermission(String node, boolean b, boolean temporary) {
|
||||
return hasPermission(buildNode(node).setValue(b).setExpiry(temporary ? 10L : 0L).build());
|
||||
return hasPermission(buildNode(node).setValue(b).setExpiry(temporary ? 10L : 0L).build()).asBoolean() == b;
|
||||
}
|
||||
|
||||
public boolean hasPermission(String node, boolean b, String server, boolean temporary) {
|
||||
return hasPermission(buildNode(node).setValue(b).setServer(server).setExpiry(temporary ? 10L : 0L).build());
|
||||
return hasPermission(buildNode(node).setValue(b).setServer(server).setExpiry(temporary ? 10L : 0L).build()).asBoolean() == b;
|
||||
}
|
||||
|
||||
public boolean hasPermission(String node, boolean b, String server, String world, boolean temporary) {
|
||||
return hasPermission(buildNode(node).setValue(b).setServer(server).setWorld(world).setExpiry(temporary ? 10L : 0L).build());
|
||||
return hasPermission(buildNode(node).setValue(b).setServer(server).setWorld(world).setExpiry(temporary ? 10L : 0L).build()).asBoolean() == b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the holder inherits a node
|
||||
* @param node the node to check
|
||||
* @return true if the holder inherits the node
|
||||
* @return a tristate
|
||||
*/
|
||||
public boolean inheritsPermission(Node node) {
|
||||
public Tristate inheritsPermission(Node node) {
|
||||
return hasPermission(getAllNodes(null), node);
|
||||
}
|
||||
|
||||
public boolean inheritsPermission(String node, boolean b) {
|
||||
return inheritsPermission(buildNode(node).setValue(b).build());
|
||||
return inheritsPermission(buildNode(node).setValue(b).build()).asBoolean() == b;
|
||||
}
|
||||
|
||||
public boolean inheritsPermission(String node, boolean b, String server) {
|
||||
return inheritsPermission(buildNode(node).setValue(b).setServer(server).build());
|
||||
return inheritsPermission(buildNode(node).setValue(b).setServer(server).build()).asBoolean() == b;
|
||||
}
|
||||
|
||||
public boolean inheritsPermission(String node, boolean b, String server, String world) {
|
||||
return inheritsPermission(buildNode(node).setValue(b).setServer(server).setWorld(world).build());
|
||||
return inheritsPermission(buildNode(node).setValue(b).setServer(server).setWorld(world).build()).asBoolean() == b;
|
||||
}
|
||||
|
||||
public boolean inheritsPermission(String node, boolean b, boolean temporary) {
|
||||
return inheritsPermission(buildNode(node).setValue(b).setExpiry(temporary ? 10L : 0L).build());
|
||||
return inheritsPermission(buildNode(node).setValue(b).setExpiry(temporary ? 10L : 0L).build()).asBoolean() == b;
|
||||
}
|
||||
|
||||
public boolean inheritsPermission(String node, boolean b, String server, boolean temporary) {
|
||||
return inheritsPermission(buildNode(node).setValue(b).setServer(server).setExpiry(temporary ? 10L : 0L).build());
|
||||
return inheritsPermission(buildNode(node).setValue(b).setServer(server).setExpiry(temporary ? 10L : 0L).build()).asBoolean() == b;
|
||||
}
|
||||
|
||||
public boolean inheritsPermission(String node, boolean b, String server, String world, boolean temporary) {
|
||||
return inheritsPermission(buildNode(node).setValue(b).setServer(server).setWorld(world).setExpiry(temporary ? 10L : 0L).build());
|
||||
return inheritsPermission(buildNode(node).setValue(b).setServer(server).setWorld(world).setExpiry(temporary ? 10L : 0L).build()).asBoolean() == b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a permission node
|
||||
* @param node the node to set
|
||||
* @throws ObjectAlreadyHasException if the holder has this permission already
|
||||
*/
|
||||
public void setPermission(Node node) throws ObjectAlreadyHasException {
|
||||
if (hasPermission(node)) {
|
||||
if (hasPermission(node, false) == Tristate.TRUE) {
|
||||
throw new ObjectAlreadyHasException();
|
||||
}
|
||||
|
||||
@ -181,6 +375,20 @@ public abstract class PermissionHolder {
|
||||
plugin.getApiProvider().fireEventAsync(new PermissionNodeSetEvent(new PermissionHolderLink(this), node));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a transient permission node
|
||||
* @param node the node to set
|
||||
* @throws ObjectAlreadyHasException if the holder has this permission already
|
||||
*/
|
||||
public void setTransientPermission(Node node) throws ObjectAlreadyHasException {
|
||||
if (hasPermission(node, true) == Tristate.TRUE) {
|
||||
throw new ObjectAlreadyHasException();
|
||||
}
|
||||
|
||||
transientNodes.add(node);
|
||||
plugin.getApiProvider().fireEventAsync(new PermissionNodeSetEvent(new PermissionHolderLink(this), node));
|
||||
}
|
||||
|
||||
public void setPermission(String node, boolean value) throws ObjectAlreadyHasException {
|
||||
setPermission(buildNode(node).setValue(value).build());
|
||||
}
|
||||
@ -211,7 +419,7 @@ public abstract class PermissionHolder {
|
||||
* @throws ObjectLacksException if the holder doesn't have this node already
|
||||
*/
|
||||
public void unsetPermission(Node node) throws ObjectLacksException {
|
||||
if (!hasPermission(node)) {
|
||||
if (hasPermission(node, false) == Tristate.FALSE) {
|
||||
throw new ObjectLacksException();
|
||||
}
|
||||
|
||||
@ -225,6 +433,26 @@ public abstract class PermissionHolder {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets a transient permission node
|
||||
* @param node the node to unset
|
||||
* @throws ObjectLacksException if the holder doesn't have this node already
|
||||
*/
|
||||
public void unsetTransientPermission(Node node) throws ObjectLacksException {
|
||||
if (hasPermission(node, true) == Tristate.FALSE) {
|
||||
throw new ObjectLacksException();
|
||||
}
|
||||
|
||||
transientNodes.remove(node);
|
||||
|
||||
if (node.isGroupNode()) {
|
||||
plugin.getApiProvider().fireEventAsync(new GroupRemoveEvent(new PermissionHolderLink(this),
|
||||
node.getGroupName(), node.getServer().orElse(null), node.getWorld().orElse(null), node.isTemporary()));
|
||||
} else {
|
||||
plugin.getApiProvider().fireEventAsync(new PermissionNodeUnsetEvent(new PermissionHolderLink(this), node));
|
||||
}
|
||||
}
|
||||
|
||||
public void unsetPermission(String node, boolean temporary) throws ObjectLacksException {
|
||||
unsetPermission(buildNode(node).setExpiry(temporary ? 10L : 0L).build());
|
||||
}
|
||||
@ -253,7 +481,7 @@ public abstract class PermissionHolder {
|
||||
* @return The temporary nodes held by the holder
|
||||
*/
|
||||
public Set<Node> getTemporaryNodes() {
|
||||
return nodes.stream().filter(Node::isTemporary).collect(Collectors.toSet());
|
||||
return getPermissions().stream().filter(Node::isTemporary).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@ -271,84 +499,18 @@ public abstract class PermissionHolder {
|
||||
* @return The permanent nodes held by the holder
|
||||
*/
|
||||
public Set<Node> getPermanentNodes() {
|
||||
return nodes.stream().filter(Node::isPermanent).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes temporary permissions that have expired
|
||||
* @return true if permissions had expired and were removed
|
||||
*/
|
||||
public boolean auditTemporaryPermissions() {
|
||||
boolean work = false;
|
||||
Iterator<Node> iterator = nodes.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Node element = iterator.next();
|
||||
if (element.hasExpired()) {
|
||||
iterator.remove();
|
||||
|
||||
work = true;
|
||||
plugin.getApiProvider().fireEventAsync(new PermissionNodeExpireEvent(new PermissionHolderLink(this), element));
|
||||
}
|
||||
}
|
||||
|
||||
return work;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all of the nodes that this holder has and inherits
|
||||
* @param excludedGroups a list of groups to exclude
|
||||
* @return a set of nodes
|
||||
*/
|
||||
public Set<Node> getAllNodes(List<String> excludedGroups) {
|
||||
Set<Node> all = ConcurrentHashMap.newKeySet();
|
||||
all.addAll(nodes);
|
||||
|
||||
if (excludedGroups == null) {
|
||||
excludedGroups = new ArrayList<>();
|
||||
}
|
||||
|
||||
excludedGroups.add(getObjectName().toLowerCase());
|
||||
|
||||
Set<String> parents = nodes.stream()
|
||||
.filter(Node::isGroupNode)
|
||||
.map(Node::getGroupName)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
for (String parent : parents) {
|
||||
Group group = plugin.getGroupManager().get(parent);
|
||||
if (group == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (excludedGroups.contains(group.getObjectName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
inherited:
|
||||
for (Node inherited : group.getAllNodes(excludedGroups)) {
|
||||
for (Node existing : all) {
|
||||
if (existing.almostEquals(inherited)) {
|
||||
continue inherited;
|
||||
}
|
||||
}
|
||||
|
||||
all.add(inherited);
|
||||
}
|
||||
}
|
||||
|
||||
return all;
|
||||
return getPermissions().stream().filter(Node::isPermanent).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't use these methods, only here for compat reasons
|
||||
*/
|
||||
public Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups, List<String> possibleNodes) {
|
||||
return getPermissions(server, world, null, plugin.getConfiguration().getIncludeGlobalPerms(), possibleNodes, true);
|
||||
return exportNodes(server, world, null, plugin.getConfiguration().getIncludeGlobalPerms(), true, possibleNodes);
|
||||
}
|
||||
|
||||
public Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups) {
|
||||
return getPermissions(server, world, null, plugin.getConfiguration().getIncludeGlobalPerms(), null, true);
|
||||
return exportNodes(server, world, null, plugin.getConfiguration().getIncludeGlobalPerms(), true, null);
|
||||
}
|
||||
|
||||
public Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups, List<String> possibleNodes) {
|
||||
@ -359,57 +521,6 @@ public abstract class PermissionHolder {
|
||||
return getLocalPermissions(server, null, excludedGroups, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the holders nodes into a Map of permissions to be applied on the platform
|
||||
* @param server the server
|
||||
* @param world the world
|
||||
* @param extraContext any extra context to filter by
|
||||
* @param includeGlobal whether to include global nodes
|
||||
* @param possibleNodes a list of possible permissions for resolving wildcards
|
||||
* @param applyGroups if inherited group permissions should be included
|
||||
* @return a map of permissions
|
||||
*/
|
||||
public Map<String, Boolean> getPermissions(String server, String world, Map<String, String> extraContext, boolean includeGlobal, List<String> possibleNodes, boolean applyGroups) {
|
||||
Map<String, Boolean> perms = new HashMap<>();
|
||||
SortedSet<Node> allNodes;
|
||||
|
||||
if (applyGroups) {
|
||||
allNodes = sort(getAllNodes(null), true);
|
||||
} else {
|
||||
allNodes = sort(nodes, true);
|
||||
}
|
||||
|
||||
for (Node node : allNodes) {
|
||||
if (!node.shouldApplyOnServer(server, includeGlobal, plugin.getConfiguration().getApplyRegex())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!node.shouldApplyOnWorld(world, includeGlobal, plugin.getConfiguration().getApplyRegex())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!node.shouldApplyWithContext(extraContext)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
perms.put(node.getPermission(), node.getValue());
|
||||
|
||||
if (plugin.getConfiguration().getApplyShorthand()) {
|
||||
node.resolveShorthand().stream()
|
||||
.filter(s -> !perms.containsKey(s))
|
||||
.forEach(s -> perms.put(s, node.getValue()));
|
||||
}
|
||||
|
||||
if (plugin.getConfiguration().getApplyWildcards()) {
|
||||
node.resolveWildcard(possibleNodes).stream()
|
||||
.filter(s -> !perms.containsKey(s))
|
||||
.forEach(s -> perms.put(s, node.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
return perms;
|
||||
}
|
||||
|
||||
public static SortedSet<Node> sort(Set<Node> toSort, boolean reversed) {
|
||||
TreeSet<Node> set = new TreeSet<>(reversed ? PRIORITY_COMPARATOR.reversed() : PRIORITY_COMPARATOR);
|
||||
set.addAll(toSort);
|
||||
@ -421,41 +532,35 @@ public abstract class PermissionHolder {
|
||||
|
||||
@Override
|
||||
public int compare(Node o1, Node o2) {
|
||||
if (takesPriority(o1, o2)) {
|
||||
return 1;
|
||||
if (o1.isOverride() != o2.isOverride()) {
|
||||
return o1.isOverride() ? 1 : -1;
|
||||
}
|
||||
|
||||
if (takesPriority(o2, o1)) {
|
||||
return -1;
|
||||
if (o1.isServerSpecific() != o2.isServerSpecific()) {
|
||||
return o1.isServerSpecific() ? 1 : -1;
|
||||
}
|
||||
|
||||
if (o1.isWorldSpecific() != o2.isWorldSpecific()) {
|
||||
return o1.isWorldSpecific() ? 1 : -1;
|
||||
}
|
||||
|
||||
if (o1.isTemporary() != o2.isTemporary()) {
|
||||
return o1.isTemporary() ? 1 : -1;
|
||||
}
|
||||
|
||||
if (o1.isWildcard() != o2.isWildcard()) {
|
||||
return o1.isWildcard() ? 1 : -1;
|
||||
}
|
||||
|
||||
if (o1.isTemporary()) {
|
||||
return o1.getSecondsTilExpiry() < o2.getSecondsTilExpiry() ? 1 : -1;
|
||||
}
|
||||
|
||||
if (o1.isWildcard()) {
|
||||
return o1.getWildcardLevel() > o2.getWildcardLevel() ? 1 : -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public boolean takesPriority(Node target, Node over) {
|
||||
if (target.isTemporary() && !over.isTemporary()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (target.isWorldSpecific() && !over.isWorldSpecific()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (target.isServerSpecific() && !over.isServerSpecific()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!target.isWildcard() && over.isWildcard()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (target.isWildcard() && over.isWildcard()) {
|
||||
if (target.getWildcardLevel() > over.getWildcardLevel()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -321,7 +321,7 @@ public class Group extends PermissionHolder implements Identifiable<String> {
|
||||
*/
|
||||
private List<String> getGroups(String server, String world, boolean includeGlobal) {
|
||||
// Call super #getPermissions method, and just sort through those
|
||||
Map<String, Boolean> perms = getPermissions(server, world, null, includeGlobal, null, true);
|
||||
Map<String, Boolean> perms = exportNodes(server, world, null, includeGlobal, true, null);
|
||||
return perms.keySet().stream()
|
||||
.filter(s -> Patterns.GROUP_MATCH.matcher(s).matches())
|
||||
.map(s -> Patterns.DOT.split(s, 2)[1])
|
||||
|
@ -28,7 +28,6 @@ import lombok.Cleanup;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
import me.lucko.luckperms.constants.Constants;
|
||||
import me.lucko.luckperms.core.PermissionHolder;
|
||||
import me.lucko.luckperms.data.Log;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.storage.Datastore;
|
||||
@ -188,7 +187,7 @@ public class FlatfileDatastore extends Datastore {
|
||||
writer.name("primaryGroup").value(user.getPrimaryGroup());
|
||||
writer.name("perms");
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, Boolean> e : convertToLegacy(user.getNodes()).entrySet()) {
|
||||
for (Map.Entry<String, Boolean> e : exportToLegacy(user.getNodes()).entrySet()) {
|
||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||
}
|
||||
writer.endObject();
|
||||
@ -229,7 +228,7 @@ public class FlatfileDatastore extends Datastore {
|
||||
writer.name("primaryGroup").value(user.getPrimaryGroup());
|
||||
writer.name("perms");
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, Boolean> e : convertToLegacy(user.getNodes()).entrySet()) {
|
||||
for (Map.Entry<String, Boolean> e : exportToLegacy(user.getNodes()).entrySet()) {
|
||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||
}
|
||||
writer.endObject();
|
||||
@ -295,7 +294,7 @@ public class FlatfileDatastore extends Datastore {
|
||||
writer.name("primaryGroup").value(user.getPrimaryGroup());
|
||||
writer.name("perms");
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, Boolean> e : convertToLegacy(user.getNodes()).entrySet()) {
|
||||
for (Map.Entry<String, Boolean> e : exportToLegacy(user.getNodes()).entrySet()) {
|
||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||
}
|
||||
writer.endObject();
|
||||
@ -323,7 +322,7 @@ public class FlatfileDatastore extends Datastore {
|
||||
writer.name("name").value(group.getName());
|
||||
writer.name("perms");
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, Boolean> e : convertToLegacy(group.getNodes()).entrySet()) {
|
||||
for (Map.Entry<String, Boolean> e : exportToLegacy(group.getNodes()).entrySet()) {
|
||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||
}
|
||||
writer.endObject();
|
||||
@ -415,7 +414,7 @@ public class FlatfileDatastore extends Datastore {
|
||||
writer.name("name").value(group.getName());
|
||||
writer.name("perms");
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, Boolean> e : convertToLegacy(group.getNodes()).entrySet()) {
|
||||
for (Map.Entry<String, Boolean> e : exportToLegacy(group.getNodes()).entrySet()) {
|
||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||
}
|
||||
writer.endObject();
|
||||
|
@ -31,7 +31,6 @@ import com.mongodb.client.MongoDatabase;
|
||||
import com.mongodb.client.model.InsertOneOptions;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
import me.lucko.luckperms.core.PermissionHolder;
|
||||
import me.lucko.luckperms.data.Log;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.groups.GroupManager;
|
||||
@ -46,7 +45,7 @@ import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static me.lucko.luckperms.core.PermissionHolder.convertToLegacy;
|
||||
import static me.lucko.luckperms.core.PermissionHolder.exportToLegacy;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class MongoDBDatastore extends Datastore {
|
||||
@ -430,7 +429,7 @@ public class MongoDBDatastore extends Datastore {
|
||||
.append("primaryGroup", user.getPrimaryGroup());
|
||||
|
||||
Document perms = new Document();
|
||||
for (Map.Entry<String, Boolean> e : convert(convertToLegacy(user.getNodes())).entrySet()) {
|
||||
for (Map.Entry<String, Boolean> e : convert(exportToLegacy(user.getNodes())).entrySet()) {
|
||||
perms.append(e.getKey(), e.getValue());
|
||||
}
|
||||
|
||||
@ -442,7 +441,7 @@ public class MongoDBDatastore extends Datastore {
|
||||
Document main = new Document("_id", group.getName());
|
||||
|
||||
Document perms = new Document();
|
||||
for (Map.Entry<String, Boolean> e : convert(convertToLegacy(group.getNodes())).entrySet()) {
|
||||
for (Map.Entry<String, Boolean> e : convert(exportToLegacy(group.getNodes())).entrySet()) {
|
||||
perms.append(e.getKey(), e.getValue());
|
||||
}
|
||||
|
||||
|
@ -330,7 +330,7 @@ public abstract class User extends PermissionHolder implements Identifiable<UUID
|
||||
*/
|
||||
private List<String> getGroups(String server, String world, boolean includeGlobal) {
|
||||
// Call super #getPermissions method, and just sort through those
|
||||
Map<String, Boolean> perms = getPermissions(server, world, null, includeGlobal, null, true);
|
||||
Map<String, Boolean> perms = exportNodes(server, world, null, includeGlobal, true, null);
|
||||
return perms.keySet().stream()
|
||||
.filter(s -> Patterns.GROUP_MATCH.matcher(s).matches())
|
||||
.map(s -> Patterns.DOT.split(s, 2)[1])
|
||||
|
@ -24,6 +24,7 @@ package me.lucko.luckperms.utils;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import lombok.*;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
|
||||
import java.util.*;
|
||||
@ -85,6 +86,9 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
@Getter
|
||||
private Boolean value;
|
||||
|
||||
@Getter
|
||||
private boolean override;
|
||||
|
||||
private String server = null;
|
||||
private String world = null;
|
||||
|
||||
@ -101,7 +105,7 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
* @param world the world this node applies on
|
||||
* @param extraContexts any additional contexts applying to this node
|
||||
*/
|
||||
public Node(String permission, boolean value, long expireAt, String server, String world, Map<String, String> extraContexts) {
|
||||
public Node(String permission, boolean value, boolean override, long expireAt, String server, String world, Map<String, String> extraContexts) {
|
||||
if (permission == null || permission.equals("")) {
|
||||
throw new IllegalArgumentException("Empty permission");
|
||||
}
|
||||
@ -120,6 +124,7 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
|
||||
this.permission = permission;
|
||||
this.value = value;
|
||||
this.override = override;
|
||||
this.expireAt = expireAt;
|
||||
this.server = server;
|
||||
this.world = world;
|
||||
@ -129,6 +134,11 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tristate getTristate() {
|
||||
return Tristate.fromBoolean(value);
|
||||
}
|
||||
|
||||
public boolean isNegated() {
|
||||
return !value;
|
||||
}
|
||||
@ -395,6 +405,53 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
return (int) getPermission().chars().filter(num -> num == Character.getNumericValue('.')).count();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equalsIgnoringValue(me.lucko.luckperms.api.Node other) {
|
||||
if (!other.getPermission().equalsIgnoreCase(this.getPermission())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (other.isTemporary() != this.isTemporary()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.isTemporary()) {
|
||||
if (other.getExpiryUnixTime() != this.getExpiryUnixTime()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (other.getServer().isPresent() != this.getServer().isPresent()) {
|
||||
if (other.getServer().isPresent()) {
|
||||
if (!other.getServer().get().equalsIgnoreCase(this.getServer().get())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (other.getWorld().isPresent() != this.getWorld().isPresent()) {
|
||||
if (other.getWorld().isPresent()) {
|
||||
if (!other.getWorld().get().equalsIgnoreCase(this.getWorld().get())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!other.getExtraContexts().equals(this.getExtraContexts())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (other.isTemporary() != this.isTemporary()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean almostEquals(me.lucko.luckperms.api.Node other) {
|
||||
if (!other.getPermission().equalsIgnoreCase(this.getPermission())) {
|
||||
@ -446,6 +503,7 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
public static class Builder implements me.lucko.luckperms.api.Node.Builder {
|
||||
private final String permission;
|
||||
private Boolean value = true;
|
||||
private boolean override = false;
|
||||
private String server = null;
|
||||
private String world = null;
|
||||
private long expireAt = 0L;
|
||||
@ -488,6 +546,12 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public me.lucko.luckperms.api.Node.Builder setOverride(boolean override) {
|
||||
this.override = override;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public me.lucko.luckperms.api.Node.Builder setExpiry(long expireAt) {
|
||||
this.expireAt = expireAt;
|
||||
@ -523,7 +587,7 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
|
||||
@Override
|
||||
public me.lucko.luckperms.api.Node build() {
|
||||
return new Node(permission, value, expireAt, server, world, extraContexts);
|
||||
return new Node(permission, value, override, expireAt, server, world, extraContexts);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,10 @@ import org.spongepowered.api.command.CommandException;
|
||||
import org.spongepowered.api.command.CommandResult;
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
import org.spongepowered.api.text.Text;
|
||||
import org.spongepowered.api.world.Location;
|
||||
import org.spongepowered.api.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@ -49,6 +52,15 @@ class SpongeCommand extends CommandManager implements CommandCallable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(CommandSource source, String s, @Nullable Location<World> location) throws CommandException {
|
||||
List<String> args = new ArrayList<>(Arrays.asList(Patterns.SPACE.split(s)));
|
||||
if (s.endsWith(" ")) {
|
||||
args.add("");
|
||||
}
|
||||
|
||||
return onTabComplete(SpongeSenderFactory.get().wrap(source), args);
|
||||
}
|
||||
|
||||
public List<String> getSuggestions(CommandSource source, String s) throws CommandException {
|
||||
List<String> args = new ArrayList<>(Arrays.asList(Patterns.SPACE.split(s)));
|
||||
if (s.endsWith(" ")) {
|
||||
@ -64,12 +76,12 @@ class SpongeCommand extends CommandManager implements CommandCallable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<? extends Text> getShortDescription(CommandSource source) {
|
||||
public Optional<Text> getShortDescription(CommandSource source) {
|
||||
return Optional.of(Text.of("LuckPerms main command."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<? extends Text> getHelp(CommandSource source) {
|
||||
public Optional<Text> getHelp(CommandSource source) {
|
||||
return Optional.of(Text.of("Type /perms for help."));
|
||||
}
|
||||
|
||||
|
@ -25,10 +25,7 @@ package me.lucko.luckperms;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.AbstractListener;
|
||||
import org.spongepowered.api.entity.Entity;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.event.Listener;
|
||||
import org.spongepowered.api.event.entity.DisplaceEntityEvent;
|
||||
import org.spongepowered.api.event.network.ClientConnectionEvent;
|
||||
import org.spongepowered.api.profile.GameProfile;
|
||||
import org.spongepowered.api.text.serializer.TextSerializers;
|
||||
@ -75,8 +72,10 @@ public class SpongeListener extends AbstractListener {
|
||||
refreshPlayer(e.getTargetEntity().getUniqueId());
|
||||
}
|
||||
|
||||
// TODO Use reflection/any other method to refresh on world change
|
||||
/*
|
||||
@Listener
|
||||
public void onPlayerTeleport(DisplaceEntityEvent.Teleport e) {
|
||||
public void onPlayerTeleport(DisplaceEntityEvent e) {
|
||||
final Entity entity = e.getTargetEntity();
|
||||
if (!(entity instanceof Player)){
|
||||
return;
|
||||
@ -84,6 +83,7 @@ public class SpongeListener extends AbstractListener {
|
||||
|
||||
refreshPlayer(entity.getUniqueId());
|
||||
}
|
||||
*/
|
||||
|
||||
@Listener
|
||||
public void onClientLeave(ClientConnectionEvent.Disconnect e) {
|
||||
|
@ -83,4 +83,9 @@ public class GroupCollection implements SubjectCollection {
|
||||
.map(sub -> new AbstractMap.SimpleEntry<Subject, Boolean>(sub, sub.getPermissionValue(contexts, node).asBoolean()))
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Subject getDefaults() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -101,4 +101,9 @@ public class UserCollection implements SubjectCollection {
|
||||
.map(sub -> new AbstractMap.SimpleEntry<Subject, Boolean>(sub, sub.getPermissionValue(contexts, node).asBoolean()))
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Subject getDefaults() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user