mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-24 11:38:40 +01:00
Add /lp track <track> editor command (#2752)
This commit is contained in:
parent
505c073c8e
commit
489c09ddfc
@ -145,6 +145,7 @@ public enum CommandPermission {
|
|||||||
GROUP_CLONE("clone", Type.GROUP),
|
GROUP_CLONE("clone", Type.GROUP),
|
||||||
|
|
||||||
TRACK_INFO("info", Type.TRACK),
|
TRACK_INFO("info", Type.TRACK),
|
||||||
|
TRACK_EDITOR("editor", Type.TRACK),
|
||||||
TRACK_APPEND("append", Type.TRACK),
|
TRACK_APPEND("append", Type.TRACK),
|
||||||
TRACK_INSERT("insert", Type.TRACK),
|
TRACK_INSERT("insert", Type.TRACK),
|
||||||
TRACK_REMOVE("remove", Type.TRACK),
|
TRACK_REMOVE("remove", Type.TRACK),
|
||||||
|
@ -325,6 +325,7 @@ public enum CommandSpec {
|
|||||||
),
|
),
|
||||||
|
|
||||||
TRACK_INFO,
|
TRACK_INFO,
|
||||||
|
TRACK_EDITOR,
|
||||||
TRACK_APPEND(
|
TRACK_APPEND(
|
||||||
arg("group", true)
|
arg("group", true)
|
||||||
),
|
),
|
||||||
|
@ -31,33 +31,24 @@ import me.lucko.luckperms.common.command.access.ArgumentPermissions;
|
|||||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||||
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||||
import me.lucko.luckperms.common.command.utils.ArgumentList;
|
import me.lucko.luckperms.common.command.utils.ArgumentList;
|
||||||
import me.lucko.luckperms.common.commands.misc.EditorCommand;
|
|
||||||
import me.lucko.luckperms.common.context.contextset.ImmutableContextSetImpl;
|
import me.lucko.luckperms.common.context.contextset.ImmutableContextSetImpl;
|
||||||
import me.lucko.luckperms.common.locale.Message;
|
import me.lucko.luckperms.common.locale.Message;
|
||||||
import me.lucko.luckperms.common.model.Group;
|
import me.lucko.luckperms.common.model.Group;
|
||||||
import me.lucko.luckperms.common.model.HolderType;
|
import me.lucko.luckperms.common.model.HolderType;
|
||||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||||
import me.lucko.luckperms.common.model.User;
|
|
||||||
import me.lucko.luckperms.common.node.matcher.ConstraintNodeMatcher;
|
import me.lucko.luckperms.common.node.matcher.ConstraintNodeMatcher;
|
||||||
import me.lucko.luckperms.common.node.matcher.StandardNodeMatchers;
|
import me.lucko.luckperms.common.node.matcher.StandardNodeMatchers;
|
||||||
import me.lucko.luckperms.common.node.types.Inheritance;
|
import me.lucko.luckperms.common.node.types.Inheritance;
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
import me.lucko.luckperms.common.sender.Sender;
|
import me.lucko.luckperms.common.sender.Sender;
|
||||||
import me.lucko.luckperms.common.storage.misc.NodeEntry;
|
|
||||||
import me.lucko.luckperms.common.util.Predicates;
|
import me.lucko.luckperms.common.util.Predicates;
|
||||||
import me.lucko.luckperms.common.verbose.event.MetaCheckEvent;
|
|
||||||
import me.lucko.luckperms.common.webeditor.WebEditorRequest;
|
import me.lucko.luckperms.common.webeditor.WebEditorRequest;
|
||||||
|
|
||||||
import net.luckperms.api.node.Node;
|
import net.luckperms.api.node.Node;
|
||||||
import net.luckperms.api.query.QueryOptions;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class HolderEditor<T extends PermissionHolder> extends ChildCommand<T> {
|
public class HolderEditor<T extends PermissionHolder> extends ChildCommand<T> {
|
||||||
public HolderEditor(HolderType type) {
|
public HolderEditor(HolderType type) {
|
||||||
@ -77,43 +68,21 @@ public class HolderEditor<T extends PermissionHolder> extends ChildCommand<T> {
|
|||||||
if (target instanceof Group) {
|
if (target instanceof Group) {
|
||||||
Group group = (Group) target;
|
Group group = (Group) target;
|
||||||
ConstraintNodeMatcher<Node> matcher = StandardNodeMatchers.key(Inheritance.key(group.getName()));
|
ConstraintNodeMatcher<Node> matcher = StandardNodeMatchers.key(Inheritance.key(group.getName()));
|
||||||
|
WebEditorRequest.includeMatchingUsers(holders, matcher, true, plugin);
|
||||||
Map<UUID, User> users = new LinkedHashMap<>(plugin.getUserManager().getAll());
|
|
||||||
|
|
||||||
// only include online players who are in the group
|
|
||||||
users.values().removeIf(user -> user.normalData().asList().stream().noneMatch(matcher));
|
|
||||||
|
|
||||||
// fill up with other matching users
|
|
||||||
if (users.size() < EditorCommand.MAX_USERS) {
|
|
||||||
plugin.getStorage().searchUserNodes(matcher).join().stream()
|
|
||||||
.map(NodeEntry::getHolder)
|
|
||||||
.distinct()
|
|
||||||
.filter(uuid -> !users.containsKey(uuid))
|
|
||||||
.sorted()
|
|
||||||
.limit(EditorCommand.MAX_USERS - users.size())
|
|
||||||
.forEach(uuid -> {
|
|
||||||
User user = plugin.getStorage().loadUser(uuid, null).join();
|
|
||||||
if (user != null) {
|
|
||||||
users.put(uuid, user);
|
|
||||||
}
|
|
||||||
plugin.getUserManager().getHouseKeeper().cleanup(uuid);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
users.values().stream()
|
|
||||||
.sorted(Comparator
|
|
||||||
.<User>comparingInt(u -> u.getCachedData().getMetaData(QueryOptions.nonContextual()).getWeight(MetaCheckEvent.Origin.INTERNAL)).reversed()
|
|
||||||
.thenComparing(User::getPlainDisplayName, String.CASE_INSENSITIVE_ORDER)
|
|
||||||
)
|
|
||||||
.forEach(holders::add);
|
|
||||||
|
|
||||||
// remove holders which the sender doesn't have perms to view
|
|
||||||
holders.removeIf(h -> ArgumentPermissions.checkViewPerms(plugin, sender, getPermission().get(), h) || ArgumentPermissions.checkGroup(plugin, sender, h, ImmutableContextSetImpl.EMPTY));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// include the original holder too
|
// include the original holder too
|
||||||
holders.add(target);
|
holders.add(target);
|
||||||
|
|
||||||
|
// remove holders which the sender doesn't have perms to view
|
||||||
|
holders.removeIf(h -> ArgumentPermissions.checkViewPerms(plugin, sender, getPermission().get(), h) || ArgumentPermissions.checkGroup(plugin, sender, h, ImmutableContextSetImpl.EMPTY));
|
||||||
|
|
||||||
|
// they don't have perms to view any of them
|
||||||
|
if (holders.isEmpty()) {
|
||||||
|
Message.COMMAND_NO_PERMISSION.send(sender);
|
||||||
|
return CommandResult.NO_PERMISSION;
|
||||||
|
}
|
||||||
|
|
||||||
Message.EDITOR_START.send(sender);
|
Message.EDITOR_START.send(sender);
|
||||||
|
|
||||||
return WebEditorRequest.generate(holders, Collections.emptyList(), sender, label, plugin)
|
return WebEditorRequest.generate(holders, Collections.emptyList(), sender, label, plugin)
|
||||||
|
@ -33,32 +33,21 @@ import me.lucko.luckperms.common.command.spec.CommandSpec;
|
|||||||
import me.lucko.luckperms.common.command.utils.ArgumentList;
|
import me.lucko.luckperms.common.command.utils.ArgumentList;
|
||||||
import me.lucko.luckperms.common.context.contextset.ImmutableContextSetImpl;
|
import me.lucko.luckperms.common.context.contextset.ImmutableContextSetImpl;
|
||||||
import me.lucko.luckperms.common.locale.Message;
|
import me.lucko.luckperms.common.locale.Message;
|
||||||
import me.lucko.luckperms.common.model.Group;
|
|
||||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||||
import me.lucko.luckperms.common.model.Track;
|
import me.lucko.luckperms.common.model.Track;
|
||||||
import me.lucko.luckperms.common.model.User;
|
|
||||||
import me.lucko.luckperms.common.node.matcher.ConstraintNodeMatcher;
|
import me.lucko.luckperms.common.node.matcher.ConstraintNodeMatcher;
|
||||||
import me.lucko.luckperms.common.node.matcher.StandardNodeMatchers;
|
import me.lucko.luckperms.common.node.matcher.StandardNodeMatchers;
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
import me.lucko.luckperms.common.sender.Sender;
|
import me.lucko.luckperms.common.sender.Sender;
|
||||||
import me.lucko.luckperms.common.storage.misc.NodeEntry;
|
|
||||||
import me.lucko.luckperms.common.util.Predicates;
|
import me.lucko.luckperms.common.util.Predicates;
|
||||||
import me.lucko.luckperms.common.verbose.event.MetaCheckEvent;
|
|
||||||
import me.lucko.luckperms.common.webeditor.WebEditorRequest;
|
import me.lucko.luckperms.common.webeditor.WebEditorRequest;
|
||||||
|
|
||||||
import net.luckperms.api.node.Node;
|
import net.luckperms.api.node.Node;
|
||||||
import net.luckperms.api.query.QueryOptions;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class EditorCommand extends SingleCommand {
|
public class EditorCommand extends SingleCommand {
|
||||||
public static final int MAX_USERS = 500;
|
|
||||||
|
|
||||||
public EditorCommand() {
|
public EditorCommand() {
|
||||||
super(CommandSpec.EDITOR, "Editor", CommandPermission.EDITOR, Predicates.notInRange(0, 2));
|
super(CommandSpec.EDITOR, "Editor", CommandPermission.EDITOR, Predicates.notInRange(0, 2));
|
||||||
}
|
}
|
||||||
@ -89,70 +78,16 @@ public class EditorCommand extends SingleCommand {
|
|||||||
// collect holders
|
// collect holders
|
||||||
List<PermissionHolder> holders = new ArrayList<>();
|
List<PermissionHolder> holders = new ArrayList<>();
|
||||||
List<Track> tracks = new ArrayList<>();
|
List<Track> tracks = new ArrayList<>();
|
||||||
if (type.includingGroups) {
|
|
||||||
plugin.getGroupManager().getAll().values().stream()
|
|
||||||
.sorted(Comparator
|
|
||||||
.<Group>comparingInt(g -> g.getWeight().orElse(0)).reversed()
|
|
||||||
.thenComparing(Group::getName, String.CASE_INSENSITIVE_ORDER)
|
|
||||||
)
|
|
||||||
.forEach(holders::add);
|
|
||||||
|
|
||||||
|
if (type.includingGroups) {
|
||||||
|
WebEditorRequest.includeMatchingGroups(holders, Predicates.alwaysTrue(), plugin);
|
||||||
tracks.addAll(plugin.getTrackManager().getAll().values());
|
tracks.addAll(plugin.getTrackManager().getAll().values());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type.includingUsers) {
|
if (type.includingUsers) {
|
||||||
// include all online players
|
// include all online players
|
||||||
Map<UUID, User> users = new LinkedHashMap<>(plugin.getUserManager().getAll());
|
ConstraintNodeMatcher<Node> matcher = filter != null ? StandardNodeMatchers.keyStartsWith(filter) : null;
|
||||||
|
WebEditorRequest.includeMatchingUsers(holders, matcher, type.includingOffline, plugin);
|
||||||
if (filter != null) {
|
|
||||||
ConstraintNodeMatcher<Node> matcher = StandardNodeMatchers.keyStartsWith(filter);
|
|
||||||
|
|
||||||
// only include online players matching the permission
|
|
||||||
users.values().removeIf(user -> user.normalData().asList().stream().noneMatch(matcher));
|
|
||||||
|
|
||||||
// fill up with other matching users
|
|
||||||
if (type.includingOffline && users.size() < MAX_USERS) {
|
|
||||||
plugin.getStorage().searchUserNodes(matcher).join().stream()
|
|
||||||
.map(NodeEntry::getHolder)
|
|
||||||
.distinct()
|
|
||||||
.filter(uuid -> !users.containsKey(uuid))
|
|
||||||
.sorted()
|
|
||||||
.limit(MAX_USERS - users.size())
|
|
||||||
.forEach(uuid -> {
|
|
||||||
User user = plugin.getStorage().loadUser(uuid, null).join();
|
|
||||||
if (user != null) {
|
|
||||||
users.put(uuid, user);
|
|
||||||
}
|
|
||||||
plugin.getUserManager().getHouseKeeper().cleanup(uuid);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// fill up with other users
|
|
||||||
if (type.includingOffline && users.size() < MAX_USERS) {
|
|
||||||
plugin.getStorage().getUniqueUsers().join().stream()
|
|
||||||
.filter(uuid -> !users.containsKey(uuid))
|
|
||||||
.sorted()
|
|
||||||
.limit(MAX_USERS - users.size())
|
|
||||||
.forEach(uuid -> {
|
|
||||||
User user = plugin.getStorage().loadUser(uuid, null).join();
|
|
||||||
if (user != null) {
|
|
||||||
users.put(uuid, user);
|
|
||||||
}
|
|
||||||
plugin.getUserManager().getHouseKeeper().cleanup(uuid);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
users.values().stream()
|
|
||||||
.sorted(Comparator
|
|
||||||
// sort firstly by the users relative weight (depends on the groups they inherit)
|
|
||||||
.<User>comparingInt(u -> u.getCachedData().getMetaData(QueryOptions.nonContextual()).getWeight(MetaCheckEvent.Origin.INTERNAL)).reversed()
|
|
||||||
// then, prioritise users we actually have a username for
|
|
||||||
.thenComparing(u -> u.getUsername().isPresent(), ((Comparator<Boolean>) Boolean::compare).reversed())
|
|
||||||
// then sort according to their username
|
|
||||||
.thenComparing(User::getPlainDisplayName, String.CASE_INSENSITIVE_ORDER)
|
|
||||||
)
|
|
||||||
.forEach(holders::add);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (holders.isEmpty()) {
|
if (holders.isEmpty()) {
|
||||||
|
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* 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.track;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.command.CommandResult;
|
||||||
|
import me.lucko.luckperms.common.command.abstraction.ChildCommand;
|
||||||
|
import me.lucko.luckperms.common.command.access.ArgumentPermissions;
|
||||||
|
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||||
|
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||||
|
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.Group;
|
||||||
|
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||||
|
import me.lucko.luckperms.common.model.Track;
|
||||||
|
import me.lucko.luckperms.common.node.matcher.ConstraintNodeMatcher;
|
||||||
|
import me.lucko.luckperms.common.node.matcher.StandardNodeMatchers;
|
||||||
|
import me.lucko.luckperms.common.node.types.Inheritance;
|
||||||
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
|
import me.lucko.luckperms.common.sender.Sender;
|
||||||
|
import me.lucko.luckperms.common.util.Predicates;
|
||||||
|
import me.lucko.luckperms.common.webeditor.WebEditorRequest;
|
||||||
|
|
||||||
|
import net.luckperms.api.node.Node;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class TrackEditor extends ChildCommand<Track> {
|
||||||
|
public TrackEditor() {
|
||||||
|
super(CommandSpec.TRACK_EDITOR, "editor", CommandPermission.TRACK_EDITOR, Predicates.alwaysFalse());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Track target, ArgumentList args, String label) {
|
||||||
|
if (ArgumentPermissions.checkViewPerms(plugin, sender, getPermission().get(), target)) {
|
||||||
|
Message.COMMAND_NO_PERMISSION.send(sender);
|
||||||
|
return CommandResult.NO_PERMISSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// run a sync task
|
||||||
|
plugin.getSyncTaskBuffer().requestDirectly();
|
||||||
|
|
||||||
|
// collect groups
|
||||||
|
List<Group> groups = new ArrayList<>();
|
||||||
|
WebEditorRequest.includeMatchingGroups(groups, target::containsGroup, plugin);
|
||||||
|
|
||||||
|
// remove groups which the sender doesn't have perms to view
|
||||||
|
groups.removeIf(holder -> ArgumentPermissions.checkViewPerms(plugin, sender, getPermission().get(), holder) || ArgumentPermissions.checkGroup(plugin, sender, holder, ImmutableContextSetImpl.EMPTY));
|
||||||
|
|
||||||
|
// then collect users which are a member of any of those groups
|
||||||
|
// (users which are on the track)
|
||||||
|
List<PermissionHolder> users = new ArrayList<>();
|
||||||
|
if (!groups.isEmpty()) {
|
||||||
|
List<ConstraintNodeMatcher<Node>> matchers = groups.stream()
|
||||||
|
.map(group -> StandardNodeMatchers.key(Inheritance.key(group.getName())))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
WebEditorRequest.includeMatchingUsers(users, matchers, true, plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove users which the sender doesn't have perms to view
|
||||||
|
users.removeIf(holder -> ArgumentPermissions.checkViewPerms(plugin, sender, getPermission().get(), holder));
|
||||||
|
|
||||||
|
List<PermissionHolder> holders = new ArrayList<>(groups.size() + users.size());
|
||||||
|
holders.addAll(groups);
|
||||||
|
holders.addAll(users);
|
||||||
|
|
||||||
|
Message.EDITOR_START.send(sender);
|
||||||
|
|
||||||
|
return WebEditorRequest.generate(holders, Collections.singletonList(target), sender, label, plugin)
|
||||||
|
.createSession(plugin, sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -55,6 +55,7 @@ public class TrackParentCommand extends ParentCommand<Track, String> {
|
|||||||
public TrackParentCommand() {
|
public TrackParentCommand() {
|
||||||
super(CommandSpec.TRACK, "Track", Type.TAKES_ARGUMENT_FOR_TARGET, ImmutableList.<Command<Track>>builder()
|
super(CommandSpec.TRACK, "Track", Type.TAKES_ARGUMENT_FOR_TARGET, ImmutableList.<Command<Track>>builder()
|
||||||
.add(new TrackInfo())
|
.add(new TrackInfo())
|
||||||
|
.add(new TrackEditor())
|
||||||
.add(new TrackAppend())
|
.add(new TrackAppend())
|
||||||
.add(new TrackInsert())
|
.add(new TrackInsert())
|
||||||
.add(new TrackRemove())
|
.add(new TrackRemove())
|
||||||
|
@ -97,11 +97,8 @@ import net.luckperms.api.node.Node;
|
|||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.model;
|
package me.lucko.luckperms.common.model;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
import me.lucko.luckperms.common.cacheddata.HolderCachedDataManager;
|
import me.lucko.luckperms.common.cacheddata.HolderCachedDataManager;
|
||||||
|
@ -35,23 +35,38 @@ import me.lucko.luckperms.common.context.contextset.ImmutableContextSetImpl;
|
|||||||
import me.lucko.luckperms.common.http.AbstractHttpClient;
|
import me.lucko.luckperms.common.http.AbstractHttpClient;
|
||||||
import me.lucko.luckperms.common.http.UnsuccessfulRequestException;
|
import me.lucko.luckperms.common.http.UnsuccessfulRequestException;
|
||||||
import me.lucko.luckperms.common.locale.Message;
|
import me.lucko.luckperms.common.locale.Message;
|
||||||
|
import me.lucko.luckperms.common.model.Group;
|
||||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||||
import me.lucko.luckperms.common.model.Track;
|
import me.lucko.luckperms.common.model.Track;
|
||||||
|
import me.lucko.luckperms.common.model.User;
|
||||||
|
import me.lucko.luckperms.common.node.matcher.ConstraintNodeMatcher;
|
||||||
import me.lucko.luckperms.common.node.utils.NodeJsonSerializer;
|
import me.lucko.luckperms.common.node.utils.NodeJsonSerializer;
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
import me.lucko.luckperms.common.sender.Sender;
|
import me.lucko.luckperms.common.sender.Sender;
|
||||||
|
import me.lucko.luckperms.common.storage.misc.NodeEntry;
|
||||||
import me.lucko.luckperms.common.util.gson.GsonProvider;
|
import me.lucko.luckperms.common.util.gson.GsonProvider;
|
||||||
import me.lucko.luckperms.common.util.gson.JArray;
|
import me.lucko.luckperms.common.util.gson.JArray;
|
||||||
import me.lucko.luckperms.common.util.gson.JObject;
|
import me.lucko.luckperms.common.util.gson.JObject;
|
||||||
|
import me.lucko.luckperms.common.verbose.event.MetaCheckEvent;
|
||||||
|
|
||||||
import net.luckperms.api.context.ImmutableContextSet;
|
import net.luckperms.api.context.ImmutableContextSet;
|
||||||
|
import net.luckperms.api.node.Node;
|
||||||
|
import net.luckperms.api.query.QueryOptions;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import java.util.zip.GZIPOutputStream;
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,6 +74,8 @@ import java.util.zip.GZIPOutputStream;
|
|||||||
*/
|
*/
|
||||||
public class WebEditorRequest {
|
public class WebEditorRequest {
|
||||||
|
|
||||||
|
public static final int MAX_USERS = 500;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a web editor request payload.
|
* Generates a web editor request payload.
|
||||||
*
|
*
|
||||||
@ -171,4 +188,80 @@ public class WebEditorRequest {
|
|||||||
return CommandResult.SUCCESS;
|
return CommandResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void includeMatchingGroups(List<? super Group> holders, Predicate<? super Group> filter, LuckPermsPlugin plugin) {
|
||||||
|
plugin.getGroupManager().getAll().values().stream()
|
||||||
|
.filter(filter)
|
||||||
|
.sorted(Comparator
|
||||||
|
.<Group>comparingInt(g -> g.getWeight().orElse(0)).reversed()
|
||||||
|
.thenComparing(Group::getName, String.CASE_INSENSITIVE_ORDER)
|
||||||
|
)
|
||||||
|
.forEach(holders::add);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void includeMatchingUsers(List<? super User> holders, ConstraintNodeMatcher<Node> matcher, boolean includeOffline, LuckPermsPlugin plugin) {
|
||||||
|
includeMatchingUsers(holders, matcher == null ? Collections.emptyList() : Collections.singleton(matcher), includeOffline, plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void includeMatchingUsers(List<? super User> holders, Collection<ConstraintNodeMatcher<Node>> matchers, boolean includeOffline, LuckPermsPlugin plugin) {
|
||||||
|
Map<UUID, User> users = new LinkedHashMap<>(plugin.getUserManager().getAll());
|
||||||
|
|
||||||
|
if (!matchers.isEmpty()) {
|
||||||
|
users.values().removeIf(user -> {
|
||||||
|
for (ConstraintNodeMatcher<Node> matcher : matchers) {
|
||||||
|
if (user.normalData().asList().stream().anyMatch(matcher)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeOffline && users.size() < MAX_USERS) {
|
||||||
|
if (matchers.isEmpty()) {
|
||||||
|
findMatchingOfflineUsers(users, null, plugin);
|
||||||
|
} else {
|
||||||
|
for (ConstraintNodeMatcher<Node> matcher : matchers) {
|
||||||
|
if (users.size() < MAX_USERS) {
|
||||||
|
findMatchingOfflineUsers(users, matcher, plugin);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
users.values().stream()
|
||||||
|
.sorted(Comparator
|
||||||
|
// sort firstly by the users relative weight (depends on the groups they inherit)
|
||||||
|
.<User>comparingInt(u -> u.getCachedData().getMetaData(QueryOptions.nonContextual()).getWeight(MetaCheckEvent.Origin.INTERNAL)).reversed()
|
||||||
|
// then, prioritise users we actually have a username for
|
||||||
|
.thenComparing(u -> u.getUsername().isPresent(), ((Comparator<Boolean>) Boolean::compare).reversed())
|
||||||
|
// then sort according to their username
|
||||||
|
.thenComparing(User::getPlainDisplayName, String.CASE_INSENSITIVE_ORDER)
|
||||||
|
)
|
||||||
|
.forEach(holders::add);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void findMatchingOfflineUsers(Map<UUID, User> users, ConstraintNodeMatcher<Node> matcher, LuckPermsPlugin plugin) {
|
||||||
|
Stream<UUID> stream;
|
||||||
|
if (matcher == null) {
|
||||||
|
stream = plugin.getStorage().getUniqueUsers().join().stream();
|
||||||
|
} else {
|
||||||
|
stream = plugin.getStorage().searchUserNodes(matcher).join().stream()
|
||||||
|
.map(NodeEntry::getHolder)
|
||||||
|
.distinct();
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.filter(uuid -> !users.containsKey(uuid))
|
||||||
|
.sorted()
|
||||||
|
.limit(MAX_USERS - users.size())
|
||||||
|
.forEach(uuid -> {
|
||||||
|
User user = plugin.getStorage().loadUser(uuid, null).join();
|
||||||
|
if (user != null) {
|
||||||
|
users.put(uuid, user);
|
||||||
|
}
|
||||||
|
plugin.getUserManager().getHouseKeeper().cleanup(uuid);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -563,6 +563,7 @@ luckperms.usage.meta-clear.description=Clears all meta
|
|||||||
luckperms.usage.meta-clear.argument.type=the type of meta to remove
|
luckperms.usage.meta-clear.argument.type=the type of meta to remove
|
||||||
luckperms.usage.meta-clear.argument.context=the contexts to filter by
|
luckperms.usage.meta-clear.argument.context=the contexts to filter by
|
||||||
luckperms.usage.track-info.description=Gives info about the track
|
luckperms.usage.track-info.description=Gives info about the track
|
||||||
|
luckperms.usage.track-editor.description=Opens the web permission editor
|
||||||
luckperms.usage.track-append.description=Appends a group onto the end of the track
|
luckperms.usage.track-append.description=Appends a group onto the end of the track
|
||||||
luckperms.usage.track-append.argument.group=the group to append
|
luckperms.usage.track-append.argument.group=the group to append
|
||||||
luckperms.usage.track-insert.description=Inserts a group at a given position along the track
|
luckperms.usage.track-insert.description=Inserts a group at a given position along the track
|
||||||
|
Loading…
Reference in New Issue
Block a user