From 6540c695dea074085fa646eeae87e8b7bf319b55 Mon Sep 17 00:00:00 2001 From: Luck Date: Fri, 3 Feb 2017 22:24:42 +0000 Subject: [PATCH] Add configurable duration handling when a holder already has a temporary permission/parent/option set - closes #152 --- bukkit/src/main/resources/config.yml | 8 ++ bungee/src/main/resources/config.yml | 8 ++ .../generic/meta/MetaAddTempPrefix.java | 10 ++- .../generic/meta/MetaAddTempSuffix.java | 10 ++- .../commands/generic/meta/MetaSetTemp.java | 8 +- .../generic/parent/ParentAddTemp.java | 20 ++++- .../generic/permission/PermissionSetTemp.java | 11 ++- .../luckperms/common/config/ConfigKeys.java | 9 ++ .../common/core/TemporaryModifier.java | 45 ++++++++++ .../common/core/model/PermissionHolder.java | 84 +++++++++++++++++-- sponge/src/main/resources/luckperms.conf | 8 ++ 11 files changed, 199 insertions(+), 22 deletions(-) create mode 100644 common/src/main/java/me/lucko/luckperms/common/core/TemporaryModifier.java diff --git a/bukkit/src/main/resources/config.yml b/bukkit/src/main/resources/config.yml index 632bddee..7240a264 100644 --- a/bukkit/src/main/resources/config.yml +++ b/bukkit/src/main/resources/config.yml @@ -46,6 +46,14 @@ online-mode: true # If the plugin should send log notifications to users whenever permissions are modified. log-notify: true +# Controls how temporary permissions/parents/meta should be accumulated +# +# The default behaviour is "deny" +# If "accumulate": durations will be added to the existing expiry time +# If "replace": durations will be replaced if the new duration is later than the current expiration +# If "deny": the command will just fail if you try to add another node with the same expiry +temporary-add-behaviour: deny + diff --git a/bungee/src/main/resources/config.yml b/bungee/src/main/resources/config.yml index 6ba7571f..3e31fd4f 100644 --- a/bungee/src/main/resources/config.yml +++ b/bungee/src/main/resources/config.yml @@ -56,6 +56,14 @@ world-rewrite: group-name-rewrite: # default: Member +# Controls how temporary permissions/parents/meta should be accumulated +# +# The default behaviour is "deny" +# If "accumulate": durations will be added to the existing expiry time +# If "replace": durations will be replaced if the new duration is later than the current expiration +# If "deny": the command will just fail if you try to add another node with the same expiry +temporary-add-behaviour: deny + diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaAddTempPrefix.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaAddTempPrefix.java index 6c662860..43f6898c 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaAddTempPrefix.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaAddTempPrefix.java @@ -30,8 +30,11 @@ import me.lucko.luckperms.common.commands.generic.SharedSubCommand; import me.lucko.luckperms.common.commands.sender.Sender; import me.lucko.luckperms.common.commands.utils.ArgumentUtils; import me.lucko.luckperms.common.commands.utils.ContextHelper; +import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.constants.Message; import me.lucko.luckperms.common.constants.Permission; +import me.lucko.luckperms.common.core.NodeBuilder; +import me.lucko.luckperms.common.core.TemporaryModifier; import me.lucko.luckperms.common.core.model.PermissionHolder; import me.lucko.luckperms.common.data.LogEntry; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; @@ -63,25 +66,26 @@ public class MetaAddTempPrefix extends SharedSubCommand { long duration = ArgumentUtils.handleDuration(2, args); String server = ArgumentUtils.handleServer(3, args); String world = ArgumentUtils.handleWorld(4, args); + TemporaryModifier modifier = plugin.getConfiguration().get(ConfigKeys.TEMPORARY_ADD_BEHAVIOUR); final String node = "prefix." + priority + "." + MetaUtils.escapeCharacters(prefix); try { switch (ContextHelper.determine(server, world)) { case NONE: - holder.setPermission(node, true, duration); + duration = holder.setPermission(new NodeBuilder(node).setValue(true).setExpiry(duration).build(), modifier).getExpiryUnixTime(); Message.ADD_TEMP_PREFIX_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority, DateUtil.formatDateDiff(duration) ); break; case SERVER: - holder.setPermission(node, true, server, duration); + duration = holder.setPermission(new NodeBuilder(node).setValue(true).setServer(server).setExpiry(duration).build(), modifier).getExpiryUnixTime(); Message.ADD_TEMP_PREFIX_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority, server, DateUtil.formatDateDiff(duration) ); break; case SERVER_AND_WORLD: - holder.setPermission(node, true, server, world, duration); + duration = holder.setPermission(new NodeBuilder(node).setValue(true).setServer(server).setWorld(world).setExpiry(duration).build(), modifier).getExpiryUnixTime(); Message.ADD_TEMP_PREFIX_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority, server, world, DateUtil.formatDateDiff(duration) ); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaAddTempSuffix.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaAddTempSuffix.java index 9dc73dd0..f3610667 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaAddTempSuffix.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaAddTempSuffix.java @@ -30,8 +30,11 @@ import me.lucko.luckperms.common.commands.generic.SharedSubCommand; import me.lucko.luckperms.common.commands.sender.Sender; import me.lucko.luckperms.common.commands.utils.ArgumentUtils; import me.lucko.luckperms.common.commands.utils.ContextHelper; +import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.constants.Message; import me.lucko.luckperms.common.constants.Permission; +import me.lucko.luckperms.common.core.NodeBuilder; +import me.lucko.luckperms.common.core.TemporaryModifier; import me.lucko.luckperms.common.core.model.PermissionHolder; import me.lucko.luckperms.common.data.LogEntry; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; @@ -63,25 +66,26 @@ public class MetaAddTempSuffix extends SharedSubCommand { long duration = ArgumentUtils.handleDuration(2, args); String server = ArgumentUtils.handleServer(3, args); String world = ArgumentUtils.handleWorld(4, args); + TemporaryModifier modifier = plugin.getConfiguration().get(ConfigKeys.TEMPORARY_ADD_BEHAVIOUR); final String node = "suffix." + priority + "." + MetaUtils.escapeCharacters(suffix); try { switch (ContextHelper.determine(server, world)) { case NONE: - holder.setPermission(node, true, duration); + duration = holder.setPermission(new NodeBuilder(node).setValue(true).setExpiry(duration).build(), modifier).getExpiryUnixTime(); Message.ADD_TEMP_SUFFIX_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority, DateUtil.formatDateDiff(duration) ); break; case SERVER: - holder.setPermission(node, true, server, duration); + duration = holder.setPermission(new NodeBuilder(node).setValue(true).setServer(server).setExpiry(duration).build(), modifier).getExpiryUnixTime(); Message.ADD_TEMP_SUFFIX_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority, server, DateUtil.formatDateDiff(duration) ); break; case SERVER_AND_WORLD: - holder.setPermission(node, true, server, world, duration); + duration = holder.setPermission(new NodeBuilder(node).setValue(true).setServer(server).setWorld(world).setExpiry(duration).build(), modifier).getExpiryUnixTime(); Message.ADD_TEMP_SUFFIX_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority, server, world, DateUtil.formatDateDiff(duration) ); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetTemp.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetTemp.java index febbd51f..1a8bd9c3 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetTemp.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetTemp.java @@ -30,9 +30,11 @@ import me.lucko.luckperms.common.commands.generic.SharedSubCommand; import me.lucko.luckperms.common.commands.sender.Sender; import me.lucko.luckperms.common.commands.utils.ArgumentUtils; import me.lucko.luckperms.common.commands.utils.ContextHelper; +import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.constants.Message; import me.lucko.luckperms.common.constants.Permission; import me.lucko.luckperms.common.core.NodeFactory; +import me.lucko.luckperms.common.core.TemporaryModifier; import me.lucko.luckperms.common.core.model.PermissionHolder; import me.lucko.luckperms.common.data.LogEntry; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; @@ -63,6 +65,7 @@ public class MetaSetTemp extends SharedSubCommand { long duration = ArgumentUtils.handleDuration(2, args); String server = ArgumentUtils.handleServer(3, args); String world = ArgumentUtils.handleWorld(4, args); + TemporaryModifier modifier = plugin.getConfiguration().get(ConfigKeys.TEMPORARY_ADD_BEHAVIOUR); Node n = NodeFactory.makeMetaNode(key, value).setServer(server).setWorld(world).setExpiry(duration).build(); @@ -74,9 +77,8 @@ public class MetaSetTemp extends SharedSubCommand { holder.clearMetaKeys(key, server, world, true); try { - holder.setPermission(n); - } catch (ObjectAlreadyHasException ignored) { - } + duration = holder.setPermission(n, modifier).getExpiryUnixTime(); + } catch (ObjectAlreadyHasException ignored) {} switch (ContextHelper.determine(server, world)) { case NONE: diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentAddTemp.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentAddTemp.java index fe5edb77..bd6aba1e 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentAddTemp.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentAddTemp.java @@ -22,6 +22,9 @@ package me.lucko.luckperms.common.commands.generic.parent; +import me.lucko.luckperms.api.event.events.GroupAddEvent; +import me.lucko.luckperms.common.api.delegate.GroupDelegate; +import me.lucko.luckperms.common.api.delegate.PermissionHolderDelegate; import me.lucko.luckperms.common.commands.Arg; import me.lucko.luckperms.common.commands.CommandException; import me.lucko.luckperms.common.commands.CommandResult; @@ -29,8 +32,11 @@ import me.lucko.luckperms.common.commands.generic.SharedSubCommand; import me.lucko.luckperms.common.commands.sender.Sender; import me.lucko.luckperms.common.commands.utils.ArgumentUtils; import me.lucko.luckperms.common.commands.utils.ContextHelper; +import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.constants.Message; import me.lucko.luckperms.common.constants.Permission; +import me.lucko.luckperms.common.core.NodeBuilder; +import me.lucko.luckperms.common.core.TemporaryModifier; import me.lucko.luckperms.common.core.model.Group; import me.lucko.luckperms.common.core.model.PermissionHolder; import me.lucko.luckperms.common.data.LogEntry; @@ -63,6 +69,7 @@ public class ParentAddTemp extends SharedSubCommand { long duration = ArgumentUtils.handleDuration(1, args); String server = ArgumentUtils.handleServer(2, args); String world = ArgumentUtils.handleWorld(3, args); + TemporaryModifier modifier = plugin.getConfiguration().get(ConfigKeys.TEMPORARY_ADD_BEHAVIOUR); if (!plugin.getStorage().loadGroup(groupName).join()) { Message.GROUP_DOES_NOT_EXIST.send(sender); @@ -76,24 +83,31 @@ public class ParentAddTemp extends SharedSubCommand { } try { + if (group.getName().equalsIgnoreCase(holder.getObjectName())) { + throw new ObjectAlreadyHasException(); + } + switch (ContextHelper.determine(server, world)) { case NONE: - holder.setInheritGroup(group, duration); + duration = holder.setPermission(new NodeBuilder("group." + group.getName()).setValue(true).setExpiry(duration).build(), modifier).getExpiryUnixTime(); Message.SET_TEMP_INHERIT_SUCCESS.send(sender, holder.getFriendlyName(), group.getDisplayName(), DateUtil.formatDateDiff(duration) ); + plugin.getApiProvider().fireEventAsync(new GroupAddEvent(new PermissionHolderDelegate(holder), new GroupDelegate(group), null, null, duration)); break; case SERVER: - holder.setInheritGroup(group, server, duration); + duration = holder.setPermission(new NodeBuilder("group." + group.getName()).setValue(true).setServer(server).setExpiry(duration).build(), modifier).getExpiryUnixTime(); Message.SET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), group.getDisplayName(), server, DateUtil.formatDateDiff(duration) ); + plugin.getApiProvider().fireEventAsync(new GroupAddEvent(new PermissionHolderDelegate(holder), new GroupDelegate(group), server, null, duration)); break; case SERVER_AND_WORLD: - holder.setInheritGroup(group, server, world, duration); + duration = holder.setPermission(new NodeBuilder("group." + group.getName()).setValue(true).setServer(server).setWorld(world).setExpiry(duration).build(), modifier).getExpiryUnixTime(); Message.SET_TEMP_INHERIT_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), group.getDisplayName(), server, world, DateUtil.formatDateDiff(duration) ); + plugin.getApiProvider().fireEventAsync(new GroupAddEvent(new PermissionHolderDelegate(holder), new GroupDelegate(group), server, world, duration)); break; } diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionSetTemp.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionSetTemp.java index f56100b1..883bb9dd 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionSetTemp.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionSetTemp.java @@ -29,8 +29,11 @@ import me.lucko.luckperms.common.commands.generic.SharedSubCommand; import me.lucko.luckperms.common.commands.sender.Sender; import me.lucko.luckperms.common.commands.utils.ArgumentUtils; import me.lucko.luckperms.common.commands.utils.ContextHelper; +import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.constants.Message; import me.lucko.luckperms.common.constants.Permission; +import me.lucko.luckperms.common.core.NodeBuilder; +import me.lucko.luckperms.common.core.TemporaryModifier; import me.lucko.luckperms.common.core.model.PermissionHolder; import me.lucko.luckperms.common.data.LogEntry; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; @@ -68,22 +71,24 @@ public class PermissionSetTemp extends SharedSubCommand { String server = ArgumentUtils.handleServer(3, args); String world = ArgumentUtils.handleWorld(4, args); + TemporaryModifier modifier = plugin.getConfiguration().get(ConfigKeys.TEMPORARY_ADD_BEHAVIOUR); + try { switch (ContextHelper.determine(server, world)) { case NONE: - holder.setPermission(node, b, duration); + duration = holder.setPermission(new NodeBuilder(node).setValue(b).setExpiry(duration).build(), modifier).getExpiryUnixTime(); Message.SETPERMISSION_TEMP_SUCCESS.send(sender, node, b, holder.getFriendlyName(), DateUtil.formatDateDiff(duration) ); break; case SERVER: - holder.setPermission(node, b, server, duration); + duration = holder.setPermission(new NodeBuilder(node).setValue(b).setServer(server).setExpiry(duration).build(), modifier).getExpiryUnixTime(); Message.SETPERMISSION_TEMP_SERVER_SUCCESS.send(sender, node, b, holder.getFriendlyName(), server, DateUtil.formatDateDiff(duration) ); break; case SERVER_AND_WORLD: - holder.setPermission(node, b, server, world, duration); + duration = holder.setPermission(new NodeBuilder(node).setValue(b).setServer(server).setWorld(world).setExpiry(duration).build(), modifier).getExpiryUnixTime(); Message.SETPERMISSION_TEMP_SERVER_WORLD_SUCCESS.send(sender, node, b, holder.getFriendlyName(), server, world, DateUtil.formatDateDiff(duration) ); diff --git a/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java b/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java index 3271d05f..94a4c895 100644 --- a/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java +++ b/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java @@ -36,6 +36,7 @@ import me.lucko.luckperms.common.config.keys.IntegerKey; import me.lucko.luckperms.common.config.keys.MapKey; import me.lucko.luckperms.common.config.keys.StaticKey; import me.lucko.luckperms.common.config.keys.StringKey; +import me.lucko.luckperms.common.core.TemporaryModifier; import me.lucko.luckperms.common.defaults.Rule; import me.lucko.luckperms.common.storage.DatastoreConfiguration; import me.lucko.luckperms.common.utils.ImmutableCollectors; @@ -58,6 +59,14 @@ public class ConfigKeys { public static final ConfigKey APPLYING_GLOBAL_GROUPS = BooleanKey.of("apply-global-groups", true); public static final ConfigKey APPLYING_GLOBAL_WORLD_GROUPS = BooleanKey.of("apply-global-world-groups", true); public static final ConfigKey ONLINE_MODE = BooleanKey.of("online-mode", true); + public static final ConfigKey TEMPORARY_ADD_BEHAVIOUR = AbstractKey.of(c -> { + String option = c.getString("temporary-add-behaviour", "deny").toLowerCase(); + if (!option.equals("deny") && !option.equals("replace") && !option.equals("accumulate")) { + option = "deny"; + } + + return TemporaryModifier.valueOf(option.toUpperCase()); + }); public static final ConfigKey APPLYING_WILDCARDS = EnduringKey.wrap(BooleanKey.of("apply-wildcards", true)); public static final ConfigKey APPLYING_REGEX = EnduringKey.wrap(BooleanKey.of("apply-regex", true)); public static final ConfigKey APPLYING_SHORTHAND = EnduringKey.wrap(BooleanKey.of("apply-shorthand", true)); diff --git a/common/src/main/java/me/lucko/luckperms/common/core/TemporaryModifier.java b/common/src/main/java/me/lucko/luckperms/common/core/TemporaryModifier.java new file mode 100644 index 00000000..062b9046 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/core/TemporaryModifier.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016 Lucko (Luck) + * + * 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.common.core; + +/** + * Controls how temporary permissions/parents/meta should be set + */ +public enum TemporaryModifier { + + /** + * Durations will be added to the existing expiry time of a permission + */ + ACCUMULATE, + + /** + * Durations will be replaced if the new duration is later than the current expiration + */ + REPLACE, + + /** + * The command will just fail if you try to add another permission with the same expiry + */ + DENY + +} diff --git a/common/src/main/java/me/lucko/luckperms/common/core/model/PermissionHolder.java b/common/src/main/java/me/lucko/luckperms/common/core/model/PermissionHolder.java index e5b82082..80d51247 100644 --- a/common/src/main/java/me/lucko/luckperms/common/core/model/PermissionHolder.java +++ b/common/src/main/java/me/lucko/luckperms/common/core/model/PermissionHolder.java @@ -58,6 +58,7 @@ import me.lucko.luckperms.common.core.InheritanceInfo; import me.lucko.luckperms.common.core.NodeBuilder; import me.lucko.luckperms.common.core.NodeFactory; import me.lucko.luckperms.common.core.PriorityComparator; +import me.lucko.luckperms.common.core.TemporaryModifier; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.utils.Cache; import me.lucko.luckperms.common.utils.ExtractedContexts; @@ -593,6 +594,16 @@ public abstract class PermissionHolder { return true; } + public Optional getAlmostEquals(Node node, boolean t) { + for (Node n : t ? getTransientNodes() : getNodes()) { + if (n.almostEquals(node)) { + return Optional.of(n); + } + } + + return Optional.empty(); + } + /** * Check if the holder has a permission node * @@ -601,13 +612,7 @@ public abstract class PermissionHolder { * @return a tristate */ public Tristate hasPermission(Node node, boolean t) { - for (Node n : t ? getTransientNodes() : getNodes()) { - if (n.almostEquals(node)) { - return n.getTristate(); - } - } - - return Tristate.UNDEFINED; + return getAlmostEquals(node, t).map(Node::getTristate).orElse(Tristate.UNDEFINED); } public Tristate hasPermission(Node node) { @@ -707,6 +712,71 @@ public abstract class PermissionHolder { plugin.getApiProvider().fireEventAsync(new PermissionNodeSetEvent(new PermissionHolderDelegate(this), node)); } + /** + * Sets a permission node, applying a temporary modifier if the node is temporary. + * @param node the node to set + * @param modifier the modifier to use for the operation + * @return the node that was actually set, respective of the modifier + * @throws ObjectAlreadyHasException if the holder has this permission set already, respective of the modifier + */ + public Node setPermission(Node node, TemporaryModifier modifier) throws ObjectAlreadyHasException { + // If the node is temporary, we should take note of the modifier + if (node.isTemporary()) { + if (modifier == TemporaryModifier.ACCUMULATE) { + // Try to accumulate with an existing node + Optional existing = getAlmostEquals(node, false); + + // An existing node was found + if (existing.isPresent()) { + Node previous = existing.get(); + + // Create a new node with the same properties, but add the expiry dates together + Node newNode = NodeFactory.builderFromExisting(node).setExpiry(previous.getExpiryUnixTime() + node.getSecondsTilExpiry()).build(); + + // Remove the old node & add the new one. + synchronized (nodes) { + nodes.remove(previous); + nodes.add(newNode); + } + + invalidateCache(true); + plugin.getApiProvider().fireEventAsync(new PermissionNodeUnsetEvent(new PermissionHolderDelegate(this), previous)); + plugin.getApiProvider().fireEventAsync(new PermissionNodeSetEvent(new PermissionHolderDelegate(this), newNode)); + return newNode; + } + + } else if (modifier == TemporaryModifier.REPLACE) { + // Try to replace an existing node + Optional existing = getAlmostEquals(node, false); + + // An existing node was found + if (existing.isPresent()) { + Node previous = existing.get(); + + // Only replace if the new expiry time is greater than the old one. + if (node.getExpiryUnixTime() > previous.getExpiryUnixTime()) { + + synchronized (nodes) { + nodes.remove(previous); + nodes.add(node); + } + + invalidateCache(true); + plugin.getApiProvider().fireEventAsync(new PermissionNodeUnsetEvent(new PermissionHolderDelegate(this), previous)); + plugin.getApiProvider().fireEventAsync(new PermissionNodeSetEvent(new PermissionHolderDelegate(this), node)); + return node; + } + } + } + + // DENY behaviour is the default anyways. + } + + // Fallback to the normal handling. + setPermission(node); + return node; + } + /** * Sets a transient permission node * diff --git a/sponge/src/main/resources/luckperms.conf b/sponge/src/main/resources/luckperms.conf index d22dd172..6bda6e0e 100644 --- a/sponge/src/main/resources/luckperms.conf +++ b/sponge/src/main/resources/luckperms.conf @@ -54,6 +54,14 @@ group-name-rewrite { # default="Member" } +# Controls how temporary permissions/parents/meta should be accumulated +# +# The default behaviour is "deny" +# If "accumulate": durations will be added to the existing expiry time +# If "replace": durations will be replaced if the new duration is later than the current expiration +# If "deny": the command will just fail if you try to add another node with the same expiry +temporary-add-behaviour="deny" +