556 lines
20 KiB
Java
556 lines
20 KiB
Java
package fr.pandacube.lib.permissions;
|
|
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Objects;
|
|
import java.util.OptionalLong;
|
|
import java.util.Set;
|
|
import java.util.stream.LongStream;
|
|
|
|
import fr.pandacube.lib.chat.ChatTreeNode;
|
|
import fr.pandacube.lib.permissions.PermissionExpressionParser.LitteralPermissionTester;
|
|
import fr.pandacube.lib.permissions.PermissionsCachedBackendReader.CachedEntity;
|
|
import fr.pandacube.lib.permissions.SQLPermissions.EntityType;
|
|
import fr.pandacube.lib.util.Log;
|
|
|
|
/**
|
|
* Represents an entity in the permission system, either a group or a player.
|
|
*/
|
|
public sealed abstract class PermEntity permits PermPlayer, PermGroup {
|
|
/* package */ final String name;
|
|
/* package */ final EntityType type;
|
|
/* package */ PermEntity(String n, EntityType t) {
|
|
name = n; type = t;
|
|
}
|
|
|
|
/* package */ abstract CachedEntity getBackendEntity();
|
|
|
|
/**
|
|
* Gets all the groups this entity inherits from.
|
|
* @return a list of all the groups this entity inherits from.
|
|
*/
|
|
public abstract List<PermGroup> getInheritances();
|
|
/**
|
|
* Gets all the group names this entity inherits from.
|
|
* @return a list of all the group names this entity inherits from.
|
|
*/
|
|
public abstract List<String> getInheritancesString();
|
|
/**
|
|
* Gets the name of this entity.
|
|
* @return the name of this entity.
|
|
*/
|
|
public abstract String getName();
|
|
|
|
/**
|
|
* Gets the name of this entity, as it is stored in the database.
|
|
* @return the name of this entity, as it is stored in the database.
|
|
*/
|
|
public String getInternalName() {
|
|
return name;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Tells if the current entity inherits directly or indirectly from the specified group.
|
|
* @param group the group to search for
|
|
* @param recursive true to search in the inheritance tree, or false to search only in the inheritance list of the current entity.
|
|
* @return true if the current entity inherits directly or indirectly from the specified group, false otherwise.
|
|
*/
|
|
public boolean inheritsFromGroup(String group, boolean recursive) {
|
|
if (group == null)
|
|
return false;
|
|
return getInheritances().stream().anyMatch(g -> g.name.equals(group) || (recursive && g.inheritsFromGroup(group, true)));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Gets the effective prefix of this entity.
|
|
* It is either the prefix defined directly for this entity, or from inheritance.
|
|
* @return the effective prefix of this entity.
|
|
*/
|
|
public String getPrefix() {
|
|
return Permissions.resolver.getEffectivePrefix(name, type);
|
|
}
|
|
|
|
/**
|
|
* Gets the prefix defined directly for this entity.
|
|
* @return the prefix defined directly for this entity.
|
|
*/
|
|
public String getSelfPrefix() {
|
|
return getBackendEntity().getSelfPrefix();
|
|
}
|
|
|
|
/**
|
|
* Provides informations on how the effective prefix of this entity is determined.
|
|
* @return a {@link ChatTreeNode} providing informations on how the effective prefix of this entity is determined.
|
|
*/
|
|
public ChatTreeNode debugPrefix() {
|
|
return Permissions.resolver.debugPrefix(name, type);
|
|
}
|
|
|
|
/**
|
|
* Sets the prefix of this entity.
|
|
* @param prefix the prefix for this entity.
|
|
*/
|
|
public void setSelfPrefix(String prefix) {
|
|
Permissions.backendWriter.setSelfPrefix(name, type, prefix);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Gets the effective suffix of this entity.
|
|
* It is either the suffix defined directly for this entity, or from inheritance.
|
|
* @return the effective suffix of this entity.
|
|
*/
|
|
public String getSuffix() {
|
|
return Permissions.resolver.getEffectiveSuffix(name, type);
|
|
}
|
|
|
|
/**
|
|
* Gets the suffix defined directly for this entity.
|
|
* @return the suffix defined directly for this entity.
|
|
*/
|
|
public String getSelfSuffix() {
|
|
return getBackendEntity().getSelfSuffix();
|
|
}
|
|
|
|
/**
|
|
* Provides informations on how the effective suffix of this entity is determined.
|
|
* @return a {@link ChatTreeNode} providing informations on how the effective suffix of this entity is determined.
|
|
*/
|
|
public ChatTreeNode debugSuffix() {
|
|
return Permissions.resolver.debugSuffix(name, type);
|
|
}
|
|
|
|
/**
|
|
* Sets the suffix of this entity.
|
|
* @param suffix the suffix for this entity.
|
|
*/
|
|
public void setSelfSuffix(String suffix) {
|
|
Permissions.backendWriter.setSelfSuffix(name, type, suffix);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Gets the effective list of permissions that applies to this entity out of a specific server and world.
|
|
* It is either the permissions defined directly for this entity, or from inheritance as long as they are not
|
|
* overriden.
|
|
* @return the effective list of permissions that applies to this entity out of a specific server and world.
|
|
*/
|
|
public Map<String, Boolean> listEffectivePermissions() {
|
|
return listEffectivePermissions(null, null);
|
|
}
|
|
|
|
/**
|
|
* Gets the effective list of permissions that applies to this entity on a specific server.
|
|
* It is either the permissions defined directly for this entity, or from inheritance as long as they are not
|
|
* overriden.
|
|
* @param server the server where the returned permissions apply for this entity.
|
|
* @return the effective list of permissions that applies to this entity on a specific server.
|
|
*/
|
|
public Map<String, Boolean> listEffectivePermissions(String server) {
|
|
return listEffectivePermissions(server, null);
|
|
}
|
|
|
|
/**
|
|
* Gets the effective list of permissions that applies to this entity on a specific server and world.
|
|
* It is either the permissions defined directly for this entity, or from inheritance as long as they are not
|
|
* overriden.
|
|
* @param server the server containing the world where the returned permissions apply for this entity.
|
|
* @param world the world in the server where the returned permissions apply for this entity.
|
|
* @return the effective list of permissions that applies to this entity on a specific server and world.
|
|
*/
|
|
public Map<String, Boolean> listEffectivePermissions(String server, String world) {
|
|
return Permissions.resolver.getEffectivePermissionList(name, type, server, world);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Gets the effective values of the provided permission range prefix that applies to this entity out of a specific
|
|
* server and world.
|
|
* It is either the range values defined directly for this entity, or from inheritance as long as they are not
|
|
* overriden.
|
|
* @param permissionPrefix the permission range prefix.
|
|
* @return the effective values of the provided permission range prefix that applies to this entity out of a
|
|
* specific server and world.
|
|
*/
|
|
public LongStream getPermissionRangeValues(String permissionPrefix) {
|
|
return getPermissionRangeValues(permissionPrefix, null, null);
|
|
}
|
|
|
|
/**
|
|
* Gets the effective values of the provided permission range prefix that applies to this entity on a specific
|
|
* server.
|
|
* It is either the range values defined directly for this entity, or from inheritance as long as they are not
|
|
* overriden.
|
|
* @param permissionPrefix the permission range prefix.
|
|
* @param server the server where the returned values apply for this entity.
|
|
* @return the effective values of the provided permission range prefix that applies to this entity on a specific
|
|
* server.
|
|
*/
|
|
public LongStream getPermissionRangeValues(String permissionPrefix, String server) {
|
|
return getPermissionRangeValues(permissionPrefix, server, null);
|
|
}
|
|
|
|
/**
|
|
* Gets the effective values of the provided permission range prefix that applies to this entity on a specific
|
|
* server and world.
|
|
* It is either the range values defined directly for this entity, or from inheritance as long as they are not
|
|
* overriden.
|
|
* @param permissionPrefix the permission range prefix.
|
|
* @param server the server containing the world where the returned values apply for this entity.
|
|
* @param world the world in the server where the returned values apply for this entity.
|
|
* @return the effective values of the provided permission range prefix that applies to this entity on a specific
|
|
* server and world.
|
|
*/
|
|
public LongStream getPermissionRangeValues(String permissionPrefix, String server, String world) {
|
|
String prefixWithEndingDot = permissionPrefix.endsWith(".") ? permissionPrefix : (permissionPrefix + ".");
|
|
int prefixLength = prefixWithEndingDot.length();
|
|
return listEffectivePermissions(server, world).entrySet().stream()
|
|
.filter(Map.Entry::getValue) // permission must be positive
|
|
.map(Map.Entry::getKey) // keep only the permission node (key), since the value is always true
|
|
.filter(p -> p.startsWith(prefixWithEndingDot)) // keep only relevant permissions
|
|
.map(p -> p.substring(prefixLength)) // keep only what is after the prefix
|
|
.map(suffix -> { // convert to long
|
|
try {
|
|
return Long.parseLong(suffix);
|
|
}
|
|
catch (NumberFormatException e) {
|
|
return null;
|
|
}
|
|
})
|
|
.filter(Objects::nonNull)
|
|
.mapToLong(longSuffix -> longSuffix)
|
|
.sorted();
|
|
}
|
|
|
|
|
|
/**
|
|
* Gets the maximum effective value of the provided permission range prefix that applies to this entity out of a
|
|
* specific server and world.
|
|
* It is either the range values defined directly for this entity, or from inheritance as long as they are not
|
|
* overriden.
|
|
* @param permissionPrefix the permission range prefix.
|
|
* @return the maximum effective value of the provided permission range prefix that applies to this entity out of a
|
|
* specific server and world.
|
|
*/
|
|
public OptionalLong getPermissionRangeMax(String permissionPrefix) {
|
|
return getPermissionRangeMax(permissionPrefix, null, null);
|
|
}
|
|
|
|
/**
|
|
* Gets the maximum effective value of the provided permission range prefix that applies to this entity on a
|
|
* specific server.
|
|
* It is either the range values defined directly for this entity, or from inheritance as long as they are not
|
|
* overriden.
|
|
* @param permissionPrefix the permission range prefix.
|
|
* @param server the server where the returned value applies for this entity.
|
|
* @return the maximum effective value of the provided permission range prefix that applies to this entity on a
|
|
* specific server.
|
|
*/
|
|
public OptionalLong getPermissionRangeMax(String permissionPrefix, String server) {
|
|
return getPermissionRangeMax(permissionPrefix, server, null);
|
|
}
|
|
|
|
/**
|
|
* Gets the maximum effective value of the provided permission range prefix that applies to this entity on a
|
|
* specific server and world.
|
|
* It is either the range values defined directly for this entity, or from inheritance as long as they are not
|
|
* overriden.
|
|
* @param permissionPrefix the permission range prefix.
|
|
* @param server the server containing the world where the returned value applies for this entity.
|
|
* @param world the world in the server where the returned value applies for this entity.
|
|
* @return the maximum effective value of the provided permission range prefix that applies to this entity on a
|
|
* specific server and world.
|
|
*/
|
|
public OptionalLong getPermissionRangeMax(String permissionPrefix, String server, String world) {
|
|
return getPermissionRangeValues(permissionPrefix, server, world).max();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Tells if this entity has the provided permission out of a specific server and world.
|
|
* It is either based on the permissions defined directly for this entity, or from inheritance as long as they are
|
|
* not overriden.
|
|
* @param permission the permission to ckeck on this entity.
|
|
* @return true if this entity has the permission, false if it is negated, or null if not known.
|
|
*/
|
|
public Boolean hasPermission(String permission) {
|
|
return hasPermission(permission, null, null);
|
|
}
|
|
|
|
/**
|
|
* Tells if this entity has the provided permission on a specitif server.
|
|
* It is either based on the permissions defined directly for this entity, or from inheritance as long as they are
|
|
* not overriden. It also consider permissions that apply on any server.
|
|
* @param permission the permission to ckeck on this entity.
|
|
* @param server the server in which to test the permission for this entity.
|
|
* @return true if this entity has the permission, false if it is negated, or null if not known.
|
|
*/
|
|
public Boolean hasPermission(String permission, String server) {
|
|
return hasPermission(permission, server, null);
|
|
}
|
|
|
|
/**
|
|
* Tells if this entity has the provided permission on a specitif server and world.
|
|
* It is either based on the permissions defined directly for this entity, or from inheritance as long as they are
|
|
* not overriden. It also consider permissions that apply on any world of that server, and then any server.
|
|
* @param permission the permission to ckeck on this entity.
|
|
* @param server the server in which to test the permission for this entity.
|
|
* @param world the world in which to test the permission for this entity.
|
|
* @return true if this entity has the permission, false if it is negated, or null if not known.
|
|
*/
|
|
public Boolean hasPermission(String permission, String server, String world) {
|
|
Boolean ret = Permissions.resolver.getEffectivePermission(name, type, permission, server, world);
|
|
Log.debug("[Perm] For " + type.toString().toLowerCase() + " " + getName() + ", '" + permission + "' is " + ret);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Tells if this entity has the provided permission on a specitif server and world.
|
|
* It is either based on the permissions defined directly for this entity, or from inheritance as long as they are
|
|
* not overriden.
|
|
* @param permission the permission to ckeck on this entity.
|
|
* @param server the server in which to test the permission for this entity.
|
|
* @param world the world in which to test the permission for this entity.
|
|
* @param deflt the default value is the permission is undefined for this entity.
|
|
* @return true if this entity has the permission, false if it is negated, or {@code deflt} if not known.
|
|
*/
|
|
public boolean hasPermissionOr(String permission, String server, String world, boolean deflt) {
|
|
Boolean ret = hasPermission(permission, server, world);
|
|
return ret != null ? ret : deflt;
|
|
}
|
|
|
|
/**
|
|
* Evaluates the provided permission expression for this entity.
|
|
* It uses {@link #hasPermissionOr(String, String, String, boolean)} with {@code false} as a default value, to check
|
|
* each permission nodes individualy.
|
|
* @param permExpression the permission expression to evaluate on this entity.
|
|
* @param server the server in which to test the permission expression for this entity.
|
|
* @param world the world in which to test the permission expression for this entity.
|
|
* @return true if this the permission expression evaluates to true, false otherwise.
|
|
* @see PermissionExpressionParser#evaluate(String, LitteralPermissionTester)
|
|
*/
|
|
public boolean hasPermissionExpression(String permExpression, String server, String world) {
|
|
return PermissionExpressionParser.evaluate(permExpression, p -> hasPermissionOr(p, server, world, false));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Provides informations on how the effective permission of this entity on the provided permission node is
|
|
* determined.
|
|
* @param permission the permission node to debug on this entity.
|
|
* @return a {@link ChatTreeNode} providing informations on how the effective permission is determined.
|
|
*/
|
|
public ChatTreeNode debugPermission(String permission) {
|
|
return debugPermission(permission, null, null);
|
|
}
|
|
|
|
/**
|
|
* Provides informations on how the effective permission of this entity on the provided permission node is
|
|
* determined.
|
|
* @param permission the permission node to debug on this entity.
|
|
* @param server the server in which to test the permission for this entity.
|
|
* @return a {@link ChatTreeNode} providing informations on how the effective permission is determined.
|
|
*/
|
|
public ChatTreeNode debugPermission(String permission, String server) {
|
|
return debugPermission(permission, server, null);
|
|
}
|
|
|
|
/**
|
|
* Provides informations on how the effective permission of this entity on the provided permission node is
|
|
* determined.
|
|
* @param permission the permission node to debug on this entity.
|
|
* @param server the server in which to test the permission for this entity.
|
|
* @param world the world in which to test the permission for this entity.
|
|
* @return a {@link ChatTreeNode} providing informations on how the effective permission is determined.
|
|
*/
|
|
public ChatTreeNode debugPermission(String permission, String server, String world) {
|
|
return Permissions.resolver.debugPermission(name, type, permission, server, world);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Adds the provided permission node to this entity that apply on any server.
|
|
* @param permission the permission node to add.
|
|
* @throws IllegalStateException if the permission is already set.
|
|
*/
|
|
public void addSelfPermission(String permission) {
|
|
addSelfPermission(permission, null, null);
|
|
}
|
|
|
|
/**
|
|
* Adds the provided permission node to this entity that apply on the provided server.
|
|
* @param permission the permission node to add.
|
|
* @param server the server in which to apply the permission.
|
|
* @throws IllegalStateException if the permission is already set.
|
|
*/
|
|
public void addSelfPermission(String permission, String server) {
|
|
addSelfPermission(permission, server, null);
|
|
}
|
|
|
|
/**
|
|
* Adds the provided permission node to this entity that apply on the provided server and world.
|
|
* @param permission the permission node to add.
|
|
* @param server the server in which to apply the permission.
|
|
* @param world the world in which to apply the permission.
|
|
* @throws IllegalStateException if the permission is already set.
|
|
*/
|
|
public void addSelfPermission(String permission, String server, String world) {
|
|
Permissions.backendWriter.addSelfPermission(name, type, permission, server, world);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Removes the provided permission node from this entity that applied on any server.
|
|
* @param permission the permission node to add.
|
|
* @throws IllegalStateException if the permission was not set.
|
|
*/
|
|
public void removeSelfPermission(String permission) {
|
|
removeSelfPermission(permission, null, null);
|
|
}
|
|
|
|
/**
|
|
* Removes the provided permission node from this entity that applied on the provided server.
|
|
* @param permission the permission node to remove.
|
|
* @param server the server from which to remove the permission.
|
|
* @throws IllegalStateException if the permission was not set.
|
|
*/
|
|
public void removeSelfPermission(String permission, String server) {
|
|
removeSelfPermission(permission, server, null);
|
|
}
|
|
|
|
/**
|
|
* Removes the provided permission node from this entity that applied on the provided server and world.
|
|
* @param permission the permission node to remove.
|
|
* @param server the server from which to remove the permission.
|
|
* @param world the world from which to remove the permission.
|
|
* @throws IllegalStateException if the permission was not set.
|
|
*/
|
|
public void removeSelfPermission(String permission, String server, String world) {
|
|
Permissions.backendWriter.removeSelfPermission(name, type, permission, server, world);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Counts the number of self permission nodes for this entity.
|
|
* @return the number of self permission nodes for this entity.
|
|
*/
|
|
public int getSelfPermissionsCount() {
|
|
return getSelfPermissionsServerWorldKeys().stream()
|
|
.mapToInt(key -> getSelfPermissions(key.server(), key.world()).size())
|
|
.sum();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Gets all the server/world attribution that have at least one self permission for this entity.
|
|
* @return all the server/world attribution that have at least one self permission for this entity.
|
|
*/
|
|
public Set<ServerWorldKey> getSelfPermissionsServerWorldKeys() {
|
|
return getBackendEntity().getSelfPermissionsServerWorldKeys();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Gets all the self permission nodes that apply everywhere for this entity.
|
|
* @return all the self permission nodes that apply everywhere for this entity.
|
|
*/
|
|
public List<String> getSelfPermissions() {
|
|
return getSelfPermissions(null, null);
|
|
}
|
|
|
|
/**
|
|
* Gets all the self permission nodes that apply on the provided server for this entity.
|
|
* @param server the server from which to get the permissions.
|
|
* @return all the self permission nodes that apply on the provided server for this entity.
|
|
*/
|
|
public List<String> getSelfPermissions(String server) {
|
|
return getSelfPermissions(server, null);
|
|
}
|
|
|
|
/**
|
|
* Gets all the self permission nodes that apply on the provided server and world for this entity.
|
|
* @param server the server from which to get the permissions.
|
|
* @param world the world from which to get the permissions.
|
|
* @return all the self permission nodes that apply on the provided server and world for this entity.
|
|
*/
|
|
public List<String> getSelfPermissions(String server, String world) {
|
|
return getBackendEntity().getSelfPermissions(server, world);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
public boolean equals(Object obj) {
|
|
return obj instanceof PermEntity o
|
|
&& Objects.equals(name, o.name)
|
|
&& type == o.type;
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(name, type);
|
|
}
|
|
|
|
} |