Add 'permission clear' command (#893)
This commit is contained in:
parent
96f0f46b3e
commit
f5c6b9e3d4
@ -291,6 +291,14 @@ public interface Node {
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
ContextSet getFullContexts();
|
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.
|
* Returns if this is a group node.
|
||||||
*
|
*
|
||||||
|
@ -70,6 +70,7 @@ public enum CommandPermission {
|
|||||||
USER_PERM_UNSET_TEMP("permission.unsettemp", USER),
|
USER_PERM_UNSET_TEMP("permission.unsettemp", USER),
|
||||||
USER_PERM_CHECK("permission.check", USER),
|
USER_PERM_CHECK("permission.check", USER),
|
||||||
USER_PERM_CHECK_INHERITS("permission.checkinherits", USER),
|
USER_PERM_CHECK_INHERITS("permission.checkinherits", USER),
|
||||||
|
USER_PERM_CLEAR("permission.clear", USER),
|
||||||
USER_PARENT_INFO("parent.info", USER),
|
USER_PARENT_INFO("parent.info", USER),
|
||||||
USER_PARENT_SET("parent.set", USER),
|
USER_PARENT_SET("parent.set", USER),
|
||||||
USER_PARENT_SET_TRACK("parent.settrack", USER),
|
USER_PARENT_SET_TRACK("parent.settrack", USER),
|
||||||
@ -109,6 +110,7 @@ public enum CommandPermission {
|
|||||||
GROUP_PERM_UNSET_TEMP("permission.unsettemp", GROUP),
|
GROUP_PERM_UNSET_TEMP("permission.unsettemp", GROUP),
|
||||||
GROUP_PERM_CHECK("permission.check", GROUP),
|
GROUP_PERM_CHECK("permission.check", GROUP),
|
||||||
GROUP_PERM_CHECK_INHERITS("permission.checkinherits", GROUP),
|
GROUP_PERM_CHECK_INHERITS("permission.checkinherits", GROUP),
|
||||||
|
GROUP_PERM_CLEAR("permission.clear", GROUP),
|
||||||
GROUP_PARENT_INFO("parent.info", GROUP),
|
GROUP_PARENT_INFO("parent.info", GROUP),
|
||||||
GROUP_PARENT_SET("parent.set", GROUP),
|
GROUP_PARENT_SET("parent.set", GROUP),
|
||||||
GROUP_PARENT_SET_TRACK("parent.settrack", GROUP),
|
GROUP_PARENT_SET_TRACK("parent.settrack", GROUP),
|
||||||
|
@ -43,6 +43,7 @@ public class CommandPermission<T extends PermissionHolder> extends SharedMainCom
|
|||||||
.add(new PermissionUnsetTemp(locale))
|
.add(new PermissionUnsetTemp(locale))
|
||||||
.add(new PermissionCheck(locale))
|
.add(new PermissionCheck(locale))
|
||||||
.add(new PermissionCheckInherits(locale))
|
.add(new PermissionCheckInherits(locale))
|
||||||
|
.add(new PermissionClear(locale))
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -240,6 +240,11 @@ public enum CommandSpec {
|
|||||||
Argument.create("context...", false, "the contexts to check in")
|
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",
|
PARENT_INFO("Lists the groups that this object inherits from",
|
||||||
Argument.list(
|
Argument.list(
|
||||||
|
@ -245,8 +245,10 @@ public enum Message {
|
|||||||
UNSET_INHERIT_SUCCESS("&b{}&a no longer inherits permissions from &b{}&a in context {}&a.", true),
|
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),
|
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("&b{}&a's nodes 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_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("&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),
|
PARENT_CLEAR_SUCCESS_SINGULAR("&b{}&a's parents were cleared in context {}&a. (&b{}&a node was removed.)", true),
|
||||||
|
|
||||||
|
@ -330,10 +330,36 @@ public abstract class PermissionHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean removeIf(Predicate<Node> predicate) {
|
public boolean removeIf(Predicate<Node> predicate) {
|
||||||
|
return removeIf(predicate, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeIf(Predicate<Node> predicate, Runnable taskIfSuccess) {
|
||||||
ImmutableCollection<Node> before = getEnduringNodes().values();
|
ImmutableCollection<Node> before = getEnduringNodes().values();
|
||||||
if (!this.enduringNodes.removeIf(predicate)) {
|
if (!this.enduringNodes.removeIf(predicate)) {
|
||||||
return false;
|
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();
|
invalidateCache();
|
||||||
ImmutableCollection<Node> after = getEnduringNodes().values();
|
ImmutableCollection<Node> after = getEnduringNodes().values();
|
||||||
|
|
||||||
@ -820,86 +846,44 @@ public abstract class PermissionHolder {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean clearParents(boolean giveDefault) {
|
public boolean clearPermissions() {
|
||||||
ImmutableCollection<Node> before = getEnduringNodes().values();
|
return removeIf(Node::isRegularPermissionNode);
|
||||||
|
|
||||||
if (!this.enduringNodes.removeIf(Node::isGroupNode)) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean clearPermissions(ContextSet contextSet) {
|
||||||
|
return removeIf(contextSet, Node::isRegularPermissionNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean clearParents(boolean giveDefault) {
|
||||||
|
return removeIf(Node::isGroupNode, () -> {
|
||||||
if (this.getType().isUser() && giveDefault) {
|
if (this.getType().isUser() && giveDefault) {
|
||||||
this.plugin.getUserManager().giveDefaultIfNeeded((User) this, false);
|
this.plugin.getUserManager().giveDefaultIfNeeded((User) this, false);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
invalidateCache();
|
|
||||||
ImmutableCollection<Node> after = getEnduringNodes().values();
|
|
||||||
|
|
||||||
this.plugin.getEventFactory().handleNodeClear(this, before, after);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean clearParents(ContextSet contextSet, boolean giveDefault) {
|
public boolean clearParents(ContextSet contextSet, boolean giveDefault) {
|
||||||
ImmutableCollection<Node> before = getEnduringNodes().values();
|
return removeIf(contextSet, Node::isGroupNode, () -> {
|
||||||
|
|
||||||
if (!this.enduringNodes.removeIf(contextSet, Node::isGroupNode)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (this.getType().isUser() && giveDefault) {
|
if (this.getType().isUser() && giveDefault) {
|
||||||
this.plugin.getUserManager().giveDefaultIfNeeded((User) this, false);
|
this.plugin.getUserManager().giveDefaultIfNeeded((User) this, false);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
invalidateCache();
|
|
||||||
ImmutableCollection<Node> after = getEnduringNodes().values();
|
|
||||||
|
|
||||||
this.plugin.getEventFactory().handleNodeClear(this, before, after);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean clearMeta(MetaType type) {
|
public boolean clearMeta(MetaType type) {
|
||||||
ImmutableCollection<Node> before = getEnduringNodes().values();
|
return removeIf(type::matches);
|
||||||
if (!this.enduringNodes.removeIf(type::matches)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
invalidateCache();
|
|
||||||
ImmutableCollection<Node> after = getEnduringNodes().values();
|
|
||||||
|
|
||||||
this.plugin.getEventFactory().handleNodeClear(this, before, after);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean clearMeta(MetaType type, ContextSet contextSet) {
|
public boolean clearMeta(MetaType type, ContextSet contextSet) {
|
||||||
ImmutableCollection<Node> before = getEnduringNodes().values();
|
return removeIf(contextSet, type::matches);
|
||||||
if (!this.enduringNodes.removeIf(contextSet, type::matches)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
invalidateCache();
|
|
||||||
ImmutableCollection<Node> after = getEnduringNodes().values();
|
|
||||||
|
|
||||||
this.plugin.getEventFactory().handleNodeClear(this, before, after);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean clearMetaKeys(String key, boolean temp) {
|
public boolean clearMetaKeys(String key, boolean temp) {
|
||||||
ImmutableCollection<Node> before = getEnduringNodes().values();
|
return removeIf(n -> n.isMeta() && (n.isTemporary() == temp) && n.getMeta().getKey().equalsIgnoreCase(key));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean clearMetaKeys(String key, ContextSet contextSet, boolean temp) {
|
public boolean clearMetaKeys(String key, ContextSet contextSet, boolean temp) {
|
||||||
ImmutableCollection<Node> before = getEnduringNodes().values();
|
return removeIf(contextSet, n -> n.isMeta() && (n.isTemporary() == temp) && n.getMeta().getKey().equalsIgnoreCase(key));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean clearTransientNodes() {
|
public boolean clearTransientNodes() {
|
||||||
|
@ -171,6 +171,11 @@ public abstract class ForwardingNode implements Node {
|
|||||||
return delegate().getFullContexts();
|
return delegate().getFullContexts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRegularPermissionNode() {
|
||||||
|
return delegate().isRegularPermissionNode();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isGroupNode() {
|
public boolean isGroupNode() {
|
||||||
return delegate().isGroupNode();
|
return delegate().isGroupNode();
|
||||||
|
@ -255,6 +255,11 @@ public final class ImmutableNode implements Node {
|
|||||||
return isTemporary() && this.expireAt < System.currentTimeMillis() / 1000L;
|
return isTemporary() && this.expireAt < System.currentTimeMillis() / 1000L;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRegularPermissionNode() {
|
||||||
|
return !isGroupNode() && !isPrefix() && !isSuffix() && !isMeta();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isGroupNode() {
|
public boolean isGroupNode() {
|
||||||
return this.groupName != null;
|
return this.groupName != null;
|
||||||
|
Loading…
Reference in New Issue
Block a user