Add 'permission clear' command (#893)

This commit is contained in:
Luck 2018-04-04 18:46:01 +01:00
parent 96f0f46b3e
commit f5c6b9e3d4
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
9 changed files with 167 additions and 66 deletions

View File

@ -291,6 +291,14 @@ public interface Node {
@Nonnull
ContextSet getFullContexts();
/**
* Returns if the node is a "standard" permission node.
*
* @return true if this is a regular permission node
* @since 4.2
*/
boolean isRegularPermissionNode();
/**
* Returns if this is a group node.
*

View File

@ -70,6 +70,7 @@ public enum CommandPermission {
USER_PERM_UNSET_TEMP("permission.unsettemp", USER),
USER_PERM_CHECK("permission.check", USER),
USER_PERM_CHECK_INHERITS("permission.checkinherits", USER),
USER_PERM_CLEAR("permission.clear", USER),
USER_PARENT_INFO("parent.info", USER),
USER_PARENT_SET("parent.set", USER),
USER_PARENT_SET_TRACK("parent.settrack", USER),
@ -109,6 +110,7 @@ public enum CommandPermission {
GROUP_PERM_UNSET_TEMP("permission.unsettemp", GROUP),
GROUP_PERM_CHECK("permission.check", GROUP),
GROUP_PERM_CHECK_INHERITS("permission.checkinherits", GROUP),
GROUP_PERM_CLEAR("permission.clear", GROUP),
GROUP_PARENT_INFO("parent.info", GROUP),
GROUP_PARENT_SET("parent.set", GROUP),
GROUP_PARENT_SET_TRACK("parent.settrack", GROUP),

View File

@ -43,6 +43,7 @@ public class CommandPermission<T extends PermissionHolder> extends SharedMainCom
.add(new PermissionUnsetTemp(locale))
.add(new PermissionCheck(locale))
.add(new PermissionCheckInherits(locale))
.add(new PermissionClear(locale))
.build());
}
}

View File

@ -0,0 +1,89 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.commands.generic.permission;
import me.lucko.luckperms.api.context.MutableContextSet;
import me.lucko.luckperms.common.actionlog.ExtendedLogEntry;
import me.lucko.luckperms.common.command.CommandResult;
import me.lucko.luckperms.common.command.abstraction.CommandException;
import me.lucko.luckperms.common.command.abstraction.SharedSubCommand;
import me.lucko.luckperms.common.command.access.ArgumentPermissions;
import me.lucko.luckperms.common.command.access.CommandPermission;
import me.lucko.luckperms.common.command.utils.ArgumentParser;
import me.lucko.luckperms.common.command.utils.MessageUtils;
import me.lucko.luckperms.common.command.utils.StorageAssistant;
import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.utils.Predicates;
import java.util.List;
public class PermissionClear extends SharedSubCommand {
public PermissionClear(LocaleManager locale) {
super(CommandSpec.PERMISSION_CLEAR.localize(locale), "clear", CommandPermission.USER_PERM_CLEAR, CommandPermission.GROUP_PERM_CLEAR, Predicates.alwaysFalse());
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args, String label, CommandPermission permission) throws CommandException {
if (ArgumentPermissions.checkModifyPerms(plugin, sender, permission, holder)) {
Message.COMMAND_NO_PERMISSION.send(sender);
return CommandResult.NO_PERMISSION;
}
int before = holder.getEnduringNodes().size();
MutableContextSet context = ArgumentParser.parseContext(0, args, plugin);
if (ArgumentPermissions.checkContext(plugin, sender, permission, context)) {
Message.COMMAND_NO_PERMISSION.send(sender);
return CommandResult.NO_PERMISSION;
}
if (context.isEmpty()) {
holder.clearPermissions();
} else {
holder.clearPermissions(context);
}
int changed = before - holder.getEnduringNodes().size();
if (changed == 1) {
Message.PERMISSION_CLEAR_SUCCESS_SINGULAR.send(sender, holder.getFriendlyName(), MessageUtils.contextSetToString(context), changed);
} else {
Message.PERMISSION_CLEAR_SUCCESS.send(sender, holder.getFriendlyName(), MessageUtils.contextSetToString(context), changed);
}
ExtendedLogEntry.build().actor(sender).acted(holder)
.action("permission", "clear", context)
.build().submit(plugin, sender);
StorageAssistant.save(holder, sender, plugin);
return CommandResult.SUCCESS;
}
}

View File

@ -240,6 +240,11 @@ public enum CommandSpec {
Argument.create("context...", false, "the contexts to check in")
)
),
PERMISSION_CLEAR("Clears all permissions",
Argument.list(
Argument.create("context...", false, "the contexts to filter by")
)
),
PARENT_INFO("Lists the groups that this object inherits from",
Argument.list(

View File

@ -245,8 +245,10 @@ public enum Message {
UNSET_INHERIT_SUCCESS("&b{}&a no longer inherits permissions from &b{}&a in context {}&a.", true),
UNSET_TEMP_INHERIT_SUCCESS("&b{}&a no longer temporarily inherits permissions from &b{}&a in context {}&a.", true),
CLEAR_SUCCESS("&b{}&a's permissions were cleared in context {}&a. (&b{}&a nodes were removed.)", true),
CLEAR_SUCCESS_SINGULAR("&b{}&a's permissions were cleared in context {}&a. (&b{}&a node was removed.)", true),
CLEAR_SUCCESS("&b{}&a's nodes were cleared in context {}&a. (&b{}&a nodes were removed.)", true),
CLEAR_SUCCESS_SINGULAR("&b{}&a's nodes were cleared in context {}&a. (&b{}&a node was removed.)", true),
PERMISSION_CLEAR_SUCCESS("&b{}&a's permissions were cleared in context {}&a. (&b{}&a nodes were removed.)", true),
PERMISSION_CLEAR_SUCCESS_SINGULAR("&b{}&a's permissions were cleared in context {}&a. (&b{}&a node was removed.)", true),
PARENT_CLEAR_SUCCESS("&b{}&a's parents were cleared in context {}&a. (&b{}&a nodes were removed.)", true),
PARENT_CLEAR_SUCCESS_SINGULAR("&b{}&a's parents were cleared in context {}&a. (&b{}&a node was removed.)", true),

View File

@ -330,10 +330,36 @@ public abstract class PermissionHolder {
}
public boolean removeIf(Predicate<Node> predicate) {
return removeIf(predicate, null);
}
public boolean removeIf(Predicate<Node> predicate, Runnable taskIfSuccess) {
ImmutableCollection<Node> before = getEnduringNodes().values();
if (!this.enduringNodes.removeIf(predicate)) {
return false;
}
if (taskIfSuccess != null) {
taskIfSuccess.run();
}
invalidateCache();
ImmutableCollection<Node> after = getEnduringNodes().values();
this.plugin.getEventFactory().handleNodeClear(this, before, after);
return true;
}
public boolean removeIf(ContextSet contextSet, Predicate<Node> predicate) {
return removeIf(contextSet, predicate, null);
}
public boolean removeIf(ContextSet contextSet, Predicate<Node> predicate, Runnable taskIfSuccess) {
ImmutableCollection<Node> before = getEnduringNodes().values();
if (!this.enduringNodes.removeIf(contextSet, predicate)) {
return false;
}
if (taskIfSuccess != null) {
taskIfSuccess.run();
}
invalidateCache();
ImmutableCollection<Node> after = getEnduringNodes().values();
@ -820,86 +846,44 @@ public abstract class PermissionHolder {
return true;
}
public boolean clearPermissions() {
return removeIf(Node::isRegularPermissionNode);
}
public boolean clearPermissions(ContextSet contextSet) {
return removeIf(contextSet, Node::isRegularPermissionNode);
}
public boolean clearParents(boolean giveDefault) {
ImmutableCollection<Node> before = getEnduringNodes().values();
if (!this.enduringNodes.removeIf(Node::isGroupNode)) {
return false;
}
if (this.getType().isUser() && giveDefault) {
this.plugin.getUserManager().giveDefaultIfNeeded((User) this, false);
}
invalidateCache();
ImmutableCollection<Node> after = getEnduringNodes().values();
this.plugin.getEventFactory().handleNodeClear(this, before, after);
return true;
return removeIf(Node::isGroupNode, () -> {
if (this.getType().isUser() && giveDefault) {
this.plugin.getUserManager().giveDefaultIfNeeded((User) this, false);
}
});
}
public boolean clearParents(ContextSet contextSet, boolean giveDefault) {
ImmutableCollection<Node> before = getEnduringNodes().values();
if (!this.enduringNodes.removeIf(contextSet, Node::isGroupNode)) {
return false;
}
if (this.getType().isUser() && giveDefault) {
this.plugin.getUserManager().giveDefaultIfNeeded((User) this, false);
}
invalidateCache();
ImmutableCollection<Node> after = getEnduringNodes().values();
this.plugin.getEventFactory().handleNodeClear(this, before, after);
return true;
return removeIf(contextSet, Node::isGroupNode, () -> {
if (this.getType().isUser() && giveDefault) {
this.plugin.getUserManager().giveDefaultIfNeeded((User) this, false);
}
});
}
public boolean clearMeta(MetaType type) {
ImmutableCollection<Node> before = getEnduringNodes().values();
if (!this.enduringNodes.removeIf(type::matches)) {
return false;
}
invalidateCache();
ImmutableCollection<Node> after = getEnduringNodes().values();
this.plugin.getEventFactory().handleNodeClear(this, before, after);
return true;
return removeIf(type::matches);
}
public boolean clearMeta(MetaType type, ContextSet contextSet) {
ImmutableCollection<Node> before = getEnduringNodes().values();
if (!this.enduringNodes.removeIf(contextSet, type::matches)) {
return false;
}
invalidateCache();
ImmutableCollection<Node> after = getEnduringNodes().values();
this.plugin.getEventFactory().handleNodeClear(this, before, after);
return true;
return removeIf(contextSet, type::matches);
}
public boolean clearMetaKeys(String key, boolean temp) {
ImmutableCollection<Node> before = getEnduringNodes().values();
if (!this.enduringNodes.removeIf(n -> n.isMeta() && (n.isTemporary() == temp) && n.getMeta().getKey().equalsIgnoreCase(key))) {
return false;
}
invalidateCache();
ImmutableCollection<Node> after = getEnduringNodes().values();
this.plugin.getEventFactory().handleNodeClear(this, before, after);
return true;
return removeIf(n -> n.isMeta() && (n.isTemporary() == temp) && n.getMeta().getKey().equalsIgnoreCase(key));
}
public boolean clearMetaKeys(String key, ContextSet contextSet, boolean temp) {
ImmutableCollection<Node> before = getEnduringNodes().values();
if (!this.enduringNodes.removeIf(contextSet, n -> n.isMeta() && (n.isTemporary() == temp) && n.getMeta().getKey().equalsIgnoreCase(key))) {
return false;
}
invalidateCache();
ImmutableCollection<Node> after = getEnduringNodes().values();
this.plugin.getEventFactory().handleNodeClear(this, before, after);
return true;
return removeIf(contextSet, n -> n.isMeta() && (n.isTemporary() == temp) && n.getMeta().getKey().equalsIgnoreCase(key));
}
public boolean clearTransientNodes() {

View File

@ -171,6 +171,11 @@ public abstract class ForwardingNode implements Node {
return delegate().getFullContexts();
}
@Override
public boolean isRegularPermissionNode() {
return delegate().isRegularPermissionNode();
}
@Override
public boolean isGroupNode() {
return delegate().isGroupNode();

View File

@ -255,6 +255,11 @@ public final class ImmutableNode implements Node {
return isTemporary() && this.expireAt < System.currentTimeMillis() / 1000L;
}
@Override
public boolean isRegularPermissionNode() {
return !isGroupNode() && !isPrefix() && !isSuffix() && !isMeta();
}
@Override
public boolean isGroupNode() {
return this.groupName != null;