use of me.lucko.luckperms.common.model.Track in project LuckPerms by lucko.
the class UserPromote method execute.
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) throws CommandException {
if (ArgumentPermissions.checkModifyPerms(plugin, sender, getPermission().get(), user)) {
Message.COMMAND_NO_PERMISSION.send(sender);
return CommandResult.NO_PERMISSION;
}
final String trackName = args.get(0).toLowerCase();
if (!DataConstraints.TRACK_NAME_TEST.test(trackName)) {
Message.TRACK_INVALID_ENTRY.send(sender, trackName);
return CommandResult.INVALID_ARGS;
}
Track track = StorageAssistant.loadTrack(trackName, sender, plugin);
if (track == null) {
return CommandResult.LOADING_ERROR;
}
if (track.getSize() <= 1) {
Message.TRACK_EMPTY.send(sender, track.getName());
return CommandResult.STATE_ERROR;
}
boolean silent = args.remove("-s");
MutableContextSet context = ArgumentParser.parseContext(1, args, plugin);
if (ArgumentPermissions.checkContext(plugin, sender, getPermission().get(), context)) {
Message.COMMAND_NO_PERMISSION.send(sender);
return CommandResult.NO_PERMISSION;
}
// Load applicable groups
Set<Node> nodes = user.getEnduringNodes().values().stream().filter(Node::isGroupNode).filter(Node::getValuePrimitive).filter(node -> node.getFullContexts().makeImmutable().equals(context.makeImmutable())).collect(Collectors.toSet());
nodes.removeIf(g -> !track.containsGroup(g.getGroupName()));
if (nodes.isEmpty()) {
String first = track.getGroups().get(0);
Group nextGroup = plugin.getGroupManager().getIfLoaded(first);
if (nextGroup == null) {
Message.USER_PROMOTE_ERROR_MALFORMED.send(sender, first);
return CommandResult.LOADING_ERROR;
}
if (ArgumentPermissions.checkArguments(plugin, sender, getPermission().get(), track.getName(), nextGroup.getName())) {
Message.COMMAND_NO_PERMISSION.send(sender);
return CommandResult.NO_PERMISSION;
}
user.setPermission(NodeFactory.buildGroupNode(nextGroup.getId()).withExtraContext(context).build());
Message.USER_TRACK_ADDED_TO_FIRST.send(sender, user.getFriendlyName(), nextGroup.getFriendlyName(), MessageUtils.contextSetToString(context));
ExtendedLogEntry.build().actor(sender).acted(user).action("promote", track.getName(), context).build().submit(plugin, sender);
StorageAssistant.save(user, sender, plugin);
plugin.getEventFactory().handleUserPromote(user, track, null, first, sender);
return CommandResult.SUCCESS;
}
if (nodes.size() != 1) {
Message.TRACK_AMBIGUOUS_CALL.send(sender, user.getFriendlyName());
return CommandResult.FAILURE;
}
final Node oldNode = nodes.stream().findAny().get();
final String old = oldNode.getGroupName();
final String next;
try {
next = track.getNext(old);
} catch (IllegalArgumentException e) {
Message.TRACK_DOES_NOT_CONTAIN.send(sender, track.getName(), old);
return CommandResult.STATE_ERROR;
}
if (next == null) {
Message.USER_PROMOTE_ERROR_ENDOFTRACK.send(sender, track.getName(), user.getFriendlyName());
return CommandResult.STATE_ERROR;
}
if (!plugin.getStorage().loadGroup(next).join().isPresent()) {
Message.USER_PROMOTE_ERROR_MALFORMED.send(sender, next);
return CommandResult.STATE_ERROR;
}
Group nextGroup = plugin.getGroupManager().getIfLoaded(next);
if (nextGroup == null) {
Message.USER_PROMOTE_ERROR_MALFORMED.send(sender, next);
return CommandResult.LOADING_ERROR;
}
if (ArgumentPermissions.checkArguments(plugin, sender, getPermission().get(), track.getName(), nextGroup.getName())) {
Message.COMMAND_NO_PERMISSION.send(sender);
return CommandResult.NO_PERMISSION;
}
user.unsetPermission(oldNode);
user.setPermission(NodeFactory.buildGroupNode(nextGroup.getName()).withExtraContext(context).build());
if (context.isEmpty() && user.getPrimaryGroup().getStoredValue().orElse(NodeFactory.DEFAULT_GROUP_NAME).equalsIgnoreCase(old)) {
user.getPrimaryGroup().setStoredValue(nextGroup.getName());
}
Message.USER_PROMOTE_SUCCESS.send(sender, user.getFriendlyName(), track.getName(), old, nextGroup.getFriendlyName(), MessageUtils.contextSetToString(context));
if (!silent) {
Message.EMPTY.send(sender, MessageUtils.listToArrowSep(track.getGroups(), old, nextGroup.getName(), false));
}
ExtendedLogEntry.build().actor(sender).acted(user).action("promote", track.getName(), context).build().submit(plugin, sender);
StorageAssistant.save(user, sender, plugin);
plugin.getEventFactory().handleUserPromote(user, track, old, nextGroup.getName(), sender);
return CommandResult.SUCCESS;
}
use of me.lucko.luckperms.common.model.Track in project LuckPerms by lucko.
the class TrackRename method execute.
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Track track, List<String> args, String label) {
String newTrackName = args.get(0).toLowerCase();
if (!DataConstraints.TRACK_NAME_TEST.test(newTrackName)) {
Message.TRACK_INVALID_ENTRY.send(sender, newTrackName);
return CommandResult.INVALID_ARGS;
}
if (plugin.getStorage().loadTrack(newTrackName).join().isPresent()) {
Message.ALREADY_EXISTS.send(sender, newTrackName);
return CommandResult.INVALID_ARGS;
}
Track newTrack;
try {
newTrack = plugin.getStorage().createAndLoadTrack(newTrackName, CreationCause.COMMAND).get();
} catch (Exception e) {
e.printStackTrace();
Message.CREATE_ERROR.send(sender, newTrackName);
return CommandResult.FAILURE;
}
try {
plugin.getStorage().deleteTrack(track, DeletionCause.COMMAND).get();
} catch (Exception e) {
e.printStackTrace();
Message.DELETE_ERROR.send(sender, track.getName());
return CommandResult.FAILURE;
}
newTrack.setGroups(track.getGroups());
Message.RENAME_SUCCESS.send(sender, track.getName(), newTrack.getName());
ExtendedLogEntry.build().actor(sender).acted(track).action("rename", newTrack.getName()).build().submit(plugin, sender);
StorageAssistant.save(newTrack, sender, plugin);
return CommandResult.SUCCESS;
}
use of me.lucko.luckperms.common.model.Track in project LuckPerms by lucko.
the class Exporter method run.
@Override
public void run() {
try (BufferedWriter writer = Files.newBufferedWriter(this.filePath, StandardCharsets.UTF_8)) {
this.log.log("Starting.");
write(writer, "# LuckPerms Export File");
write(writer, "# Generated by " + this.executor.getNameWithLocation() + " at " + DATE_FORMAT.format(new Date(System.currentTimeMillis())));
write(writer, "");
// Export Groups
this.log.log("Starting group export.");
// Create the actual groups first
write(writer, "# Create groups");
AtomicInteger groupCount = new AtomicInteger(0);
List<? extends Group> groups = this.plugin.getGroupManager().getAll().values().stream().sorted((o1, o2) -> {
int i = Integer.compare(o2.getWeight().orElse(0), o1.getWeight().orElse(0));
return i != 0 ? i : o1.getName().compareToIgnoreCase(o2.getName());
}).collect(Collectors.toList());
for (Group group : groups) {
if (!group.getName().equals(NodeFactory.DEFAULT_GROUP_NAME)) {
write(writer, "/lp creategroup " + group.getName());
}
}
for (Group group : groups) {
if (groupCount.get() == 0) {
write(writer, "");
}
write(writer, "# Export group: " + group.getName());
for (Node node : group.getEnduringNodes().values()) {
write(writer, "/lp " + NodeFactory.nodeAsCommand(node, group.getName(), HolderType.GROUP, true));
}
write(writer, "");
this.log.logAllProgress("Exported {} groups so far.", groupCount.incrementAndGet());
}
this.log.log("Exported " + groupCount.get() + " groups.");
write(writer, "");
write(writer, "");
// Export tracks
this.log.log("Starting track export.");
Collection<? extends Track> tracks = this.plugin.getTrackManager().getAll().values();
if (!tracks.isEmpty()) {
// Create the actual tracks first
write(writer, "# Create tracks");
for (Track track : tracks) {
write(writer, "/lp createtrack " + track.getName());
}
write(writer, "");
AtomicInteger trackCount = new AtomicInteger(0);
for (Track track : this.plugin.getTrackManager().getAll().values()) {
write(writer, "# Export track: " + track.getName());
for (String group : track.getGroups()) {
write(writer, "/lp track " + track.getName() + " append " + group);
}
write(writer, "");
this.log.logAllProgress("Exported {} tracks so far.", trackCount.incrementAndGet());
}
write(writer, "");
write(writer, "");
}
this.log.log("Exported " + tracks.size() + " tracks.");
// Users are migrated in separate threads.
// This is because there are likely to be a lot of them, and because we can.
// It's a big speed improvement, since the database/files are split up and can handle concurrent reads.
this.log.log("Starting user export. Finding a list of unique users to export.");
// Find all of the unique users we need to export
Storage ds = this.plugin.getStorage();
Set<UUID> users = ds.getUniqueUsers().join();
this.log.log("Found " + users.size() + " unique users to export.");
write(writer, "# Export users");
// divide into 16 pools.
Cycle<List<UUID>> userPools = new Cycle<>(nInstances(32, ArrayList::new));
for (UUID uuid : users) {
userPools.next().add(uuid);
}
this.log.log("Split users into " + userPools.getBacking().size() + " threads for export.");
// Setup a file writing lock. We don't want multiple threads writing at the same time.
// The write function accepts a list of strings, as we want a user's data to be grouped together.
// This means it can be processed and added in one go.
ReentrantLock lock = new ReentrantLock();
Consumer<List<String>> writeFunction = strings -> {
lock.lock();
try {
for (String s : strings) {
write(writer, s);
}
} finally {
lock.unlock();
}
};
// A set of futures, which are really just the threads we need to wait for.
Set<CompletableFuture<Void>> futures = new HashSet<>();
AtomicInteger userCount = new AtomicInteger(0);
// iterate through each user sublist.
for (List<UUID> subList : userPools.getBacking()) {
// register and start a new thread to process the sublist
futures.add(CompletableFuture.runAsync(() -> {
// iterate through each user in the sublist, and grab their data.
for (UUID uuid : subList) {
try {
// actually export the user. this output will be fed to the writing function when we have all of the user's data.
List<String> output = new ArrayList<>();
User user = this.plugin.getStorage().loadUser(uuid, null).join();
output.add("# Export user: " + user.getUuid().toString() + " - " + user.getName().orElse("unknown username"));
boolean inDefault = false;
for (Node node : user.getEnduringNodes().values()) {
if (node.isGroupNode() && node.getGroupName().equalsIgnoreCase(NodeFactory.DEFAULT_GROUP_NAME)) {
inDefault = true;
continue;
}
output.add("/lp " + NodeFactory.nodeAsCommand(node, user.getUuid().toString(), HolderType.USER, true));
}
if (!user.getPrimaryGroup().getStoredValue().orElse(NodeFactory.DEFAULT_GROUP_NAME).equalsIgnoreCase(NodeFactory.DEFAULT_GROUP_NAME)) {
output.add("/lp user " + user.getUuid().toString() + " switchprimarygroup " + user.getPrimaryGroup().getStoredValue().get());
}
if (!inDefault) {
output.add("/lp user " + user.getUuid().toString() + " parent remove default");
}
this.plugin.getUserManager().cleanup(user);
writeFunction.accept(output);
this.log.logProgress("Exported {} users so far.", userCount.incrementAndGet());
} catch (Exception e) {
e.printStackTrace();
}
}
}, this.plugin.getBootstrap().getScheduler().async()));
}
// all of the threads have been scheduled now and are running. we just need to wait for them all to complete
CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).join();
this.log.log("Exported " + userCount.get() + " users.");
writer.flush();
this.log.getListeners().forEach(l -> Message.LOG_EXPORT_SUCCESS.send(l, this.filePath.toFile().getAbsolutePath()));
} catch (Exception e) {
e.printStackTrace();
}
}
use of me.lucko.luckperms.common.model.Track in project LuckPerms by lucko.
the class ParentClearTrack method execute.
@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;
}
final String trackName = args.get(0).toLowerCase();
if (!DataConstraints.TRACK_NAME_TEST.test(trackName)) {
Message.TRACK_INVALID_ENTRY.send(sender, trackName);
return CommandResult.INVALID_ARGS;
}
Track track = StorageAssistant.loadTrack(trackName, sender, plugin);
if (track == null) {
return CommandResult.LOADING_ERROR;
}
if (track.getSize() <= 1) {
Message.TRACK_EMPTY.send(sender, track.getName());
return CommandResult.STATE_ERROR;
}
int before = holder.getEnduringNodes().size();
MutableContextSet context = ArgumentParser.parseContext(1, args, plugin);
if (ArgumentPermissions.checkContext(plugin, sender, permission, context)) {
Message.COMMAND_NO_PERMISSION.send(sender);
return CommandResult.NO_PERMISSION;
}
if (ArgumentPermissions.checkArguments(plugin, sender, permission, track.getName())) {
Message.COMMAND_NO_PERMISSION.send(sender);
return CommandResult.NO_PERMISSION;
}
if (context.isEmpty()) {
holder.removeIf(node -> node.isGroupNode() && track.containsGroup(node.getGroupName()));
} else {
holder.removeIf(node -> node.isGroupNode() && node.getFullContexts().equals(context) && track.containsGroup(node.getGroupName()));
}
if (holder.getType().isUser()) {
plugin.getUserManager().giveDefaultIfNeeded(((User) holder), false);
}
int changed = before - holder.getEnduringNodes().size();
if (changed == 1) {
Message.PARENT_CLEAR_TRACK_SUCCESS_SINGULAR.send(sender, holder.getFriendlyName(), track.getName(), MessageUtils.contextSetToString(context), changed);
} else {
Message.PARENT_CLEAR_TRACK_SUCCESS.send(sender, holder.getFriendlyName(), track.getName(), MessageUtils.contextSetToString(context), changed);
}
ExtendedLogEntry.build().actor(sender).acted(holder).action("parent", "cleartrack", track.getName(), context).build().submit(plugin, sender);
StorageAssistant.save(holder, sender, plugin);
return CommandResult.SUCCESS;
}
use of me.lucko.luckperms.common.model.Track in project LuckPerms by lucko.
the class ArgumentPermissions method checkModifyPerms.
/**
* Checks if the sender has permission to modify the given target
*
* @param plugin the plugin instance
* @param sender the sender to check
* @param base the base permission for the command
* @param target the object the sender is truing to modify
* @return true if the sender should NOT be allowed to modify the target, true if they should
*/
public static boolean checkModifyPerms(LuckPermsPlugin plugin, Sender sender, CommandPermission base, Object target) {
if (!plugin.getConfiguration().get(ConfigKeys.USE_ARGUMENT_BASED_COMMAND_PERMISSIONS)) {
return false;
}
if (target instanceof User) {
User targetUser = ((User) target);
if (targetUser.getUuid().equals(sender.getUuid())) {
// the sender is trying to edit themselves
Tristate ret = sender.getPermissionValue(base.getPermission() + ".modify.self");
if (ret != Tristate.UNDEFINED) {
return !ret.asBoolean();
} else {
// fallback to the global perm if the one for the specific command is undefined
Tristate globalRet = sender.getPermissionValue(USER_MODIFY_SELF);
return !globalRet.asBoolean();
}
} else {
// they're trying to edit another user
Tristate ret = sender.getPermissionValue(base.getPermission() + ".modify.others");
if (ret != Tristate.UNDEFINED) {
return !ret.asBoolean();
} else {
// fallback to the global perm if the one for the specific command is undefined
Tristate globalRet = sender.getPermissionValue(USER_MODIFY_OTHERS);
return !globalRet.asBoolean();
}
}
} else if (target instanceof Group) {
Group targetGroup = ((Group) target);
Tristate ret = sender.getPermissionValue(base.getPermission() + ".modify." + targetGroup.getName());
if (ret != Tristate.UNDEFINED) {
return !ret.asBoolean();
} else {
// fallback to the global perm if the one for the specific command is undefined
Tristate globalRet = sender.getPermissionValue(GROUP_MODIFY.apply(targetGroup.getName()));
return !globalRet.asBoolean();
}
} else if (target instanceof Track) {
Track targetTrack = ((Track) target);
Tristate ret = sender.getPermissionValue(base.getPermission() + ".modify." + targetTrack.getName());
if (ret != Tristate.UNDEFINED) {
return !ret.asBoolean();
} else {
// fallback to the global perm if the one for the specific command is undefined
Tristate globalRet = sender.getPermissionValue(TRACK_MODIFY.apply(targetTrack.getName()));
return !globalRet.asBoolean();
}
} else {
throw new IllegalStateException();
}
}
Aggregations