mirror of
https://github.com/lucko/LuckPerms.git
synced 2025-08-23 06:32:49 +02:00
Add API methods and command tests for new ActionLog system
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
package net.luckperms.api;
|
||||
|
||||
import net.luckperms.api.actionlog.ActionLogger;
|
||||
import net.luckperms.api.actionlog.filter.ActionFilterFactory;
|
||||
import net.luckperms.api.context.ContextCalculator;
|
||||
import net.luckperms.api.context.ContextManager;
|
||||
import net.luckperms.api.event.EventBus;
|
||||
@@ -267,4 +268,14 @@ public interface LuckPerms {
|
||||
@Internal
|
||||
@NonNull NodeMatcherFactory getNodeMatcherFactory();
|
||||
|
||||
/**
|
||||
* Gets the {@link ActionFilterFactory}.
|
||||
*
|
||||
* @return the action filter factory
|
||||
* @since 5.5
|
||||
*/
|
||||
@Internal
|
||||
@NonNull
|
||||
ActionFilterFactory getActionFilterFactory();
|
||||
|
||||
}
|
||||
|
@@ -28,6 +28,7 @@ package net.luckperms.api.actionlog;
|
||||
import net.luckperms.api.LuckPermsProvider;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.jetbrains.annotations.ApiStatus.NonExtendable;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
@@ -35,7 +36,10 @@ import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Represents a logged action.
|
||||
*
|
||||
* <p>API users should not implement this interface directly.</p>
|
||||
*/
|
||||
@NonExtendable
|
||||
public interface Action extends Comparable<Action> {
|
||||
|
||||
/**
|
||||
@@ -81,6 +85,7 @@ public interface Action extends Comparable<Action> {
|
||||
/**
|
||||
* Represents the source of an action.
|
||||
*/
|
||||
@NonExtendable
|
||||
interface Source {
|
||||
|
||||
/**
|
||||
@@ -102,6 +107,7 @@ public interface Action extends Comparable<Action> {
|
||||
/**
|
||||
* Represents the target of an action.
|
||||
*/
|
||||
@NonExtendable
|
||||
interface Target {
|
||||
|
||||
/**
|
||||
@@ -126,7 +132,7 @@ public interface Action extends Comparable<Action> {
|
||||
@NonNull Type getType();
|
||||
|
||||
/**
|
||||
* Represents the type of a {@link Target}.
|
||||
* Represents the type of {@link Target}.
|
||||
*/
|
||||
enum Type {
|
||||
USER, GROUP, TRACK
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
package net.luckperms.api.actionlog;
|
||||
|
||||
import net.luckperms.api.actionlog.filter.ActionFilter;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
@@ -40,7 +41,11 @@ import java.util.UUID;
|
||||
* You can add to the log using the {@link ActionLogger}, and then request an updated copy.</p>
|
||||
*
|
||||
* <p>All methods are thread safe, and return immutable and thread safe collections.</p>
|
||||
*
|
||||
* @deprecated Use {@link ActionLogger#queryActions(ActionFilter)} or
|
||||
* {@link ActionLogger#queryActions(ActionFilter, int, int)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface ActionLog {
|
||||
|
||||
/**
|
||||
|
@@ -25,9 +25,11 @@
|
||||
|
||||
package net.luckperms.api.actionlog;
|
||||
|
||||
import net.luckperms.api.messaging.MessagingService;
|
||||
import net.luckperms.api.actionlog.filter.ActionFilter;
|
||||
import net.luckperms.api.util.Page;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
@@ -46,43 +48,78 @@ public interface ActionLogger {
|
||||
* Gets a {@link ActionLog} instance from the plugin storage.
|
||||
*
|
||||
* @return a log instance
|
||||
* @deprecated Use {@link #queryActions(ActionFilter)} or {@link #queryActions(ActionFilter, int, int)} instead. These methods
|
||||
* are more efficient (they don't load the full action log into memory) and allow for pagination.
|
||||
*/
|
||||
@Deprecated
|
||||
@NonNull CompletableFuture<ActionLog> getLog();
|
||||
|
||||
/**
|
||||
* Submits a log entry to the plugin to be handled.
|
||||
* Gets all actions from the action log matching the given {@code filter}.
|
||||
*
|
||||
* <p>This method submits the log to the storage provider and broadcasts
|
||||
* it.</p>
|
||||
* <p>If the filter is {@code null}, all actions will be returned.</p>
|
||||
*
|
||||
* <p>It is therefore roughly equivalent to calling
|
||||
* {@link #submitToStorage(Action)} and {@link #broadcastAction(Action)},
|
||||
* however, using this method is preferred to making the calls individually.</p>
|
||||
* <p>Unlike {@link #queryActions(ActionFilter, int, int)}, this method does not implement any pagination and will return
|
||||
* all entries at once.</p>
|
||||
*
|
||||
* <p>If you want to submit a log entry but don't know which method to pick,
|
||||
* @param filter the filter, optional
|
||||
* @return the actions
|
||||
* @since 5.5
|
||||
*/
|
||||
@NonNull CompletableFuture<List<Action>> queryActions(@NonNull ActionFilter filter);
|
||||
|
||||
/**
|
||||
* Gets a page of actions from the action log matching the given {@code filter}.
|
||||
*
|
||||
* <p>If the filter is {@code null}, all actions will be returned.</p>
|
||||
*
|
||||
* @param filter the filter, optional
|
||||
* @param pageSize the size of the page
|
||||
* @param pageNumber the page number
|
||||
* @return the page of actions
|
||||
* @since 5.5
|
||||
*/
|
||||
@NonNull CompletableFuture<Page<Action>> queryActions(@NonNull ActionFilter filter, int pageSize, int pageNumber);
|
||||
|
||||
/**
|
||||
* Submits a logged action to LuckPerms.
|
||||
*
|
||||
* <p>This method submits the action to the storage provider to be persisted in the action log.
|
||||
* It also broadcasts it to administrator players on the current instance and to admins on other
|
||||
* connected servers if a messaging service is configured.</p>
|
||||
*
|
||||
* <p>It is roughly equivalent to calling
|
||||
* {@link #submitToStorage(Action)} followed by {@link #broadcastAction(Action)},
|
||||
* however using this method is preferred to making the calls individually.</p>
|
||||
*
|
||||
* <p>If you want to submit an action log entry but don't know which method to pick,
|
||||
* use this one.</p>
|
||||
*
|
||||
* @param entry the entry to submit
|
||||
* @return a future which will complete when the action is done
|
||||
* @return a future which will complete when the action is submitted
|
||||
*/
|
||||
@NonNull CompletableFuture<Void> submit(@NonNull Action entry);
|
||||
|
||||
/**
|
||||
* Submits a log entry to the plugins storage handler.
|
||||
* Submits a logged action to LuckPerms and persists it in the storage backend.
|
||||
*
|
||||
* <p>This method does not broadcast the action or send it through the messaging service.</p>
|
||||
*
|
||||
* @param entry the entry to submit
|
||||
* @return a future which will complete when the action is done
|
||||
* @return a future which will complete when the action is submitted
|
||||
*/
|
||||
@NonNull CompletableFuture<Void> submitToStorage(@NonNull Action entry);
|
||||
|
||||
/**
|
||||
* Submits a log entry to the plugins log broadcasting handler.
|
||||
* Submits a logged action to LuckPerms and broadcasts it to administrators.
|
||||
*
|
||||
* <p>If enabled, this method will also dispatch the log entry via the
|
||||
* plugins {@link MessagingService}.</p>
|
||||
* <p>The broadcast is made to administrator players on the current instance
|
||||
* and to admins on other connected servers if a messaging service is configured.</p>
|
||||
*
|
||||
* <p>This method does not save the action to the plugin storage backend.</p>
|
||||
*
|
||||
* @param entry the entry to submit
|
||||
* @return a future which will complete when the action is done
|
||||
* @return a future which will complete when the action is broadcasted
|
||||
*/
|
||||
@NonNull CompletableFuture<Void> broadcastAction(@NonNull Action entry);
|
||||
|
||||
|
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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 net.luckperms.api.actionlog.filter;
|
||||
|
||||
import net.luckperms.api.LuckPermsProvider;
|
||||
import net.luckperms.api.actionlog.Action;
|
||||
import org.jetbrains.annotations.ApiStatus.NonExtendable;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* A predicate filter which matches certain {@link Action}s.
|
||||
*
|
||||
* <p>API users should not implement this interface directly.</p>
|
||||
*
|
||||
* @since 5.5
|
||||
*/
|
||||
@NonExtendable
|
||||
public interface ActionFilter extends Predicate<Action> {
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches any action.
|
||||
*
|
||||
* @return the matcher
|
||||
*/
|
||||
static ActionFilter any() {
|
||||
return LuckPermsProvider.get().getActionFilterFactory().any();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions with a specific source user.
|
||||
*
|
||||
* @param uniqueId the source user unique id
|
||||
* @return the matcher
|
||||
*/
|
||||
static ActionFilter source(UUID uniqueId) {
|
||||
return LuckPermsProvider.get().getActionFilterFactory().source(uniqueId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions which target a specific user.
|
||||
*
|
||||
* @param uniqueId the target user unique id
|
||||
* @return the matcher
|
||||
*/
|
||||
static ActionFilter user(UUID uniqueId) {
|
||||
return LuckPermsProvider.get().getActionFilterFactory().user(uniqueId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions which target a specific group.
|
||||
*
|
||||
* @param name the target group name
|
||||
* @return the matcher
|
||||
*/
|
||||
static ActionFilter group(String name) {
|
||||
return LuckPermsProvider.get().getActionFilterFactory().group(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions which target a specific track.
|
||||
*
|
||||
* @param name the target track name
|
||||
* @return the matcher
|
||||
*/
|
||||
static ActionFilter track(String name) {
|
||||
return LuckPermsProvider.get().getActionFilterFactory().track(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions which contain a specific search query in the source name,
|
||||
* target name or description.
|
||||
*
|
||||
* @param query the search query
|
||||
* @return the matcher
|
||||
*/
|
||||
static ActionFilter search(String query) {
|
||||
return LuckPermsProvider.get().getActionFilterFactory().search(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests to see if the given {@link Action} matches the filter.
|
||||
*
|
||||
* @param action the action to test
|
||||
* @return true if the action matched
|
||||
*/
|
||||
@Override
|
||||
boolean test(Action action);
|
||||
|
||||
}
|
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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 net.luckperms.api.actionlog.filter;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus.Internal;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A factory which creates {@link ActionFilter}s.
|
||||
*
|
||||
* @since 5.5
|
||||
*/
|
||||
@Internal
|
||||
public interface ActionFilterFactory {
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches any action.
|
||||
*
|
||||
* @return the matcher
|
||||
*/
|
||||
ActionFilter any();
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions with a specific source user.
|
||||
*
|
||||
* @param uniqueId the source user unique id
|
||||
* @return the matcher
|
||||
*/
|
||||
ActionFilter source(UUID uniqueId);
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions which target a specific user.
|
||||
*
|
||||
* @param uniqueId the target user unique id
|
||||
* @return the matcher
|
||||
*/
|
||||
ActionFilter user(UUID uniqueId);
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions which target a specific group.
|
||||
*
|
||||
* @param name the target group name
|
||||
* @return the matcher
|
||||
*/
|
||||
ActionFilter group(String name);
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions which target a specific track.
|
||||
*
|
||||
* @param name the target track name
|
||||
* @return the matcher
|
||||
*/
|
||||
ActionFilter track(String name);
|
||||
|
||||
/**
|
||||
* Gets an {@link ActionFilter} which matches actions which contain a specific search query in the source name,
|
||||
* target name or description.
|
||||
*
|
||||
* @param query the search query
|
||||
* @return the matcher
|
||||
*/
|
||||
ActionFilter search(String query);
|
||||
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* {@link net.luckperms.api.actionlog.Action} filters.
|
||||
*/
|
||||
package net.luckperms.api.actionlog.filter;
|
53
api/src/main/java/net/luckperms/api/util/Page.java
Normal file
53
api/src/main/java/net/luckperms/api/util/Page.java
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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 net.luckperms.api.util;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a page of entries.
|
||||
*
|
||||
* @since 5.5
|
||||
*/
|
||||
public interface Page<T> {
|
||||
|
||||
/**
|
||||
* Gets the entries on this page.
|
||||
*
|
||||
* @return the entries
|
||||
*/
|
||||
@NonNull List<T> entries();
|
||||
|
||||
/**
|
||||
* Gets the total/overall number of entries (not just the number of entries on this page).
|
||||
*
|
||||
* @return the total number of entries
|
||||
*/
|
||||
int overallSize();
|
||||
|
||||
}
|
@@ -29,12 +29,14 @@ import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.commands.log.LogNotify;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.messaging.InternalMessagingService;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import net.luckperms.api.event.log.LogBroadcastEvent;
|
||||
import net.luckperms.api.event.log.LogNotifyEvent;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class LogDispatcher {
|
||||
@@ -64,7 +66,12 @@ public class LogDispatcher {
|
||||
return !this.plugin.getEventDispatcher().dispatchLogBroadcast(cancelled, entry, origin);
|
||||
}
|
||||
|
||||
private void broadcast(LoggedAction entry, LogNotifyEvent.Origin origin, Sender sender) {
|
||||
// broadcast the entry to online players
|
||||
private void broadcast(LoggedAction entry, LogBroadcastEvent.Origin broadcastOrigin, LogNotifyEvent.Origin origin, Sender sender) {
|
||||
if (!shouldBroadcast(entry, broadcastOrigin)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.plugin.getOnlineSenders()
|
||||
.filter(CommandPermission.LOG_NOTIFY::isAuthorized)
|
||||
.filter(s -> {
|
||||
@@ -74,41 +81,46 @@ public class LogDispatcher {
|
||||
.forEach(s -> Message.LOG.send(s, entry));
|
||||
}
|
||||
|
||||
public void dispatch(LoggedAction entry, Sender sender) {
|
||||
// log the entry to storage
|
||||
public CompletableFuture<Void> logToStorage(LoggedAction entry) {
|
||||
if (!this.plugin.getEventDispatcher().dispatchLogPublish(false, entry)) {
|
||||
this.plugin.getStorage().logAction(entry);
|
||||
return this.plugin.getStorage().logAction(entry);
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
}
|
||||
|
||||
this.plugin.getMessagingService().ifPresent(service -> service.pushLog(entry));
|
||||
|
||||
if (shouldBroadcast(entry, LogBroadcastEvent.Origin.LOCAL)) {
|
||||
broadcast(entry, LogNotifyEvent.Origin.LOCAL, sender);
|
||||
// log the entry to messaging
|
||||
public CompletableFuture<Void> logToMessaging(LoggedAction entry) {
|
||||
InternalMessagingService messagingService = this.plugin.getMessagingService().orElse(null);
|
||||
if (messagingService != null) {
|
||||
return messagingService.pushLog(entry);
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
}
|
||||
|
||||
// log the entry to storage and messaging, and broadcast it to online players
|
||||
private CompletableFuture<Void> dispatch(LoggedAction entry, Sender sender, LogBroadcastEvent.Origin broadcastOrigin, LogNotifyEvent.Origin origin) {
|
||||
CompletableFuture<Void> storageFuture = logToStorage(entry);
|
||||
CompletableFuture<Void> messagingFuture = logToMessaging(entry);
|
||||
broadcast(entry, broadcastOrigin, origin, sender);
|
||||
return CompletableFuture.allOf(storageFuture, messagingFuture);
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> dispatch(LoggedAction entry, Sender sender) {
|
||||
return dispatch(entry, sender, LogBroadcastEvent.Origin.LOCAL, LogNotifyEvent.Origin.LOCAL);
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> dispatchFromApi(LoggedAction entry) {
|
||||
return dispatch(entry, null, LogBroadcastEvent.Origin.LOCAL_API, LogNotifyEvent.Origin.LOCAL_API);
|
||||
}
|
||||
|
||||
public void broadcastFromApi(LoggedAction entry) {
|
||||
this.plugin.getMessagingService().ifPresent(extendedMessagingService -> extendedMessagingService.pushLog(entry));
|
||||
|
||||
if (shouldBroadcast(entry, LogBroadcastEvent.Origin.LOCAL_API)) {
|
||||
broadcast(entry, LogNotifyEvent.Origin.LOCAL_API, null);
|
||||
}
|
||||
broadcast(entry, LogBroadcastEvent.Origin.LOCAL_API, LogNotifyEvent.Origin.LOCAL_API, null);
|
||||
}
|
||||
|
||||
public void dispatchFromApi(LoggedAction entry) {
|
||||
if (!this.plugin.getEventDispatcher().dispatchLogPublish(false, entry)) {
|
||||
try {
|
||||
this.plugin.getStorage().logAction(entry).get();
|
||||
} catch (Exception e) {
|
||||
this.plugin.getLogger().warn("Error whilst storing action", e);
|
||||
}
|
||||
}
|
||||
|
||||
broadcastFromApi(entry);
|
||||
}
|
||||
|
||||
public void dispatchFromRemote(LoggedAction entry) {
|
||||
if (shouldBroadcast(entry, LogBroadcastEvent.Origin.REMOTE)) {
|
||||
broadcast(entry, LogNotifyEvent.Origin.REMOTE, null);
|
||||
}
|
||||
public void broadcastFromRemote(LoggedAction entry) {
|
||||
broadcast(entry, LogBroadcastEvent.Origin.REMOTE, LogNotifyEvent.Origin.REMOTE, null);
|
||||
}
|
||||
}
|
||||
|
@@ -26,6 +26,7 @@
|
||||
package me.lucko.luckperms.common.actionlog;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.HolderType;
|
||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
@@ -44,10 +45,10 @@ import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* An implementation of {@link Action} and {@link Action.Builder},
|
||||
@@ -123,15 +124,11 @@ public class LoggedAction implements Action {
|
||||
return ActionComparator.INSTANCE.compare(this, other);
|
||||
}
|
||||
|
||||
public boolean matchesSearch(String query) {
|
||||
query = Objects.requireNonNull(query, "query").toLowerCase(Locale.ROOT);
|
||||
return this.source.name.toLowerCase(Locale.ROOT).contains(query) ||
|
||||
this.target.name.toLowerCase(Locale.ROOT).contains(query) ||
|
||||
this.description.toLowerCase(Locale.ROOT).contains(query);
|
||||
}
|
||||
|
||||
public void submit(LuckPermsPlugin plugin, Sender sender) {
|
||||
plugin.getLogDispatcher().dispatch(this, sender);
|
||||
CompletableFuture<Void> future = plugin.getLogDispatcher().dispatch(this, sender);
|
||||
if (plugin.getConfiguration().get(ConfigKeys.LOG_SYNCHRONOUSLY_IN_COMMANDS)) {
|
||||
future.join();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
package me.lucko.luckperms.common.api;
|
||||
|
||||
import me.lucko.luckperms.common.api.implementation.ApiActionFilterFactory;
|
||||
import me.lucko.luckperms.common.api.implementation.ApiActionLogger;
|
||||
import me.lucko.luckperms.common.api.implementation.ApiContextManager;
|
||||
import me.lucko.luckperms.common.api.implementation.ApiGroupManager;
|
||||
@@ -47,6 +48,7 @@ import me.lucko.luckperms.common.plugin.logging.PluginLogger;
|
||||
import net.luckperms.api.LuckPerms;
|
||||
import net.luckperms.api.LuckPermsProvider;
|
||||
import net.luckperms.api.actionlog.ActionLogger;
|
||||
import net.luckperms.api.actionlog.filter.ActionFilterFactory;
|
||||
import net.luckperms.api.context.ContextManager;
|
||||
import net.luckperms.api.messaging.MessagingService;
|
||||
import net.luckperms.api.messenger.MessengerProvider;
|
||||
@@ -225,4 +227,8 @@ public class LuckPermsApiProvider implements LuckPerms {
|
||||
return ApiNodeMatcherFactory.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ActionFilterFactory getActionFilterFactory() {
|
||||
return ApiActionFilterFactory.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.api.implementation;
|
||||
|
||||
import me.lucko.luckperms.common.filter.FilterList;
|
||||
import net.luckperms.api.actionlog.Action;
|
||||
import net.luckperms.api.actionlog.filter.ActionFilter;
|
||||
|
||||
public class ApiActionFilter implements ActionFilter {
|
||||
private final FilterList<Action> filter;
|
||||
|
||||
public ApiActionFilter(FilterList<Action> filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Action action) {
|
||||
return this.filter.evaluate(action);
|
||||
}
|
||||
|
||||
public FilterList<Action> getFilter() {
|
||||
return this.filter;
|
||||
}
|
||||
}
|
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.api.implementation;
|
||||
|
||||
import me.lucko.luckperms.common.actionlog.filter.ActionFilters;
|
||||
import net.luckperms.api.actionlog.filter.ActionFilter;
|
||||
import net.luckperms.api.actionlog.filter.ActionFilterFactory;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class ApiActionFilterFactory implements ActionFilterFactory {
|
||||
public static final ApiActionFilterFactory INSTANCE = new ApiActionFilterFactory();
|
||||
|
||||
private ApiActionFilterFactory() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionFilter any() {
|
||||
return new ApiActionFilter(ActionFilters.all());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionFilter source(UUID uniqueId) {
|
||||
Objects.requireNonNull(uniqueId, "uniqueId");
|
||||
return new ApiActionFilter(ActionFilters.source(uniqueId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionFilter user(UUID uniqueId) {
|
||||
Objects.requireNonNull(uniqueId, "uniqueId");
|
||||
return new ApiActionFilter(ActionFilters.user(uniqueId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionFilter group(String name) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
return new ApiActionFilter(ActionFilters.group(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionFilter track(String name) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
return new ApiActionFilter(ActionFilters.track(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionFilter search(String query) {
|
||||
Objects.requireNonNull(query, "query");
|
||||
return new ApiActionFilter(ActionFilters.search(query));
|
||||
}
|
||||
|
||||
}
|
@@ -37,6 +37,7 @@ import java.util.Objects;
|
||||
import java.util.SortedSet;
|
||||
import java.util.UUID;
|
||||
|
||||
@Deprecated
|
||||
public class ApiActionLog implements ActionLog {
|
||||
private final SortedSet<Action> content;
|
||||
|
||||
|
@@ -25,14 +25,22 @@
|
||||
|
||||
package me.lucko.luckperms.common.api.implementation;
|
||||
|
||||
import me.lucko.luckperms.common.actionlog.LogDispatcher;
|
||||
import me.lucko.luckperms.common.actionlog.LogPage;
|
||||
import me.lucko.luckperms.common.actionlog.LoggedAction;
|
||||
import me.lucko.luckperms.common.actionlog.filter.ActionFilters;
|
||||
import me.lucko.luckperms.common.filter.FilterList;
|
||||
import me.lucko.luckperms.common.filter.PageParameters;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import net.luckperms.api.actionlog.Action;
|
||||
import net.luckperms.api.actionlog.ActionLog;
|
||||
import net.luckperms.api.actionlog.ActionLogger;
|
||||
import net.luckperms.api.actionlog.filter.ActionFilter;
|
||||
import net.luckperms.api.util.Page;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class ApiActionLogger implements ActionLogger {
|
||||
@@ -48,23 +56,66 @@ public class ApiActionLogger implements ActionLogger {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public @NonNull CompletableFuture<ActionLog> getLog() {
|
||||
return this.plugin.getStorage().getLogPage(ActionFilters.all(), null)
|
||||
.thenApply(result -> new ApiActionLog(result.getContent()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<List<Action>> queryActions(@NonNull ActionFilter filter) {
|
||||
return this.plugin.getStorage().getLogPage(getFilterList(filter), null).thenApply(ActionPage::new).thenApply(Page::entries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<Page<Action>> queryActions(@NonNull ActionFilter filter, int pageSize, int pageNumber) {
|
||||
return this.plugin.getStorage().getLogPage(getFilterList(filter), new PageParameters(pageSize, pageNumber)).thenApply(ActionPage::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<Void> submit(@NonNull Action entry) {
|
||||
return CompletableFuture.runAsync(() -> this.plugin.getLogDispatcher().dispatchFromApi((LoggedAction) entry), this.plugin.getBootstrap().getScheduler().async());
|
||||
return this.plugin.getLogDispatcher().dispatchFromApi((LoggedAction) entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<Void> submitToStorage(@NonNull Action entry) {
|
||||
return this.plugin.getStorage().logAction(entry);
|
||||
return this.plugin.getLogDispatcher().logToStorage((LoggedAction) entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<Void> broadcastAction(@NonNull Action entry) {
|
||||
return CompletableFuture.runAsync(() -> this.plugin.getLogDispatcher().broadcastFromApi((LoggedAction) entry), this.plugin.getBootstrap().getScheduler().async());
|
||||
LogDispatcher dispatcher = this.plugin.getLogDispatcher();
|
||||
|
||||
CompletableFuture<Void> messagingFuture = dispatcher.logToStorage(((LoggedAction) entry));
|
||||
dispatcher.broadcastFromApi(((LoggedAction) entry));
|
||||
return messagingFuture;
|
||||
}
|
||||
|
||||
private static FilterList<Action> getFilterList(ActionFilter filter) {
|
||||
Objects.requireNonNull(filter, "filter");
|
||||
if (filter instanceof ApiActionFilter) {
|
||||
return ((ApiActionFilter) filter).getFilter();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown filter type: " + filter.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ActionPage implements Page<Action> {
|
||||
private final LogPage page;
|
||||
|
||||
private ActionPage(LogPage page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Override
|
||||
public @NonNull List<Action> entries() {
|
||||
return (List) this.page.getContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int overallSize() {
|
||||
return this.page.getTotalEntries();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +1,28 @@
|
||||
/*
|
||||
* 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.bulkupdate;
|
||||
|
||||
import me.lucko.luckperms.common.filter.FilterField;
|
||||
|
@@ -28,14 +28,10 @@ package me.lucko.luckperms.common.bulkupdate;
|
||||
import me.lucko.luckperms.common.bulkupdate.action.BulkUpdateAction;
|
||||
import me.lucko.luckperms.common.bulkupdate.action.DeleteAction;
|
||||
import me.lucko.luckperms.common.bulkupdate.action.UpdateAction;
|
||||
import me.lucko.luckperms.common.filter.Filter;
|
||||
import me.lucko.luckperms.common.filter.FilterField;
|
||||
import me.lucko.luckperms.common.filter.FilterList;
|
||||
import me.lucko.luckperms.common.filter.sql.FilterSqlBuilder;
|
||||
import net.luckperms.api.node.Node;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BulkUpdateSqlBuilder extends FilterSqlBuilder<Node> {
|
||||
|
||||
public void visit(BulkUpdate update) {
|
||||
|
@@ -59,13 +59,13 @@ public class LogGroupHistory extends ChildCommand<Void> {
|
||||
return;
|
||||
}
|
||||
|
||||
PageParameters pageParams = new PageParameters(ENTRIES_PER_PAGE, args.getIntOrDefault(1, Integer.MIN_VALUE));
|
||||
PageParameters pageParams = new PageParameters(ENTRIES_PER_PAGE, args.getIntOrDefault(1, 1));
|
||||
LogPage log = plugin.getStorage().getLogPage(ActionFilters.group(group), pageParams).join();
|
||||
|
||||
int page = pageParams.pageNumber();
|
||||
int maxPage = pageParams.getMaxPage(log.getTotalEntries());
|
||||
|
||||
if (log.getContent().isEmpty()) {
|
||||
if (log.getTotalEntries() == 0) {
|
||||
Message.LOG_NO_ENTRIES.send(sender);
|
||||
return;
|
||||
}
|
||||
|
@@ -74,7 +74,7 @@ public class LogRecent extends ChildCommand<Void> {
|
||||
LogPage log = plugin.getStorage().getLogPage(uuid == null ? ActionFilters.all() : ActionFilters.source(uuid), pageParams).join();
|
||||
|
||||
int maxPage = pageParams.getMaxPage(log.getTotalEntries());
|
||||
if (log.getContent().isEmpty()) {
|
||||
if (log.getTotalEntries() == 0) {
|
||||
Message.LOG_NO_ENTRIES.send(sender);
|
||||
return;
|
||||
}
|
||||
|
@@ -49,7 +49,7 @@ public class LogSearch extends ChildCommand<Void> {
|
||||
|
||||
@Override
|
||||
public void execute(LuckPermsPlugin plugin, Sender sender, Void ignored, ArgumentList args, String label) {
|
||||
int page = Integer.MIN_VALUE;
|
||||
int page = 1;
|
||||
if (args.size() > 1) {
|
||||
try {
|
||||
page = Integer.parseInt(args.get(args.size() - 1));
|
||||
@@ -64,7 +64,7 @@ public class LogSearch extends ChildCommand<Void> {
|
||||
LogPage log = plugin.getStorage().getLogPage(ActionFilters.search(query), pageParams).join();
|
||||
|
||||
int maxPage = pageParams.getMaxPage(log.getTotalEntries());
|
||||
if (log.getContent().isEmpty()) {
|
||||
if (log.getTotalEntries() == 0) {
|
||||
Message.LOG_NO_ENTRIES.send(sender);
|
||||
return;
|
||||
}
|
||||
|
@@ -58,13 +58,13 @@ public class LogTrackHistory extends ChildCommand<Void> {
|
||||
Message.TRACK_INVALID_ENTRY.send(sender, track);
|
||||
return;
|
||||
}
|
||||
PageParameters pageParams = new PageParameters(ENTRIES_PER_PAGE, args.getIntOrDefault(1, Integer.MIN_VALUE));
|
||||
PageParameters pageParams = new PageParameters(ENTRIES_PER_PAGE, args.getIntOrDefault(1, 1));
|
||||
LogPage log = plugin.getStorage().getLogPage(ActionFilters.track(track), pageParams).join();
|
||||
|
||||
int page = pageParams.pageNumber();
|
||||
int maxPage = pageParams.getMaxPage(log.getTotalEntries());
|
||||
|
||||
if (log.getContent().isEmpty()) {
|
||||
if (log.getTotalEntries() == 0) {
|
||||
Message.LOG_NO_ENTRIES.send(sender);
|
||||
return;
|
||||
}
|
||||
|
@@ -55,13 +55,13 @@ public class LogUserHistory extends ChildCommand<Void> {
|
||||
return;
|
||||
}
|
||||
|
||||
PageParameters pageParams = new PageParameters(ENTRIES_PER_PAGE, args.getIntOrDefault(1, Integer.MIN_VALUE));
|
||||
PageParameters pageParams = new PageParameters(ENTRIES_PER_PAGE, args.getIntOrDefault(1, 1));
|
||||
LogPage log = plugin.getStorage().getLogPage(ActionFilters.user(uuid), pageParams).join();
|
||||
|
||||
int page = pageParams.pageNumber();
|
||||
int maxPage = pageParams.getMaxPage(log.getTotalEntries());
|
||||
|
||||
if (log.getContent().isEmpty()) {
|
||||
if (log.getTotalEntries() == 0) {
|
||||
Message.LOG_NO_ENTRIES.send(sender);
|
||||
return;
|
||||
}
|
||||
|
@@ -443,6 +443,11 @@ public final class ConfigKeys {
|
||||
.collect(ImmutableCollectors.toList());
|
||||
});
|
||||
|
||||
/**
|
||||
* If log should be posted synchronously to storage/messaging in commands
|
||||
*/
|
||||
public static final ConfigKey<Boolean> LOG_SYNCHRONOUSLY_IN_COMMANDS = booleanKey("log-synchronously-in-commands", false);
|
||||
|
||||
/**
|
||||
* If LuckPerms should automatically install translation bundles and periodically update them.
|
||||
*/
|
||||
|
@@ -1,3 +1,28 @@
|
||||
/*
|
||||
* 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.filter;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@@ -1,3 +1,28 @@
|
||||
/*
|
||||
* 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.filter;
|
||||
|
||||
import com.google.common.collect.ForwardingList;
|
||||
|
@@ -1,3 +1,28 @@
|
||||
/*
|
||||
* 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.filter.sql;
|
||||
|
||||
import me.lucko.luckperms.common.filter.Comparison;
|
||||
|
@@ -31,6 +31,8 @@ import net.luckperms.api.actionlog.Action;
|
||||
import net.luckperms.api.messenger.Messenger;
|
||||
import net.luckperms.api.messenger.MessengerProvider;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface InternalMessagingService {
|
||||
|
||||
/**
|
||||
@@ -60,21 +62,21 @@ public interface InternalMessagingService {
|
||||
* Uses the messaging service to inform other servers about a general
|
||||
* change.
|
||||
*/
|
||||
void pushUpdate();
|
||||
CompletableFuture<Void> pushUpdate();
|
||||
|
||||
/**
|
||||
* Pushes an update for a specific user.
|
||||
*
|
||||
* @param user the user
|
||||
*/
|
||||
void pushUserUpdate(User user);
|
||||
CompletableFuture<Void> pushUserUpdate(User user);
|
||||
|
||||
/**
|
||||
* Pushes a log entry to connected servers.
|
||||
*
|
||||
* @param logEntry the log entry
|
||||
*/
|
||||
void pushLog(Action logEntry);
|
||||
CompletableFuture<Void> pushLog(Action logEntry);
|
||||
|
||||
/**
|
||||
* Pushes a custom payload to connected servers.
|
||||
@@ -82,6 +84,6 @@ public interface InternalMessagingService {
|
||||
* @param channelId the channel id
|
||||
* @param payload the payload
|
||||
*/
|
||||
void pushCustomPayload(String channelId, String payload);
|
||||
CompletableFuture<Void> pushCustomPayload(String channelId, String payload);
|
||||
|
||||
}
|
||||
|
@@ -36,6 +36,7 @@ import me.lucko.luckperms.common.messaging.message.UpdateMessageImpl;
|
||||
import me.lucko.luckperms.common.messaging.message.UserUpdateMessageImpl;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.util.AsyncInterface;
|
||||
import me.lucko.luckperms.common.util.ExpiringSet;
|
||||
import me.lucko.luckperms.common.util.gson.GsonProvider;
|
||||
import me.lucko.luckperms.common.util.gson.JObject;
|
||||
@@ -54,9 +55,10 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class LuckPermsMessagingService implements InternalMessagingService, IncomingMessageConsumer {
|
||||
public class LuckPermsMessagingService extends AsyncInterface implements InternalMessagingService, IncomingMessageConsumer {
|
||||
private final LuckPermsPlugin plugin;
|
||||
private final ExpiringSet<UUID> receivedMessages;
|
||||
private final PushUpdateBuffer updateBuffer;
|
||||
@@ -65,6 +67,7 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco
|
||||
private final Messenger messenger;
|
||||
|
||||
public LuckPermsMessagingService(LuckPermsPlugin plugin, MessengerProvider messengerProvider) {
|
||||
super(plugin);
|
||||
this.plugin = plugin;
|
||||
|
||||
this.messengerProvider = messengerProvider;
|
||||
@@ -107,8 +110,8 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pushUpdate() {
|
||||
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||
public CompletableFuture<Void> pushUpdate() {
|
||||
return future(() -> {
|
||||
UUID requestId = generatePingId();
|
||||
this.plugin.getLogger().info("[Messaging] Sending ping with id: " + requestId);
|
||||
this.messenger.sendOutgoingMessage(new UpdateMessageImpl(requestId));
|
||||
@@ -116,8 +119,8 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pushUserUpdate(User user) {
|
||||
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||
public CompletableFuture<Void> pushUserUpdate(User user) {
|
||||
return future(() -> {
|
||||
UUID requestId = generatePingId();
|
||||
this.plugin.getLogger().info("[Messaging] Sending user ping for '" + user.getPlainDisplayName() + "' with id: " + requestId);
|
||||
this.messenger.sendOutgoingMessage(new UserUpdateMessageImpl(requestId, user.getUniqueId()));
|
||||
@@ -125,8 +128,8 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pushLog(Action logEntry) {
|
||||
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||
public CompletableFuture<Void> pushLog(Action logEntry) {
|
||||
return future(() -> {
|
||||
UUID requestId = generatePingId();
|
||||
|
||||
if (this.plugin.getEventDispatcher().dispatchLogNetworkPublish(!this.plugin.getConfiguration().get(ConfigKeys.PUSH_LOG_ENTRIES), requestId, logEntry)) {
|
||||
@@ -139,8 +142,8 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pushCustomPayload(String channelId, String payload) {
|
||||
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||
public CompletableFuture<Void> pushCustomPayload(String channelId, String payload) {
|
||||
return future(() -> {
|
||||
UUID requestId = generatePingId();
|
||||
this.messenger.sendOutgoingMessage(new CustomMessageImpl(requestId, channelId, payload));
|
||||
});
|
||||
@@ -283,7 +286,7 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco
|
||||
ActionLogMessage msg = (ActionLogMessage) message;
|
||||
|
||||
this.plugin.getEventDispatcher().dispatchLogReceive(msg.getId(), msg.getAction());
|
||||
this.plugin.getLogDispatcher().dispatchFromRemote((LoggedAction) msg.getAction());
|
||||
this.plugin.getLogDispatcher().broadcastFromRemote((LoggedAction) msg.getAction());
|
||||
|
||||
} else if (message instanceof CustomMessage) {
|
||||
CustomMessage msg = (CustomMessage) message;
|
||||
|
@@ -78,7 +78,7 @@ public final class AbstractSender<T> implements Sender {
|
||||
|
||||
@Override
|
||||
public void sendMessage(Component message) {
|
||||
if (isConsole()) {
|
||||
if (this.factory.shouldSplitNewlines(this.sender)) {
|
||||
for (Component line : splitNewlines(message)) {
|
||||
this.factory.sendMessage(this.sender, line);
|
||||
}
|
||||
@@ -89,12 +89,12 @@ public final class AbstractSender<T> implements Sender {
|
||||
|
||||
@Override
|
||||
public Tristate getPermissionValue(String permission) {
|
||||
return (isConsole() && this.factory.consoleHasAllPermissions()) ? Tristate.TRUE : this.factory.getPermissionValue(this.sender, permission);
|
||||
return isConsole() ? Tristate.TRUE : this.factory.getPermissionValue(this.sender, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return (isConsole() && this.factory.consoleHasAllPermissions()) || this.factory.hasPermission(this.sender, permission);
|
||||
return isConsole() || this.factory.hasPermission(this.sender, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -63,8 +63,8 @@ public abstract class SenderFactory<P extends LuckPermsPlugin, T> implements Aut
|
||||
|
||||
protected abstract boolean isConsole(T sender);
|
||||
|
||||
protected boolean consoleHasAllPermissions() {
|
||||
return true;
|
||||
protected boolean shouldSplitNewlines(T sender) {
|
||||
return isConsole(sender);
|
||||
}
|
||||
|
||||
public final Sender wrap(T sender) {
|
||||
|
@@ -38,7 +38,7 @@ import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
|
||||
import me.lucko.luckperms.common.storage.implementation.split.SplitStorage;
|
||||
import me.lucko.luckperms.common.storage.misc.NodeEntry;
|
||||
import me.lucko.luckperms.common.util.Throwing;
|
||||
import me.lucko.luckperms.common.util.AsyncInterface;
|
||||
import net.luckperms.api.actionlog.Action;
|
||||
import net.luckperms.api.event.cause.CreationCause;
|
||||
import net.luckperms.api.event.cause.DeletionCause;
|
||||
@@ -54,18 +54,17 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
|
||||
/**
|
||||
* Provides a {@link CompletableFuture} based API for interacting with a {@link StorageImplementation}.
|
||||
*/
|
||||
public class Storage {
|
||||
public class Storage extends AsyncInterface {
|
||||
private final LuckPermsPlugin plugin;
|
||||
private final StorageImplementation implementation;
|
||||
|
||||
public Storage(LuckPermsPlugin plugin, StorageImplementation implementation) {
|
||||
super(plugin);
|
||||
this.plugin = plugin;
|
||||
this.implementation = implementation;
|
||||
}
|
||||
@@ -82,32 +81,6 @@ public class Storage {
|
||||
}
|
||||
}
|
||||
|
||||
private <T> CompletableFuture<T> future(Callable<T> supplier) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
return supplier.call();
|
||||
} catch (Exception e) {
|
||||
if (e instanceof RuntimeException) {
|
||||
throw (RuntimeException) e;
|
||||
}
|
||||
throw new CompletionException(e);
|
||||
}
|
||||
}, this.plugin.getBootstrap().getScheduler().async());
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> future(Throwing.Runnable runnable) {
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (Exception e) {
|
||||
if (e instanceof RuntimeException) {
|
||||
throw (RuntimeException) e;
|
||||
}
|
||||
throw new CompletionException(e);
|
||||
}
|
||||
}, this.plugin.getBootstrap().getScheduler().async());
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.implementation.getImplementationName();
|
||||
}
|
||||
|
@@ -137,7 +137,7 @@ public class FileActionLogger {
|
||||
}
|
||||
}
|
||||
|
||||
private Stream<LoggedAction> getRawLog() throws IOException {
|
||||
private Stream<LoggedAction> loadLog(FilterList<Action> filters) throws IOException {
|
||||
// if there is log content waiting to be written, flush immediately before trying to read
|
||||
if (this.saveBuffer.isEnqueued()) {
|
||||
this.saveBuffer.requestDirectly();
|
||||
@@ -153,7 +153,10 @@ public class FileActionLogger {
|
||||
while ((line = reader.readLine()) != null) {
|
||||
try {
|
||||
JsonElement parsed = GsonProvider.parser().parse(line);
|
||||
builder.add(ActionJsonSerializer.deserialize(parsed));
|
||||
LoggedAction action = ActionJsonSerializer.deserialize(parsed);
|
||||
if (filters.evaluate(action)) {
|
||||
builder.add(action);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -163,10 +166,10 @@ public class FileActionLogger {
|
||||
}
|
||||
|
||||
public LogPage getLogPage(FilterList<Action> filters, @Nullable PageParameters page) throws IOException {
|
||||
List<LoggedAction> filtered = getRawLog()
|
||||
.filter(filters::evaluate)
|
||||
.sorted(Comparator.reverseOrder())
|
||||
.collect(Collectors.toList());
|
||||
List<LoggedAction> filtered = loadLog(filters)
|
||||
.sorted(Comparator.comparing(LoggedAction::getTimestamp))
|
||||
.collect(Collectors.toList())
|
||||
.reversed();
|
||||
|
||||
int size = filtered.size();
|
||||
List<LoggedAction> paginated = page != null ? page.paginate(filtered) : filtered;
|
||||
|
@@ -186,7 +186,7 @@ public class MongoStorage implements StorageImplementation {
|
||||
long count = c.countDocuments(filter);
|
||||
|
||||
List<LoggedAction> content = new ArrayList<>();
|
||||
try (MongoCursor<Document> cursor = ConstraintMongoBuilder.page(page, c.find(filter).sort(Sorts.descending("timestamp"))).iterator()) {
|
||||
try (MongoCursor<Document> cursor = ConstraintMongoBuilder.page(page, c.find(filter).sort(Sorts.descending("timestamp", "_id"))).iterator()) {
|
||||
while (cursor.hasNext()) {
|
||||
content.add(actionFromDoc(cursor.next()));
|
||||
}
|
||||
|
@@ -268,7 +268,7 @@ public class SqlStorage implements StorageImplementation {
|
||||
ActionFilterSqlBuilder sqlBuilder = new ActionFilterSqlBuilder();
|
||||
sqlBuilder.builder().append(ACTION_SELECT_ALL);
|
||||
sqlBuilder.visit(filter);
|
||||
sqlBuilder.builder().append(" ORDER BY time DESC");
|
||||
sqlBuilder.builder().append(" ORDER BY time DESC, id DESC");
|
||||
sqlBuilder.visit(page);
|
||||
|
||||
try (PreparedStatement ps = sqlBuilder.builder().build(c, this.statementProcessor)) {
|
||||
|
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
|
||||
/**
|
||||
* Base class for an interface which can perform operations asynchronously and return {@link CompletableFuture}s
|
||||
*/
|
||||
public abstract class AsyncInterface {
|
||||
|
||||
private final LuckPermsPlugin plugin;
|
||||
|
||||
protected AsyncInterface(LuckPermsPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
protected <T> CompletableFuture<T> future(Callable<T> supplier) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
return supplier.call();
|
||||
} catch (Exception e) {
|
||||
if (e instanceof RuntimeException) {
|
||||
throw (RuntimeException) e;
|
||||
}
|
||||
throw new CompletionException(e);
|
||||
}
|
||||
}, this.plugin.getBootstrap().getScheduler().async());
|
||||
}
|
||||
|
||||
protected CompletableFuture<Void> future(Throwing.Runnable runnable) {
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (Exception e) {
|
||||
if (e instanceof RuntimeException) {
|
||||
throw (RuntimeException) e;
|
||||
}
|
||||
throw new CompletionException(e);
|
||||
}
|
||||
}, this.plugin.getBootstrap().getScheduler().async());
|
||||
}
|
||||
|
||||
}
|
@@ -54,18 +54,18 @@ public class ActionFilterMongoTest {
|
||||
),
|
||||
Arguments.of(
|
||||
ActionFilters.user(UUID.fromString("725d585e-4ff1-4f18-acca-6ac538364080")),
|
||||
// {"$and": [{"target.type": "U"}, {"target.uniqueId": {"$binary": {"base64": "cl1YXk/xTxisymrFODZAgA==", "subType": "04"}}}]}
|
||||
"{\"$and\": [{\"target.type\": \"U\"}, {\"target.uniqueId\": {\"$binary\": {\"base64\": \"cl1YXk/xTxisymrFODZAgA==\", \"subType\": \"04\"}}}]}"
|
||||
// {"$and": [{"target.type": "USER"}, {"target.uniqueId": {"$binary": {"base64": "cl1YXk/xTxisymrFODZAgA==", "subType": "04"}}}]}
|
||||
"{\"$and\": [{\"target.type\": \"USER\"}, {\"target.uniqueId\": {\"$binary\": {\"base64\": \"cl1YXk/xTxisymrFODZAgA==\", \"subType\": \"04\"}}}]}"
|
||||
),
|
||||
Arguments.of(
|
||||
ActionFilters.group("test"),
|
||||
// {"$and": [{"target.type": "G"}, {"target.name": "test"}]}
|
||||
"{\"$and\": [{\"target.type\": \"G\"}, {\"target.name\": \"test\"}]}"
|
||||
// {"$and": [{"target.type": "GROUP"}, {"target.name": "test"}]}
|
||||
"{\"$and\": [{\"target.type\": \"GROUP\"}, {\"target.name\": \"test\"}]}"
|
||||
),
|
||||
Arguments.of(
|
||||
ActionFilters.track("test"),
|
||||
// {"$and": [{"target.type": "T"}, {"target.name": "test"}]}
|
||||
"{\"$and\": [{\"target.type\": \"T\"}, {\"target.name\": \"test\"}]}"
|
||||
// {"$and": [{"target.type": "TRACK"}, {"target.name": "test"}]}
|
||||
"{\"$and\": [{\"target.type\": \"TRACK\"}, {\"target.name\": \"test\"}]}"
|
||||
),
|
||||
Arguments.of(
|
||||
ActionFilters.search("test"),
|
||||
|
@@ -152,6 +152,7 @@ public abstract class AbstractStorageTest {
|
||||
.targetType(Action.Target.Type.GROUP)
|
||||
.targetName(i % 2 == 0 ? "test_group" : "dummy")
|
||||
.description("group test " + i)
|
||||
.timestamp(baseTime)
|
||||
.build());
|
||||
}
|
||||
|
||||
@@ -162,6 +163,7 @@ public abstract class AbstractStorageTest {
|
||||
.targetType(Action.Target.Type.TRACK)
|
||||
.targetName(i % 2 == 0 ? "test_track" : "dummy")
|
||||
.description("track test " + i)
|
||||
.timestamp(baseTime)
|
||||
.build());
|
||||
}
|
||||
|
||||
@@ -210,9 +212,17 @@ public abstract class AbstractStorageTest {
|
||||
|
||||
page = this.storage.getLogPage(ActionFilters.group("test_group"), new PageParameters(10, 1));
|
||||
assertEquals(5, page.getContent().size());
|
||||
assertEquals(
|
||||
ImmutableList.of("group test 8", "group test 6", "group test 4", "group test 2", "group test 0"),
|
||||
page.getContent().stream().map(LoggedAction::getDescription).collect(Collectors.toList())
|
||||
);
|
||||
|
||||
page = this.storage.getLogPage(ActionFilters.track("test_track"), new PageParameters(10, 1));
|
||||
assertEquals(5, page.getContent().size());
|
||||
assertEquals(
|
||||
ImmutableList.of("track test 8", "track test 6", "track test 4", "track test 2", "track test 0"),
|
||||
page.getContent().stream().map(LoggedAction::getDescription).collect(Collectors.toList())
|
||||
);
|
||||
|
||||
page = this.storage.getLogPage(ActionFilters.search("hello"), new PageParameters(500, 1));
|
||||
assertEquals(300, page.getContent().size());
|
||||
|
@@ -1,3 +1,28 @@
|
||||
/*
|
||||
* 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.storage;
|
||||
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
|
@@ -1,3 +1,28 @@
|
||||
/*
|
||||
* 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.storage;
|
||||
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
|
@@ -33,8 +33,16 @@ import java.util.concurrent.CompletableFuture;
|
||||
*/
|
||||
public interface CommandExecutor {
|
||||
|
||||
CompletableFuture<Void> execute(String command);
|
||||
CompletableFuture<Void> execute(StandaloneSender player, String command);
|
||||
|
||||
List<String> tabComplete(String command);
|
||||
List<String> tabComplete(StandaloneSender player, String command);
|
||||
|
||||
default CompletableFuture<Void> execute(String command) {
|
||||
return execute(StandaloneUser.INSTANCE, command);
|
||||
}
|
||||
|
||||
default List<String> tabComplete(String command) {
|
||||
return tabComplete(StandaloneUser.INSTANCE, command);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.standalone.app.integration;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.luckperms.api.util.Tristate;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface StandaloneSender {
|
||||
String getName();
|
||||
|
||||
UUID getUniqueId();
|
||||
|
||||
void sendMessage(Component component);
|
||||
|
||||
Tristate getPermissionValue(String permission);
|
||||
|
||||
boolean hasPermission(String permission);
|
||||
|
||||
boolean isConsole();
|
||||
|
||||
Locale getLocale();
|
||||
}
|
@@ -28,57 +28,57 @@ package me.lucko.luckperms.standalone.app.integration;
|
||||
import me.lucko.luckperms.standalone.app.LuckPermsApplication;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.ansi.ANSIComponentSerializer;
|
||||
import net.luckperms.api.util.Tristate;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Dummy/singleton player class used by the standalone plugin.
|
||||
*
|
||||
* <p>In various places (ContextManager, SenderFactory, ..) the platform "player" type is used
|
||||
* as a generic parameter. This class acts as this type for the standalone plugin.</p>
|
||||
* The sender instance used for the console / users executing commands
|
||||
* on a standalone instance of LuckPerms
|
||||
*/
|
||||
public class SingletonPlayer {
|
||||
public class StandaloneUser implements StandaloneSender {
|
||||
|
||||
/** Empty UUID used by the singleton player. */
|
||||
private static final UUID UUID = new UUID(0, 0);
|
||||
|
||||
/** A message sink that prints the component to stdout */
|
||||
private static final Consumer<Component> PRINT_TO_STDOUT = component -> LuckPermsApplication.LOGGER.info(ANSIComponentSerializer.ansi().serialize(component));
|
||||
public static final StandaloneUser INSTANCE = new StandaloneUser();
|
||||
|
||||
/** Singleton instance */
|
||||
public static final SingletonPlayer INSTANCE = new SingletonPlayer();
|
||||
|
||||
/** A set of message sinks that messages are delivered to */
|
||||
private final Set<Consumer<Component>> messageSinks;
|
||||
|
||||
private SingletonPlayer() {
|
||||
this.messageSinks = new CopyOnWriteArraySet<>();
|
||||
this.messageSinks.add(PRINT_TO_STDOUT);
|
||||
private StandaloneUser() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "StandaloneUser";
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return UUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(Component component) {
|
||||
for (Consumer<Component> sink : this.messageSinks) {
|
||||
sink.accept(component);
|
||||
}
|
||||
LuckPermsApplication.LOGGER.info(ANSIComponentSerializer.ansi().serialize(component));
|
||||
}
|
||||
|
||||
public void addMessageSink(Consumer<Component> sink) {
|
||||
this.messageSinks.add(sink);
|
||||
@Override
|
||||
public Tristate getPermissionValue(String permission) {
|
||||
return Tristate.TRUE;
|
||||
}
|
||||
|
||||
public void removeMessageSink(Consumer<Component> sink) {
|
||||
this.messageSinks.remove(sink);
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConsole() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return Locale.getDefault();
|
||||
}
|
||||
|
||||
}
|
@@ -39,7 +39,7 @@ import me.lucko.luckperms.common.plugin.AbstractLuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.plugin.util.AbstractConnectionListener;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.standalone.app.LuckPermsApplication;
|
||||
import me.lucko.luckperms.standalone.app.integration.SingletonPlayer;
|
||||
import me.lucko.luckperms.standalone.app.integration.StandaloneUser;
|
||||
import me.lucko.luckperms.standalone.stub.StandaloneContextManager;
|
||||
import me.lucko.luckperms.standalone.stub.StandaloneDummyConnectionListener;
|
||||
import me.lucko.luckperms.standalone.stub.StandaloneEventBus;
|
||||
@@ -162,7 +162,7 @@ public class LPStandalonePlugin extends AbstractLuckPermsPlugin {
|
||||
|
||||
@Override
|
||||
public Sender getConsoleSender() {
|
||||
return getSenderFactory().wrap(SingletonPlayer.INSTANCE);
|
||||
return getSenderFactory().wrap(StandaloneUser.INSTANCE);
|
||||
}
|
||||
|
||||
public StandaloneSenderFactory getSenderFactory() {
|
||||
|
@@ -29,7 +29,7 @@ import me.lucko.luckperms.common.command.CommandManager;
|
||||
import me.lucko.luckperms.common.command.utils.ArgumentTokenizer;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.standalone.app.integration.CommandExecutor;
|
||||
import me.lucko.luckperms.standalone.app.integration.SingletonPlayer;
|
||||
import me.lucko.luckperms.standalone.app.integration.StandaloneSender;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -43,15 +43,15 @@ public class StandaloneCommandManager extends CommandManager implements CommandE
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> execute(String command) {
|
||||
Sender wrapped = this.plugin.getSenderFactory().wrap(SingletonPlayer.INSTANCE);
|
||||
public CompletableFuture<Void> execute(StandaloneSender player, String command) {
|
||||
Sender wrapped = this.plugin.getSenderFactory().wrap(player);
|
||||
List<String> arguments = ArgumentTokenizer.EXECUTE.tokenizeInput(command);
|
||||
return executeCommand(wrapped, "lp", arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> tabComplete(String command) {
|
||||
Sender wrapped = this.plugin.getSenderFactory().wrap(SingletonPlayer.INSTANCE);
|
||||
public List<String> tabComplete(StandaloneSender player, String command) {
|
||||
Sender wrapped = this.plugin.getSenderFactory().wrap(player);
|
||||
List<String> arguments = ArgumentTokenizer.TAB_COMPLETE.tokenizeInput(command);
|
||||
return tabCompleteCommand(wrapped, arguments);
|
||||
}
|
||||
|
@@ -27,53 +27,56 @@ package me.lucko.luckperms.standalone;
|
||||
|
||||
import me.lucko.luckperms.common.locale.TranslationManager;
|
||||
import me.lucko.luckperms.common.sender.SenderFactory;
|
||||
import me.lucko.luckperms.standalone.app.integration.SingletonPlayer;
|
||||
import me.lucko.luckperms.standalone.app.integration.StandaloneSender;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.luckperms.api.util.Tristate;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
public class StandaloneSenderFactory extends SenderFactory<LPStandalonePlugin, SingletonPlayer> {
|
||||
public class StandaloneSenderFactory extends SenderFactory<LPStandalonePlugin, StandaloneSender> {
|
||||
|
||||
public StandaloneSenderFactory(LPStandalonePlugin plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getName(SingletonPlayer sender) {
|
||||
protected String getName(StandaloneSender sender) {
|
||||
return sender.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UUID getUniqueId(SingletonPlayer sender) {
|
||||
protected UUID getUniqueId(StandaloneSender sender) {
|
||||
return sender.getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sendMessage(SingletonPlayer sender, Component message) {
|
||||
Component rendered = TranslationManager.render(message, Locale.getDefault());
|
||||
protected void sendMessage(StandaloneSender sender, Component message) {
|
||||
Component rendered = TranslationManager.render(message, sender.getLocale());
|
||||
sender.sendMessage(rendered);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Tristate getPermissionValue(SingletonPlayer sender, String node) {
|
||||
return Tristate.TRUE;
|
||||
protected Tristate getPermissionValue(StandaloneSender sender, String node) {
|
||||
return sender.getPermissionValue(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasPermission(SingletonPlayer sender, String node) {
|
||||
protected boolean hasPermission(StandaloneSender sender, String node) {
|
||||
return sender.hasPermission(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performCommand(StandaloneSender sender, String command) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isConsole(StandaloneSender sender) {
|
||||
return sender.isConsole();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldSplitNewlines(StandaloneSender sender) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performCommand(SingletonPlayer sender, String command) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isConsole(SingletonPlayer sender) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -29,39 +29,45 @@ import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.context.manager.ContextManager;
|
||||
import me.lucko.luckperms.common.context.manager.QueryOptionsCache;
|
||||
import me.lucko.luckperms.standalone.LPStandalonePlugin;
|
||||
import me.lucko.luckperms.standalone.app.integration.SingletonPlayer;
|
||||
import me.lucko.luckperms.standalone.app.integration.StandaloneSender;
|
||||
import me.lucko.luckperms.standalone.app.integration.StandaloneUser;
|
||||
import net.luckperms.api.context.ImmutableContextSet;
|
||||
import net.luckperms.api.query.QueryOptions;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class StandaloneContextManager extends ContextManager<SingletonPlayer, SingletonPlayer> {
|
||||
private final QueryOptionsCache<SingletonPlayer> singletonCache = new QueryOptionsCache<>(SingletonPlayer.INSTANCE, this);
|
||||
public class StandaloneContextManager extends ContextManager<StandaloneSender, StandaloneSender> {
|
||||
private final QueryOptionsCache<StandaloneSender> singletonCache = new QueryOptionsCache<>(StandaloneUser.INSTANCE, this);
|
||||
|
||||
public StandaloneContextManager(LPStandalonePlugin plugin) {
|
||||
super(plugin, SingletonPlayer.class, SingletonPlayer.class);
|
||||
super(plugin, StandaloneSender.class, StandaloneSender.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId(SingletonPlayer player) {
|
||||
public UUID getUniqueId(StandaloneSender player) {
|
||||
return player.getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryOptionsCache<SingletonPlayer> getCacheFor(SingletonPlayer subject) {
|
||||
public QueryOptionsCache<StandaloneSender> getCacheFor(StandaloneSender subject) {
|
||||
if (subject == null) {
|
||||
throw new NullPointerException("subject");
|
||||
}
|
||||
return this.singletonCache;
|
||||
if (subject == StandaloneUser.INSTANCE) {
|
||||
return this.singletonCache;
|
||||
}
|
||||
|
||||
// just return a new one every time - not optimal but this case should only be hit using unit tests anyway
|
||||
return new QueryOptionsCache<>(subject, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void invalidateCache(SingletonPlayer subject) {
|
||||
protected void invalidateCache(StandaloneSender subject) {
|
||||
this.singletonCache.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryOptions formQueryOptions(SingletonPlayer subject, ImmutableContextSet contextSet) {
|
||||
public QueryOptions formQueryOptions(StandaloneSender subject, ImmutableContextSet contextSet) {
|
||||
QueryOptions.Builder queryOptions = this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_QUERY_OPTIONS).toBuilder();
|
||||
return queryOptions.context(contextSet).build();
|
||||
}
|
||||
|
@@ -29,9 +29,9 @@ import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.node.types.Inheritance;
|
||||
import me.lucko.luckperms.standalone.app.integration.CommandExecutor;
|
||||
import me.lucko.luckperms.standalone.app.integration.SingletonPlayer;
|
||||
import me.lucko.luckperms.standalone.utils.CommandTester;
|
||||
import me.lucko.luckperms.standalone.utils.TestPluginProvider;
|
||||
import me.lucko.luckperms.standalone.utils.TestSender;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import net.luckperms.api.event.log.LogNotifyEvent;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -54,6 +54,7 @@ public class CommandsIntegrationTest {
|
||||
|
||||
private static final Map<String, String> CONFIG = ImmutableMap.<String, String>builder()
|
||||
.put("log-notify", "false")
|
||||
.put("commands-rate-limit", "false")
|
||||
.build();
|
||||
|
||||
@Test
|
||||
@@ -61,7 +62,7 @@ public class CommandsIntegrationTest {
|
||||
TestPluginProvider.use(tempDir, CONFIG, (app, bootstrap, plugin) -> {
|
||||
CommandExecutor executor = app.getCommandExecutor();
|
||||
|
||||
new CommandTester(plugin, executor)
|
||||
new CommandTester(executor)
|
||||
.givenHasPermissions("luckperms.creategroup")
|
||||
.whenRunCommand("creategroup test")
|
||||
.thenExpect("[LP] test was successfully created.")
|
||||
@@ -97,9 +98,9 @@ public class CommandsIntegrationTest {
|
||||
"""
|
||||
)
|
||||
|
||||
.givenHasAllPermissions()
|
||||
.givenHasPermissions("luckperms.group.meta.set")
|
||||
.whenRunCommand("group test meta set hello world")
|
||||
.clearMessageBuffer()
|
||||
.thenExpect("[LP] Set meta key 'hello' to 'world' for test in context global.")
|
||||
|
||||
.givenHasPermissions("luckperms.group.setweight")
|
||||
.whenRunCommand("group test setweight 10")
|
||||
@@ -182,7 +183,7 @@ public class CommandsIntegrationTest {
|
||||
TestPluginProvider.use(tempDir, CONFIG, (app, bootstrap, plugin) -> {
|
||||
CommandExecutor executor = app.getCommandExecutor();
|
||||
|
||||
new CommandTester(plugin, executor)
|
||||
new CommandTester(executor)
|
||||
.whenRunCommand("creategroup test")
|
||||
.clearMessageBuffer()
|
||||
|
||||
@@ -262,7 +263,7 @@ public class CommandsIntegrationTest {
|
||||
TestPluginProvider.use(tempDir, CONFIG, (app, bootstrap, plugin) -> {
|
||||
CommandExecutor executor = app.getCommandExecutor();
|
||||
|
||||
new CommandTester(plugin, executor)
|
||||
new CommandTester(executor)
|
||||
.whenRunCommand("creategroup test")
|
||||
.whenRunCommand("creategroup test2")
|
||||
.whenRunCommand("creategroup test3")
|
||||
@@ -321,7 +322,7 @@ public class CommandsIntegrationTest {
|
||||
TestPluginProvider.use(tempDir, CONFIG, (app, bootstrap, plugin) -> {
|
||||
CommandExecutor executor = app.getCommandExecutor();
|
||||
|
||||
new CommandTester(plugin, executor)
|
||||
new CommandTester(executor)
|
||||
.whenRunCommand("creategroup test")
|
||||
.clearMessageBuffer()
|
||||
|
||||
@@ -445,7 +446,7 @@ public class CommandsIntegrationTest {
|
||||
plugin.getStorage().savePlayerData(UUID.fromString("c1d60c50-70b5-4722-8057-87767557e50d"), "Luck").join();
|
||||
plugin.getStorage().savePlayerData(UUID.fromString("069a79f4-44e9-4726-a5be-fca90e38aaf5"), "Notch").join();
|
||||
|
||||
new CommandTester(plugin, executor)
|
||||
new CommandTester(executor)
|
||||
.givenHasPermissions("luckperms.user.info")
|
||||
.whenRunCommand("user Luck info")
|
||||
.thenExpect("""
|
||||
@@ -508,7 +509,7 @@ public class CommandsIntegrationTest {
|
||||
|
||||
plugin.getStorage().savePlayerData(UUID.fromString("c1d60c50-70b5-4722-8057-87767557e50d"), "Luck").join();
|
||||
|
||||
new CommandTester(plugin, executor)
|
||||
new CommandTester(executor)
|
||||
.givenHasPermissions("luckperms.user.permission.set")
|
||||
.whenRunCommand("user Luck permission set test.node true")
|
||||
.thenExpect("[LP] Set test.node to true for luck in context global.")
|
||||
@@ -587,7 +588,7 @@ public class CommandsIntegrationTest {
|
||||
|
||||
plugin.getStorage().savePlayerData(UUID.fromString("c1d60c50-70b5-4722-8057-87767557e50d"), "Luck").join();
|
||||
|
||||
new CommandTester(plugin, executor)
|
||||
new CommandTester(executor)
|
||||
.whenRunCommand("creategroup test2")
|
||||
.whenRunCommand("creategroup test3")
|
||||
.clearMessageBuffer()
|
||||
@@ -651,7 +652,7 @@ public class CommandsIntegrationTest {
|
||||
|
||||
plugin.getStorage().savePlayerData(UUID.fromString("c1d60c50-70b5-4722-8057-87767557e50d"), "Luck").join();
|
||||
|
||||
new CommandTester(plugin, executor)
|
||||
new CommandTester(executor)
|
||||
.givenHasPermissions("luckperms.user.meta.info")
|
||||
.whenRunCommand("user Luck meta info")
|
||||
.thenExpect("""
|
||||
@@ -773,7 +774,7 @@ public class CommandsIntegrationTest {
|
||||
TestPluginProvider.use(tempDir, CONFIG, (app, bootstrap, plugin) -> {
|
||||
CommandExecutor executor = app.getCommandExecutor();
|
||||
|
||||
new CommandTester(plugin, executor)
|
||||
new CommandTester(executor)
|
||||
.givenHasPermissions("luckperms.createtrack")
|
||||
.whenRunCommand("createtrack test1")
|
||||
.thenExpect("[LP] test1 was successfully created.")
|
||||
@@ -884,7 +885,7 @@ public class CommandsIntegrationTest {
|
||||
|
||||
plugin.getStorage().savePlayerData(UUID.fromString("c1d60c50-70b5-4722-8057-87767557e50d"), "Luck").join();
|
||||
|
||||
new CommandTester(plugin, executor)
|
||||
new CommandTester(executor)
|
||||
.whenRunCommand("createtrack staff")
|
||||
.whenRunCommand("createtrack premium")
|
||||
|
||||
@@ -1023,7 +1024,7 @@ public class CommandsIntegrationTest {
|
||||
|
||||
plugin.getStorage().savePlayerData(UUID.fromString("c1d60c50-70b5-4722-8057-87767557e50d"), "Luck").join();
|
||||
|
||||
new CommandTester(plugin, executor)
|
||||
new CommandTester(executor)
|
||||
.whenRunCommand("creategroup test")
|
||||
.whenRunCommand("user Luck permission set hello.world true server=survival")
|
||||
.whenRunCommand("group test permission set hello.world true world=nether")
|
||||
@@ -1045,12 +1046,12 @@ public class CommandsIntegrationTest {
|
||||
.givenHasPermissions("luckperms.search")
|
||||
.whenRunCommand("search ~~ group.%")
|
||||
.thenExpect("""
|
||||
[LP] Searching for users and groups with permissions ~~ group.%...
|
||||
[LP] Found 2 entries from 2 users and 0 groups.
|
||||
[LP] Showing user entries: (page 1 of 1 - 2 entries)
|
||||
> luck - (group.test) - true
|
||||
> luck - (group.default) - true
|
||||
"""
|
||||
[LP] Searching for users and groups with permissions ~~ group.%...
|
||||
[LP] Found 2 entries from 2 users and 0 groups.
|
||||
[LP] Showing user entries: (page 1 of 1 - 2 entries)
|
||||
> luck - (group.test) - true
|
||||
> luck - (group.default) - true
|
||||
"""
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -1068,14 +1069,16 @@ public class CommandsIntegrationTest {
|
||||
|
||||
CountDownLatch completed = new CountDownLatch(1);
|
||||
|
||||
SingletonPlayer.INSTANCE.addMessageSink(component -> {
|
||||
TestSender console = new TestSender();
|
||||
console.setConsole(true);
|
||||
console.addMessageSink(component -> {
|
||||
String plain = PlainTextComponentSerializer.plainText().serialize(component);
|
||||
if (plain.contains("Bulk update completed successfully")) {
|
||||
completed.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
new CommandTester(plugin, executor)
|
||||
new CommandTester(executor, console)
|
||||
.whenRunCommand("creategroup moderator")
|
||||
.whenRunCommand("creategroup admin")
|
||||
.whenRunCommand("user Luck parent add moderator server=survival")
|
||||
@@ -1084,7 +1087,6 @@ public class CommandsIntegrationTest {
|
||||
.whenRunCommand("group moderator rename mod")
|
||||
.clearMessageBuffer()
|
||||
|
||||
.givenHasPermissions("luckperms.bulkupdate")
|
||||
.whenRunCommand("bulkupdate all update permission group.mod \"permission == group.moderator\"")
|
||||
.thenExpectStartsWith("[LP] Running bulk update.");
|
||||
|
||||
@@ -1113,6 +1115,151 @@ public class CommandsIntegrationTest {
|
||||
),
|
||||
notchUser.normalData().asSet()
|
||||
);
|
||||
|
||||
// test normal players are unable to use
|
||||
new CommandTester(executor)
|
||||
.givenHasPermissions("luckperms.bulkupdate")
|
||||
.whenRunCommand("bulkupdate all update permission group.mod \"permission == group.moderator\"")
|
||||
.thenExpect("[LP] The bulk update command can only be used from the console.");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLogCommands(@TempDir Path tempDir) {
|
||||
Map<String, String> config = new HashMap<>(CONFIG);
|
||||
config.put("log-notify", "true");
|
||||
config.put("log-synchronously-in-commands", "true");
|
||||
|
||||
TestPluginProvider.use(tempDir, config, (app, bootstrap, plugin) -> {
|
||||
CommandExecutor executor = app.getCommandExecutor();
|
||||
|
||||
UUID luckUniqueId = UUID.fromString("c1d60c50-70b5-4722-8057-87767557e50d");
|
||||
|
||||
plugin.getStorage().savePlayerData(luckUniqueId, "Luck").join();
|
||||
plugin.getStorage().savePlayerData(UUID.fromString("069a79f4-44e9-4726-a5be-fca90e38aaf5"), "Notch").join();
|
||||
|
||||
TestSender testSender = new TestSender();
|
||||
testSender.setUniqueId(luckUniqueId);
|
||||
testSender.setName("Luck");
|
||||
|
||||
new CommandTester(executor, testSender)
|
||||
.whenRunCommand("group default permission set hello");
|
||||
|
||||
new CommandTester(executor)
|
||||
.whenRunCommand("creategroup moderator")
|
||||
.whenRunCommand("creategroup admin")
|
||||
.whenRunCommand("createtrack staff")
|
||||
.whenRunCommand("user Luck parent add moderator server=survival")
|
||||
.whenRunCommand("user Notch parent add moderator")
|
||||
.whenRunCommand("group admin parent add moderator")
|
||||
.whenRunCommand("group moderator rename mod")
|
||||
.whenRunCommand("user Luck permission set test.1")
|
||||
.whenRunCommand("user Luck permission set test.2 false")
|
||||
.whenRunCommand("user Luck permission set test.3 server=survival")
|
||||
.whenRunCommand("user Luck permission settemp test.4 true 1h")
|
||||
.whenRunCommand("user Luck permission settemp test.5 false 2d")
|
||||
.clearMessageBuffer()
|
||||
|
||||
.givenHasPermissions("luckperms.log.userhistory")
|
||||
.whenRunCommand("log userhistory Luck")
|
||||
.thenExpectReplacing("\\ds ago", "1m ago", """
|
||||
[LP] Showing history for user luck (page 1 of 1)
|
||||
[LP] #1 (1m ago) (StandaloneUser) [U] (luck)
|
||||
[LP] > permission settemp test.5 false 2d
|
||||
[LP] #2 (1m ago) (StandaloneUser) [U] (luck)
|
||||
[LP] > permission settemp test.4 true 1h
|
||||
[LP] #3 (1m ago) (StandaloneUser) [U] (luck)
|
||||
[LP] > permission set test.3 true server=survival
|
||||
[LP] #4 (1m ago) (StandaloneUser) [U] (luck)
|
||||
[LP] > permission set test.2 false
|
||||
[LP] #5 (1m ago) (StandaloneUser) [U] (luck)
|
||||
[LP] > permission set test.1 true
|
||||
[LP] #6 (1m ago) (StandaloneUser) [U] (luck)
|
||||
[LP] > parent add moderator server=survival
|
||||
"""
|
||||
)
|
||||
|
||||
.givenHasPermissions("luckperms.log.grouphistory")
|
||||
.whenRunCommand("log grouphistory admin")
|
||||
.thenExpectReplacing("\\ds ago", "1m ago", """
|
||||
[LP] Showing history for group admin (page 1 of 1)
|
||||
[LP] #1 (1m ago) (StandaloneUser) [G] (admin)
|
||||
[LP] > parent add moderator
|
||||
[LP] #2 (1m ago) (StandaloneUser) [G] (admin)
|
||||
[LP] > create
|
||||
"""
|
||||
)
|
||||
|
||||
.givenHasPermissions("luckperms.log.trackhistory")
|
||||
.whenRunCommand("log trackhistory staff")
|
||||
.thenExpectReplacing("\\ds ago", "1m ago", """
|
||||
[LP] Showing history for track staff (page 1 of 1)
|
||||
[LP] #1 (1m ago) (StandaloneUser) [T] (staff)
|
||||
[LP] > create
|
||||
"""
|
||||
)
|
||||
|
||||
.givenHasPermissions("luckperms.log.recent")
|
||||
.whenRunCommand("log recent")
|
||||
.thenExpectReplacing("\\ds ago", "1m ago", """
|
||||
[LP] Showing recent actions (page 1 of 2)
|
||||
[LP] #1 (1m ago) (StandaloneUser) [U] (luck)
|
||||
[LP] > permission settemp test.5 false 2d
|
||||
[LP] #2 (1m ago) (StandaloneUser) [U] (luck)
|
||||
[LP] > permission settemp test.4 true 1h
|
||||
[LP] #3 (1m ago) (StandaloneUser) [U] (luck)
|
||||
[LP] > permission set test.3 true server=survival
|
||||
[LP] #4 (1m ago) (StandaloneUser) [U] (luck)
|
||||
[LP] > permission set test.2 false
|
||||
[LP] #5 (1m ago) (StandaloneUser) [U] (luck)
|
||||
[LP] > permission set test.1 true
|
||||
[LP] #6 (1m ago) (StandaloneUser) [G] (moderator)
|
||||
[LP] > rename mod
|
||||
[LP] #7 (1m ago) (StandaloneUser) [G] (admin)
|
||||
[LP] > parent add moderator
|
||||
[LP] #8 (1m ago) (StandaloneUser) [U] (notch)
|
||||
[LP] > parent add moderator
|
||||
[LP] #9 (1m ago) (StandaloneUser) [U] (luck)
|
||||
[LP] > parent add moderator server=survival
|
||||
[LP] #10 (1m ago) (StandaloneUser) [T] (staff)
|
||||
[LP] > create
|
||||
"""
|
||||
)
|
||||
|
||||
.givenHasPermissions("luckperms.log.recent")
|
||||
.whenRunCommand("log recent 2")
|
||||
.thenExpectReplacing("\\ds ago", "1m ago", """
|
||||
[LP] Showing recent actions (page 2 of 2)
|
||||
[LP] #11 (1m ago) (StandaloneUser) [G] (admin)
|
||||
[LP] > create
|
||||
[LP] #12 (1m ago) (StandaloneUser) [G] (moderator)
|
||||
[LP] > create
|
||||
[LP] #13 (1m ago) (Luck) [G] (default)
|
||||
[LP] > permission set hello true
|
||||
"""
|
||||
)
|
||||
|
||||
.givenHasPermissions("luckperms.log.recent")
|
||||
.whenRunCommand("log recent 3")
|
||||
.thenExpect("[LP] Invalid page number. Please enter a value between 1 and 2.")
|
||||
|
||||
.givenHasPermissions("luckperms.log.search")
|
||||
.whenRunCommand("log search hello")
|
||||
.thenExpectReplacing("\\ds ago", "1m ago", """
|
||||
[LP] Showing recent actions for query hello (page 1 of 1)
|
||||
[LP] #1 (1m ago) (Luck) [G] (default)
|
||||
[LP] > permission set hello true
|
||||
"""
|
||||
)
|
||||
|
||||
.givenHasPermissions("luckperms.log.recent")
|
||||
.whenRunCommand("log recent Luck")
|
||||
.thenExpectReplacing("\\ds ago", "1m ago", """
|
||||
[LP] Showing recent actions by Luck (page 1 of 1)
|
||||
[LP] #1 (1m ago) (Luck) [G] (default)
|
||||
[LP] > permission set hello true
|
||||
"""
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1121,7 +1268,7 @@ public class CommandsIntegrationTest {
|
||||
TestPluginProvider.use(tempDir, CONFIG, (app, bootstrap, plugin) -> {
|
||||
CommandExecutor executor = app.getCommandExecutor();
|
||||
|
||||
new CommandTester(plugin, executor)
|
||||
new CommandTester(executor)
|
||||
.givenHasPermissions("luckperms.user.info")
|
||||
.whenRunCommand("user unknown info")
|
||||
.thenExpect("[LP] A user for unknown could not be found.")
|
||||
@@ -1154,7 +1301,7 @@ public class CommandsIntegrationTest {
|
||||
CommandExecutor executor = app.getCommandExecutor();
|
||||
String version = "v" + bootstrap.getVersion();
|
||||
|
||||
new CommandTester(plugin, executor)
|
||||
new CommandTester(executor)
|
||||
.givenHasPermissions(/* empty */)
|
||||
|
||||
.whenRunCommand("")
|
||||
@@ -1188,7 +1335,10 @@ public class CommandsIntegrationTest {
|
||||
// by default, notifications are not sent to the user who initiated the event - override that
|
||||
app.getApi().getEventBus().subscribe(LogNotifyEvent.class, e -> e.setCancelled(false));
|
||||
|
||||
new CommandTester(plugin, executor)
|
||||
TestSender sender = new TestSender();
|
||||
plugin.addOnlineSender(sender);
|
||||
|
||||
new CommandTester(executor, sender)
|
||||
.givenHasPermissions("luckperms.group.permission.set", "luckperms.log.notify")
|
||||
.whenRunCommand("group default permission set hello.world true server=test")
|
||||
.thenExpect("""
|
||||
@@ -1208,7 +1358,7 @@ public class CommandsIntegrationTest {
|
||||
TestPluginProvider.use(tempDir, config, (app, bootstrap, plugin) -> {
|
||||
CommandExecutor executor = app.getCommandExecutor();
|
||||
|
||||
new CommandTester(plugin, executor)
|
||||
new CommandTester(executor)
|
||||
.givenHasPermissions("luckperms.group.permission.set")
|
||||
.whenRunCommand("group default permission set hello.world true server=test")
|
||||
.thenExpect("[LP] You do not have permission to use this command!")
|
||||
|
@@ -36,7 +36,7 @@ import me.lucko.luckperms.common.util.Predicates;
|
||||
import me.lucko.luckperms.common.util.gson.GsonProvider;
|
||||
import me.lucko.luckperms.common.webeditor.WebEditorRequest;
|
||||
import me.lucko.luckperms.common.webeditor.WebEditorSession;
|
||||
import me.lucko.luckperms.standalone.app.integration.SingletonPlayer;
|
||||
import me.lucko.luckperms.standalone.app.integration.StandaloneUser;
|
||||
import me.lucko.luckperms.standalone.utils.TestPluginProvider;
|
||||
import net.luckperms.api.model.data.DataType;
|
||||
import okhttp3.OkHttpClient;
|
||||
@@ -115,7 +115,7 @@ public class WebEditorIntegrationTest {
|
||||
assertFalse(holders.isEmpty());
|
||||
|
||||
// create a new editor session
|
||||
Sender sender = plugin.getSenderFactory().wrap(SingletonPlayer.INSTANCE);
|
||||
Sender sender = plugin.getSenderFactory().wrap(StandaloneUser.INSTANCE);
|
||||
WebEditorSession session = WebEditorSession.create(holders, Collections.emptyList(), sender, "lp", plugin);
|
||||
String bytebinKey = session.open();
|
||||
String bytesocksKey = session.getSocket().getSocket().channelId();
|
||||
|
@@ -26,14 +26,12 @@
|
||||
package me.lucko.luckperms.standalone.utils;
|
||||
|
||||
import me.lucko.luckperms.standalone.app.integration.CommandExecutor;
|
||||
import me.lucko.luckperms.standalone.app.integration.SingletonPlayer;
|
||||
import me.lucko.luckperms.standalone.utils.TestPluginBootstrap.TestPlugin;
|
||||
import me.lucko.luckperms.standalone.utils.TestPluginBootstrap.TestSenderFactory;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import net.luckperms.api.util.Tristate;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.intellij.lang.annotations.RegExp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -57,12 +55,12 @@ public final class CommandTester implements Consumer<Component>, Function<String
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(CommandTester.class);
|
||||
|
||||
/** The test plugin */
|
||||
private final TestPlugin plugin;
|
||||
|
||||
/** The LuckPerms command executor */
|
||||
private final CommandExecutor executor;
|
||||
|
||||
/** The test player */
|
||||
private final TestSender sender;
|
||||
|
||||
/** The current map of permissions held by the fake executor */
|
||||
private Map<String, Tristate> permissions = null;
|
||||
|
||||
@@ -72,9 +70,16 @@ public final class CommandTester implements Consumer<Component>, Function<String
|
||||
/** A buffer of messages received by the test tool */
|
||||
private final List<Component> messageBuffer = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
public CommandTester(TestPlugin plugin, CommandExecutor executor) {
|
||||
this.plugin = plugin;
|
||||
public CommandTester(CommandExecutor executor, TestSender sender) {
|
||||
this.executor = executor;
|
||||
this.sender = sender;
|
||||
|
||||
this.sender.setPermissionChecker(this);
|
||||
this.sender.addMessageSink(this);
|
||||
}
|
||||
|
||||
public CommandTester(CommandExecutor executor) {
|
||||
this(executor, new TestSender());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,15 +143,7 @@ public final class CommandTester implements Consumer<Component>, Function<String
|
||||
*/
|
||||
public CommandTester whenRunCommand(String command) {
|
||||
LOGGER.info("Executing test command: " + command);
|
||||
|
||||
TestSenderFactory senderFactory = this.plugin.getSenderFactory();
|
||||
senderFactory.setPermissionChecker(this);
|
||||
SingletonPlayer.INSTANCE.addMessageSink(this);
|
||||
|
||||
this.executor.execute(command).join();
|
||||
|
||||
SingletonPlayer.INSTANCE.removeMessageSink(this);
|
||||
senderFactory.resetPermissionChecker();
|
||||
this.executor.execute(this.sender, command).join();
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -184,6 +181,23 @@ public final class CommandTester implements Consumer<Component>, Function<String
|
||||
return this.clearMessageBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the current contents of the message buffer matches the given input string.
|
||||
*
|
||||
* @param expected the expected contents
|
||||
* @return this
|
||||
*/
|
||||
public CommandTester thenExpectReplacing(@RegExp String regex, String replacement, String expected) {
|
||||
String actual = this.renderBuffer().replaceAll(regex, replacement);
|
||||
assertEquals(expected.trim(), actual.trim());
|
||||
|
||||
if (this.permissions != null) {
|
||||
assertEquals(this.checkedPermissions, this.permissions.keySet());
|
||||
}
|
||||
|
||||
return this.clearMessageBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the message buffer.
|
||||
*
|
||||
|
@@ -27,21 +27,19 @@ package me.lucko.luckperms.standalone.utils;
|
||||
|
||||
import me.lucko.luckperms.common.dependencies.Dependency;
|
||||
import me.lucko.luckperms.common.dependencies.DependencyManager;
|
||||
import me.lucko.luckperms.common.locale.TranslationManager;
|
||||
import me.lucko.luckperms.common.plugin.classpath.ClassPathAppender;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.storage.StorageType;
|
||||
import me.lucko.luckperms.standalone.LPStandaloneBootstrap;
|
||||
import me.lucko.luckperms.standalone.LPStandalonePlugin;
|
||||
import me.lucko.luckperms.standalone.StandaloneSenderFactory;
|
||||
import me.lucko.luckperms.standalone.app.LuckPermsApplication;
|
||||
import me.lucko.luckperms.standalone.app.integration.SingletonPlayer;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.luckperms.api.util.Tristate;
|
||||
import me.lucko.luckperms.standalone.app.integration.StandaloneSender;
|
||||
import me.lucko.luckperms.standalone.app.integration.StandaloneUser;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* An extension standalone bootstrap for testing.
|
||||
@@ -50,7 +48,7 @@ import java.util.function.Function;
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>Dependency loading system is replaced with a no-op stub that delegates to the test classloader</li>
|
||||
* <li>Sender factory is extended and allows for permission checks to be intercepted</li>
|
||||
* <li>Ability to register additional sender instances as being online</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
@@ -81,7 +79,7 @@ public final class TestPluginBootstrap extends LPStandaloneBootstrap {
|
||||
}
|
||||
|
||||
public static final class TestPlugin extends LPStandalonePlugin {
|
||||
private TestSenderFactory senderFactory;
|
||||
private final Set<StandaloneSender> onlineSenders = new CopyOnWriteArraySet<>();
|
||||
|
||||
TestPlugin(LPStandaloneBootstrap bootstrap) {
|
||||
super(bootstrap);
|
||||
@@ -93,13 +91,15 @@ public final class TestPluginBootstrap extends LPStandaloneBootstrap {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupSenderFactory() {
|
||||
this.senderFactory = new TestSenderFactory(this);
|
||||
public Stream<Sender> getOnlineSenders() {
|
||||
return Stream.concat(
|
||||
Stream.of(StandaloneUser.INSTANCE),
|
||||
this.onlineSenders.stream()
|
||||
).map(player -> getSenderFactory().wrap(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TestSenderFactory getSenderFactory() {
|
||||
return this.senderFactory;
|
||||
public void addOnlineSender(StandaloneSender player) {
|
||||
this.onlineSenders.add(player);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,46 +125,4 @@ public final class TestPluginBootstrap extends LPStandaloneBootstrap {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static final class TestSenderFactory extends StandaloneSenderFactory {
|
||||
|
||||
private Function<String, Tristate> permissionChecker;
|
||||
|
||||
public TestSenderFactory(LPStandalonePlugin plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
public void setPermissionChecker(Function<String, Tristate> permissionChecker) {
|
||||
this.permissionChecker = permissionChecker;
|
||||
}
|
||||
|
||||
public void resetPermissionChecker() {
|
||||
this.permissionChecker = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean consoleHasAllPermissions() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sendMessage(SingletonPlayer sender, Component message) {
|
||||
Component rendered = TranslationManager.render(message, Locale.ENGLISH);
|
||||
sender.sendMessage(rendered);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Tristate getPermissionValue(SingletonPlayer sender, String node) {
|
||||
return this.permissionChecker == null
|
||||
? super.getPermissionValue(sender, node)
|
||||
: this.permissionChecker.apply(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasPermission(SingletonPlayer sender, String node) {
|
||||
return this.permissionChecker == null
|
||||
? super.hasPermission(sender, node)
|
||||
: this.permissionChecker.apply(node).asBoolean();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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.standalone.utils;
|
||||
|
||||
import me.lucko.luckperms.standalone.app.integration.StandaloneSender;
|
||||
import me.lucko.luckperms.standalone.app.integration.StandaloneUser;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.luckperms.api.util.Tristate;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class TestSender implements StandaloneSender {
|
||||
|
||||
private final Set<Consumer<Component>> messageSinks;
|
||||
|
||||
private String name = "StandaloneUser";
|
||||
private UUID uniqueId = UUID.randomUUID();
|
||||
private boolean isConsole = false;
|
||||
|
||||
private Function<String, Tristate> permissionChecker;
|
||||
|
||||
public TestSender() {
|
||||
this.messageSinks = new CopyOnWriteArraySet<>();
|
||||
this.messageSinks.add(StandaloneUser.INSTANCE::sendMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return this.uniqueId;
|
||||
}
|
||||
|
||||
public void setUniqueId(UUID uuid) {
|
||||
this.uniqueId = uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(Component component) {
|
||||
for (Consumer<Component> sink : this.messageSinks) {
|
||||
sink.accept(component);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tristate getPermissionValue(String permission) {
|
||||
return this.permissionChecker == null
|
||||
? Tristate.TRUE
|
||||
: this.permissionChecker.apply(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return getPermissionValue(permission).asBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConsole() {
|
||||
return this.isConsole;
|
||||
}
|
||||
|
||||
public void setConsole(boolean console) {
|
||||
this.isConsole = console;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return Locale.ENGLISH;
|
||||
}
|
||||
|
||||
public void setPermissionChecker(Function<String, Tristate> permissionChecker) {
|
||||
this.permissionChecker = permissionChecker;
|
||||
}
|
||||
|
||||
public void addMessageSink(Consumer<Component> sink) {
|
||||
this.messageSinks.add(sink);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user