Disallow empty permission node (#2966)

This commit is contained in:
Luck 2021-04-05 18:29:36 +01:00
parent d150bd39a5
commit c2231bcc2e
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
21 changed files with 107 additions and 31 deletions

View File

@ -67,6 +67,10 @@ public class PermissionSet extends GenericChildCommand {
boolean value = args.getBooleanOrInsert(1, true);
MutableContextSet context = args.getContextOrDefault(2, plugin);
if (node.isEmpty()) {
Message.PERMISSION_INVALID_ENTRY_EMPTY.send(sender);
}
if (ArgumentPermissions.checkContext(plugin, sender, permission, context) ||
ArgumentPermissions.checkGroup(plugin, sender, target, context) ||
ArgumentPermissions.checkArguments(plugin, sender, permission, node)) {

View File

@ -72,6 +72,10 @@ public class PermissionSetTemp extends GenericChildCommand {
TemporaryNodeMergeStrategy modifier = args.getTemporaryModifierAndRemove(3).orElseGet(() -> plugin.getConfiguration().get(ConfigKeys.TEMPORARY_ADD_BEHAVIOUR));
MutableContextSet context = args.getContextOrDefault(3, plugin);
if (node.isEmpty()) {
Message.PERMISSION_INVALID_ENTRY_EMPTY.send(sender);
}
if (ArgumentPermissions.checkContext(plugin, sender, permission, context) ||
ArgumentPermissions.checkGroup(plugin, sender, target, context) ||
ArgumentPermissions.checkArguments(plugin, sender, permission, node)) {

View File

@ -66,6 +66,10 @@ public class PermissionUnset extends GenericChildCommand {
String node = args.get(0);
MutableContextSet context = args.getContextOrDefault(1, plugin);
if (node.isEmpty()) {
Message.PERMISSION_INVALID_ENTRY_EMPTY.send(sender);
}
if (ArgumentPermissions.checkContext(plugin, sender, permission, context) ||
ArgumentPermissions.checkGroup(plugin, sender, target, context) ||
ArgumentPermissions.checkArguments(plugin, sender, permission, node)) {

View File

@ -69,6 +69,10 @@ public class PermissionUnsetTemp extends GenericChildCommand {
int fromIndex = duration == null ? 1 : 2;
MutableContextSet context = args.getContextOrDefault(fromIndex, plugin);
if (node.isEmpty()) {
Message.PERMISSION_INVALID_ENTRY_EMPTY.send(sender);
}
if (ArgumentPermissions.checkContext(plugin, sender, permission, context) ||
ArgumentPermissions.checkGroup(plugin, sender, target, context) ||
ArgumentPermissions.checkArguments(plugin, sender, permission, node)) {

View File

@ -34,7 +34,7 @@ import me.lucko.luckperms.common.command.utils.ArgumentList;
import me.lucko.luckperms.common.context.contextset.ImmutableContextSetImpl;
import me.lucko.luckperms.common.locale.Message;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.node.factory.NodeBuilders;
import me.lucko.luckperms.common.node.types.Permission;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.util.Predicates;
@ -75,7 +75,7 @@ public class LogNotify extends ChildCommand<Log> {
if (state) {
// add the perm
user.setNode(DataType.NORMAL, NodeBuilders.determineMostApplicable(IGNORE_NODE).build(), true);
user.setNode(DataType.NORMAL, Permission.builder().permission(IGNORE_NODE).build(), true);
} else {
// remove the perm
user.removeIf(DataType.NORMAL, ImmutableContextSetImpl.EMPTY, n -> n.getKey().equalsIgnoreCase(IGNORE_NODE), false);

View File

@ -1959,6 +1959,13 @@ public interface Message {
.append(FULL_STOP)
);
Args0 PERMISSION_INVALID_ENTRY_EMPTY = () -> prefixed(translatable()
// "&cThe empty string is not a valid permission."
.key("luckperms.command.misc.permission-invalid-empty")
.color(RED)
.append(FULL_STOP)
);
Args3<PermissionHolder, Group, ContextSet> SET_INHERIT_SUCCESS = (holder, parent, context) -> prefixed(translatable()
// "&b{}&a now inherits permissions from &b{}&a in context {}&a."
.key("luckperms.command.generic.parent.add")

View File

@ -138,4 +138,10 @@ public abstract class AbstractNodeBuilder<N extends ScopedNode<N, B>, B extends
return (B) this;
}
protected static void ensureDefined(Object value, String description) {
if (value == null) {
throw new IllegalStateException(description + " has not been defined");
}
}
}

View File

@ -46,6 +46,8 @@ import net.luckperms.api.node.types.WeightNode;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Objects;
public final class NodeBuilders {
private NodeBuilders() {}
@ -60,6 +62,7 @@ public final class NodeBuilders {
private static final Parser<?>[] PARSERS = new Parser[]{INHERITANCE, PREFIX, SUFFIX, META, WEIGHT, DISPLAY_NAME, REGEX_PERMISSION};
public static @NonNull NodeBuilder<?, ?> determineMostApplicable(String key) {
Objects.requireNonNull(key, "key");
for (Parser<?> parser : PARSERS) {
NodeBuilder<?, ?> builder = parser.parse(key);
if (builder != null) {

View File

@ -94,13 +94,13 @@ public class DisplayName extends AbstractNode<DisplayNameNode, DisplayNameNode.B
@Override
public @NonNull Builder displayName(@NonNull String displayName) {
this.displayName = displayName;
this.displayName = Objects.requireNonNull(displayName, "displayName");
return this;
}
@Override
public @NonNull DisplayName build() {
Objects.requireNonNull(this.displayName, "displayName");
ensureDefined(this.displayName, "display name");
return new DisplayName(this.displayName, this.value, this.expireAt, this.context.build(), this.metadata);
}
}

View File

@ -108,7 +108,7 @@ public class Inheritance extends AbstractNode<InheritanceNode, InheritanceNode.B
@Override
public @NonNull Inheritance build() {
Objects.requireNonNull(this.groupName, "groupName");
ensureDefined(this.groupName, "group");
return new Inheritance(this.groupName, this.value, this.expireAt, this.context.build(), this.metadata);
}
}

View File

@ -115,7 +115,11 @@ public class Meta extends AbstractNode<MetaNode, MetaNode.Builder> implements Me
@Override
public @NonNull Builder key(@NonNull String key) {
this.metaKey = Objects.requireNonNull(key, "key");
Objects.requireNonNull(key, "key");
if (key.isEmpty()) {
throw new IllegalArgumentException("key is empty");
}
this.metaKey = key;
return this;
}
@ -127,8 +131,8 @@ public class Meta extends AbstractNode<MetaNode, MetaNode.Builder> implements Me
@Override
public @NonNull Meta build() {
Objects.requireNonNull(this.metaKey, "metaKey");
Objects.requireNonNull(this.metaValue, "metaValue");
ensureDefined(this.metaKey, "meta key");
ensureDefined(this.metaValue, "meta value");
return new Meta(this.metaKey, this.metaValue, this.value, this.expireAt, this.context.build(), this.metadata);
}
}

View File

@ -87,13 +87,17 @@ public class Permission extends AbstractNode<PermissionNode, PermissionNode.Buil
@Override
public @NonNull Builder permission(@NonNull String permission) {
this.permission = Objects.requireNonNull(permission, "permission");
Objects.requireNonNull(permission, "permission");
if (permission.isEmpty()) {
throw new IllegalArgumentException("permission string is empty");
}
this.permission = permission;
return this;
}
@Override
public @NonNull Permission build() {
Objects.requireNonNull(this.permission, "permission");
ensureDefined(this.permission, "permission");
NodeBuilder<?, ?> testBuilder = NodeBuilders.determineMostApplicable(this.permission);
if (!(testBuilder instanceof Builder)) {

View File

@ -125,7 +125,7 @@ public class Prefix extends AbstractNode<PrefixNode, PrefixNode.Builder> impleme
@Override
public @NonNull Builder prefix(@NonNull String prefix) {
this.prefix = prefix;
this.prefix = Objects.requireNonNull(prefix, "prefix");
return this;
}
@ -137,8 +137,8 @@ public class Prefix extends AbstractNode<PrefixNode, PrefixNode.Builder> impleme
@Override
public @NonNull Prefix build() {
Objects.requireNonNull(this.prefix, "prefix");
Objects.requireNonNull(this.priority, "priority");
ensureDefined(this.prefix, "prefix");
ensureDefined(this.priority, "priority");
return new Prefix(this.prefix, this.priority, this.value, this.expireAt, this.context.build(), this.metadata);
}
}

View File

@ -106,19 +106,22 @@ public class RegexPermission extends AbstractNode<RegexPermissionNode, RegexPerm
@Override
public @NonNull Builder pattern(@NonNull String pattern) {
this.pattern = Objects.requireNonNull(pattern, "pattern");
Objects.requireNonNull(pattern, "pattern");
if (pattern.isEmpty()) {
throw new IllegalArgumentException("pattern is empty");
}
this.pattern = pattern;
return this;
}
@Override
public @NonNull Builder pattern(@NonNull Pattern pattern) {
this.pattern = Objects.requireNonNull(pattern, "pattern").pattern();
return this;
return pattern(Objects.requireNonNull(pattern, "pattern").pattern());
}
@Override
public @NonNull RegexPermission build() {
Objects.requireNonNull(this.pattern, "pattern");
ensureDefined(this.pattern, "pattern");
return new RegexPermission(this.pattern, this.value, this.expireAt, this.context.build(), this.metadata);
}
}

View File

@ -126,7 +126,7 @@ public class Suffix extends AbstractNode<SuffixNode, SuffixNode.Builder> impleme
@Override
public @NonNull Builder suffix(@NonNull String suffix) {
this.suffix = suffix;
this.suffix = Objects.requireNonNull(suffix, "suffix");
return this;
}
@ -138,8 +138,8 @@ public class Suffix extends AbstractNode<SuffixNode, SuffixNode.Builder> impleme
@Override
public @NonNull Suffix build() {
Objects.requireNonNull(this.suffix, "suffix");
Objects.requireNonNull(this.priority, "priority");
ensureDefined(this.suffix, "suffix");
ensureDefined(this.priority, "priority");
return new Suffix(this.suffix, this.priority, this.value, this.expireAt, this.context.build(), this.metadata);
}
}

View File

@ -36,7 +36,6 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Map;
import java.util.Objects;
public class Weight extends AbstractNode<WeightNode, WeightNode.Builder> implements WeightNode {
public static final String NODE_KEY = "weight";
@ -105,7 +104,7 @@ public class Weight extends AbstractNode<WeightNode, WeightNode.Builder> impleme
@Override
public @NonNull Weight build() {
Objects.requireNonNull(this.weight, "weight");
ensureDefined(this.weight, "weight");
return new Weight(this.weight, this.value, this.expireAt, this.context.build(), this.metadata);
}
}

View File

@ -75,9 +75,15 @@ public class NodeJsonSerializer {
JsonObject attributes = ent.getAsJsonObject();
String key = attributes.get("key").getAsString();
boolean value = attributes.get("value").getAsBoolean();
NodeBuilder<?, ?> builder = NodeBuilders.determineMostApplicable(key).value(value);
if (key.isEmpty()) {
continue; // skip
}
NodeBuilder<?, ?> builder = NodeBuilders.determineMostApplicable(key);
boolean value = attributes.get("value").getAsBoolean();
builder.value(value);
if (attributes.has("expiry")) {
builder.expiry(attributes.get("expiry").getAsLong());

View File

@ -432,7 +432,7 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio
String permission = entry.getKey().toString();
ConfigurationNode attributes = entry.getValue();
if (!permission.equals(keyFieldName)) {
if (!permission.equals(keyFieldName) && !permission.isEmpty()) {
return new NodeEntry(permission, attributes);
}
}
@ -440,7 +440,7 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio
// assume 'configNode' is the actual entry.
String permission = children.get(keyFieldName).getString(null);
if (permission == null) {
if (permission == null || permission.isEmpty()) {
return null;
}
@ -452,7 +452,7 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio
for (ConfigurationNode appended : data.getNode("permissions").getChildrenList()) {
String plainValue = appended.getValue(Types::strictAsString);
if (plainValue != null) {
if (plainValue != null && !plainValue.isEmpty()) {
nodes.add(NodeBuilders.determineMostApplicable(plainValue).build());
continue;
}

View File

@ -605,7 +605,10 @@ public class MongoStorage implements StorageImplementation {
//noinspection unchecked
List<Document> permsList = (List<Document>) document.get("permissions");
for (Document d : permsList) {
nodes.add(nodeFromDoc(d));
Node node = nodeFromDoc(d);
if (node != null) {
nodes.add(node);
}
}
}
return nodes;
@ -644,6 +647,10 @@ public class MongoStorage implements StorageImplementation {
private static Node nodeFromDoc(Document document) {
String key = document.containsKey("permission") ? document.getString("permission") : document.getString("key");
if (key == null || key.isEmpty()) {
return null;
}
NodeBuilder<?, ?> builder = NodeBuilders.determineMostApplicable(key)
.value(document.getBoolean("value", true));

View File

@ -410,6 +410,9 @@ public class SqlStorage implements StorageImplementation {
while (rs.next()) {
UUID holder = UUID.fromString(rs.getString("uuid"));
Node node = readNode(rs);
if (node == null) {
continue;
}
N match = constraint.filterConstraintMatch(node);
if (match != null) {
@ -511,6 +514,9 @@ public class SqlStorage implements StorageImplementation {
while (rs.next()) {
String holder = rs.getString("name");
Node node = readNode(rs);
if (node == null) {
continue;
}
N match = constraint.filterConstraintMatch(node);
if (match != null) {
@ -721,6 +727,11 @@ public class SqlStorage implements StorageImplementation {
private static Node readNode(ResultSet rs) throws SQLException {
long id = rs.getLong("id");
String permission = rs.getString("permission");
if (permission == null || permission.isEmpty()) {
return null;
}
boolean value = rs.getBoolean("value");
String server = rs.getString("server");
String world = rs.getString("world");
@ -829,7 +840,10 @@ public class SqlStorage implements StorageImplementation {
ps.setString(1, user.toString());
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
nodes.add(readNode(rs));
Node node = readNode(rs);
if (node != null) {
nodes.add(readNode(rs));
}
}
}
}
@ -906,7 +920,10 @@ public class SqlStorage implements StorageImplementation {
ps.setString(1, group);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
nodes.add(readNode(rs));
Node node = readNode(rs);
if (node != null) {
nodes.add(node);
}
}
}
}
@ -920,7 +937,10 @@ public class SqlStorage implements StorageImplementation {
String holder = rs.getString("name");
Collection<Node> list = nodes.get(holder);
if (list != null) {
list.add(readNode(rs));
Node node = readNode(rs);
if (node != null) {
list.add(readNode(rs));
}
}
}
}

View File

@ -54,6 +54,7 @@ luckperms.command.misc.webapp-unable-to-communicate=Unable to communicate with t
luckperms.command.misc.check-console-for-errors=Check the console for errors
luckperms.command.misc.file-must-be-in-data=File {0} must be a direct child of the data directory
luckperms.command.misc.wait-to-finish=Please wait for it to finish and try again
luckperms.command.misc.permission-invalid-empty=The empty string is not a valid permission
luckperms.command.misc.invalid-priority=Invalid priority {0}
luckperms.command.misc.expected-number=Expected a number
luckperms.command.misc.date-parse-error=Could not parse date {0}