diff --git a/api/src/main/java/me/lucko/luckperms/api/FullySatisfiedContexts.java b/api/src/main/java/me/lucko/luckperms/api/FullySatisfiedContexts.java index 9c05eba7..f2205b09 100644 --- a/api/src/main/java/me/lucko/luckperms/api/FullySatisfiedContexts.java +++ b/api/src/main/java/me/lucko/luckperms/api/FullySatisfiedContexts.java @@ -1,3 +1,28 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * 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.api; import me.lucko.luckperms.api.caching.MetaContexts; diff --git a/api/src/main/java/me/lucko/luckperms/api/event/log/LogBroadcastEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/log/LogBroadcastEvent.java index 8d676d4a..00e8d51b 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/log/LogBroadcastEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/log/LogBroadcastEvent.java @@ -44,4 +44,31 @@ public interface LogBroadcastEvent extends LuckPermsEvent, Cancellable { @Nonnull LogEntry getEntry(); + /** + * Gets where the log entry originated from. + * + * @return the origin of the log + * @since 3.3 + */ + @Nonnull + Origin getOrigin(); + + /** + * Represents where a log entry is from + * + * @since 3.3 + */ + enum Origin { + + /** + * Represents a log entry which originated from the current server instance + */ + LOCAL, + + /** + * Represents a log entry which was sent to this server via the messaging service + */ + REMOTE + } + } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/log/LogNetworkPublishEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/log/LogNetworkPublishEvent.java new file mode 100644 index 00000000..54e4895c --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/event/log/LogNetworkPublishEvent.java @@ -0,0 +1,59 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * 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.api.event.log; + +import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.event.Cancellable; +import me.lucko.luckperms.api.event.LuckPermsEvent; + +import java.util.UUID; + +import javax.annotation.Nonnull; + +/** + * Called when a log is about to be published to the network via the MessagingService + * + * @since 3.3 + */ +public interface LogNetworkPublishEvent extends LuckPermsEvent, Cancellable { + + /** + * Gets the ID of the log entry being published + * + * @return the id of the log entry being published + */ + @Nonnull + UUID getLogId(); + + /** + * Gets the log entry to be published + * + * @return the log entry to be published + */ + @Nonnull + LogEntry getEntry(); + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/event/log/LogReceiveEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/log/LogReceiveEvent.java new file mode 100644 index 00000000..0752aa67 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/event/log/LogReceiveEvent.java @@ -0,0 +1,58 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * 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.api.event.log; + +import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.event.LuckPermsEvent; + +import java.util.UUID; + +import javax.annotation.Nonnull; + +/** + * Called when a log entry is received via the MessagingService + * + * @since 3.3 + */ +public interface LogReceiveEvent extends LuckPermsEvent { + + /** + * Gets the ID of the log entry being received + * + * @return the id of the log entry being received + */ + @Nonnull + UUID getLogId(); + + /** + * Gets the log entry being received + * + * @return the log entry being received + */ + @Nonnull + LogEntry getEntry(); + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/event/sync/PreNetworkSyncEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/sync/PreNetworkSyncEvent.java index fec70ac0..a5241964 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/sync/PreNetworkSyncEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/sync/PreNetworkSyncEvent.java @@ -33,7 +33,7 @@ import java.util.UUID; import javax.annotation.Nonnull; /** - * Called before a network sync task runs + * Called before a received network sync task runs */ public interface PreNetworkSyncEvent extends LuckPermsEvent, Cancellable { diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java index d96b0788..bb1d0d6c 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java @@ -43,6 +43,7 @@ import me.lucko.luckperms.bukkit.model.LPPermissible; import me.lucko.luckperms.bukkit.processors.ChildPermissionProvider; import me.lucko.luckperms.bukkit.processors.DefaultsProvider; import me.lucko.luckperms.bukkit.vault.VaultHookManager; +import me.lucko.luckperms.common.actionlog.LogDispatcher; import me.lucko.luckperms.common.api.ApiHandler; import me.lucko.luckperms.common.api.ApiProvider; import me.lucko.luckperms.common.buffers.BufferedRequest; @@ -109,8 +110,7 @@ import java.util.stream.Collectors; @Getter public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin { - private Set ignoringLogs; - private Set uniqueConnections; + private long startTime; private LPBukkitScheduler scheduler; private BukkitCommand commandManager; @@ -139,6 +139,8 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin { private VerboseHandler verboseHandler; private BukkitSenderFactory senderFactory; private PermissionVault permissionVault; + private LogDispatcher logDispatcher; + private Set uniqueConnections = ConcurrentHashMap.newKeySet(); @Override public void onLoad() { @@ -182,11 +184,9 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin { private void enable() { startTime = System.currentTimeMillis(); LuckPermsPlugin.sendStartupBanner(getConsoleSender(), this); - - ignoringLogs = ConcurrentHashMap.newKeySet(); - uniqueConnections = ConcurrentHashMap.newKeySet(); - verboseHandler = new VerboseHandler(scheduler.getAsyncBukkitExecutor(), getVersion()); - permissionVault = new PermissionVault(scheduler.getAsyncBukkitExecutor()); + verboseHandler = new VerboseHandler(scheduler.asyncBukkit(), getVersion()); + permissionVault = new PermissionVault(scheduler.asyncBukkit()); + logDispatcher = new LogDispatcher(this); getLog().info("Loading configuration..."); configuration = new BukkitConfig(this); @@ -448,7 +448,6 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin { HandlerList.unregisterAll(this); // Null everything - ignoringLogs = null; vaultHookManager = null; configuration = null; userManager = null; @@ -472,6 +471,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin { verboseHandler = null; senderFactory = null; permissionVault = null; + logDispatcher = null; } public void tryVaultHook(boolean force) { diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitScheduler.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitScheduler.java index ec97590f..95c23e3c 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitScheduler.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitScheduler.java @@ -27,6 +27,7 @@ package me.lucko.luckperms.bukkit; import lombok.Getter; import lombok.Setter; +import lombok.experimental.Accessors; import me.lucko.luckperms.common.plugin.LuckPermsScheduler; @@ -43,10 +44,16 @@ public class LPBukkitScheduler implements LuckPermsScheduler { private final LPBukkitPlugin plugin; @Getter - private ExecutorService asyncLpExecutor; + @Accessors(fluent = true) + private ExecutorService asyncLp; + @Getter - private Executor asyncBukkitExecutor; - private Executor syncExecutor; + @Accessors(fluent = true) + private Executor asyncBukkit; + + @Getter + @Accessors(fluent = true) + private Executor sync; @Getter @Setter @@ -57,19 +64,14 @@ public class LPBukkitScheduler implements LuckPermsScheduler { public LPBukkitScheduler(LPBukkitPlugin plugin) { this.plugin = plugin; - this.asyncLpExecutor = Executors.newCachedThreadPool(); - this.asyncBukkitExecutor = r -> plugin.getServer().getScheduler().runTaskAsynchronously(plugin, r); - this.syncExecutor = r -> plugin.getServer().getScheduler().runTask(plugin, r); + this.asyncLp = Executors.newCachedThreadPool(); + this.asyncBukkit = r -> plugin.getServer().getScheduler().runTaskAsynchronously(plugin, r); + this.sync = r -> plugin.getServer().getScheduler().runTask(plugin, r); } @Override public Executor async() { - return useBukkitAsync ? asyncBukkitExecutor : asyncLpExecutor; - } - - @Override - public Executor sync() { - return syncExecutor; + return useBukkitAsync ? asyncBukkit : asyncLp; } @Override @@ -108,9 +110,9 @@ public class LPBukkitScheduler implements LuckPermsScheduler { public void shutdown() { tasks.forEach(BukkitTask::cancel); // wait for executor - asyncLpExecutor.shutdown(); + asyncLp.shutdown(); try { - asyncLpExecutor.awaitTermination(30, TimeUnit.SECONDS); + asyncLp.awaitTermination(30, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } diff --git a/bukkit/src/main/resources/config.yml b/bukkit/src/main/resources/config.yml index 4007a017..b678fe46 100644 --- a/bukkit/src/main/resources/config.yml +++ b/bukkit/src/main/resources/config.yml @@ -328,6 +328,16 @@ messaging-service: none # If LuckPerms should automatically push updates after a change has been made with a command. auto-push-updates: true +# If LuckPerms should push logging entries to connected servers via the messaging service. +push-log-entries: true + +# If LuckPerms should broadcast received logging entries to players on this platform. +# +# If you have LuckPerms installed on your backend servers as well as a BungeeCord proxy, you should +# set this option to false on either your backends or your proxies, to avoid players being messaged +# twice about log entries. +broadcast-received-log-entries: true + # Settings for Redis. # Port 6379 is used by default; set address to "host:port" if differs redis: diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java b/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java index 4c09d727..c9494a0b 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java @@ -37,6 +37,7 @@ import me.lucko.luckperms.bungee.contexts.BackendServerCalculator; import me.lucko.luckperms.bungee.messaging.BungeeMessagingService; import me.lucko.luckperms.bungee.messaging.RedisBungeeMessagingService; import me.lucko.luckperms.bungee.util.RedisBungeeUtil; +import me.lucko.luckperms.common.actionlog.LogDispatcher; import me.lucko.luckperms.common.api.ApiHandler; import me.lucko.luckperms.common.api.ApiProvider; import me.lucko.luckperms.common.buffers.BufferedRequest; @@ -93,8 +94,7 @@ import java.util.stream.Collectors; @Getter public class LPBungeePlugin extends Plugin implements LuckPermsPlugin { - private final Set ignoringLogs = ConcurrentHashMap.newKeySet(); - private Set uniqueConnections = ConcurrentHashMap.newKeySet(); + private long startTime; private LuckPermsScheduler scheduler; private CommandManager commandManager; @@ -116,6 +116,8 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin { private VerboseHandler verboseHandler; private BungeeSenderFactory senderFactory; private PermissionVault permissionVault; + private LogDispatcher logDispatcher; + private Set uniqueConnections = ConcurrentHashMap.newKeySet(); @Override public void onLoad() { @@ -134,6 +136,7 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin { LuckPermsPlugin.sendStartupBanner(getConsoleSender(), this); verboseHandler = new VerboseHandler(scheduler.async(), getVersion()); permissionVault = new PermissionVault(scheduler.async()); + logDispatcher = new LogDispatcher(this); getLog().info("Loading configuration..."); configuration = new BungeeConfig(this); diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/messaging/BungeeMessagingService.java b/bungee/src/main/java/me/lucko/luckperms/bungee/messaging/BungeeMessagingService.java index 31171d88..ce7e8347 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/messaging/BungeeMessagingService.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/messaging/BungeeMessagingService.java @@ -89,7 +89,7 @@ public class BungeeMessagingService extends AbstractMessagingService implements onMessage(e.getTag(), msg, u -> { // Forward to other servers - plugin.doAsync(() -> sendMessage(CHANNEL, "update:" + u.toString())); + plugin.doAsync(() -> sendMessage(CHANNEL, u)); }); } } diff --git a/bungee/src/main/resources/config.yml b/bungee/src/main/resources/config.yml index 5cbaeb35..435ac60a 100644 --- a/bungee/src/main/resources/config.yml +++ b/bungee/src/main/resources/config.yml @@ -263,6 +263,16 @@ messaging-service: none # If LuckPerms should automatically push updates after a change has been made with a command. auto-push-updates: true +# If LuckPerms should push logging entries to connected servers via the messaging service. +push-log-entries: true + +# If LuckPerms should broadcast received logging entries to players on this platform. +# +# If you have LuckPerms installed on your backend servers as well as a BungeeCord proxy, you should +# set this option to false on either your backends or your proxies, to avoid players being messaged +# twice about log entries. +broadcast-received-log-entries: false + # Settings for Redis. # Port 6379 is used by default; set address to "host:port" if differs redis: diff --git a/common/src/main/java/me/lucko/luckperms/common/actionlog/ExtendedLogEntry.java b/common/src/main/java/me/lucko/luckperms/common/actionlog/ExtendedLogEntry.java index f093aafe..40a7cca0 100644 --- a/common/src/main/java/me/lucko/luckperms/common/actionlog/ExtendedLogEntry.java +++ b/common/src/main/java/me/lucko/luckperms/common/actionlog/ExtendedLogEntry.java @@ -25,11 +25,12 @@ package me.lucko.luckperms.common.actionlog; +import com.google.common.collect.Maps; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + import me.lucko.luckperms.api.LogEntry; import me.lucko.luckperms.common.commands.sender.Sender; -import me.lucko.luckperms.common.config.ConfigKeys; -import me.lucko.luckperms.common.constants.CommandPermission; -import me.lucko.luckperms.common.locale.Message; import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.PermissionHolder; import me.lucko.luckperms.common.model.Track; @@ -37,7 +38,8 @@ import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.utils.DateUtil; -import java.util.List; +import java.util.Map; +import java.util.UUID; /** * An extended version of {@link LogEntry}, with helper methods for @@ -52,36 +54,41 @@ public class ExtendedLogEntry extends LogEntry { return (ExtendedLogEntry) super.copy(); } - public void submit(LuckPermsPlugin plugin) { - submit(plugin, null); + public void submit(LuckPermsPlugin plugin, Sender sender) { + plugin.getLogDispatcher().dispatch(this, sender); } - public void submit(LuckPermsPlugin plugin, Sender sender) { - if (!plugin.getApiProvider().getEventFactory().handleLogPublish(false, this)) { - plugin.getStorage().logAction(this); + public static JsonObject serializeWithId(UUID id, LogEntry entry) { + JsonObject data = new JsonObject(); + + data.add("id", new JsonPrimitive(id.toString())); + data.add("actor", new JsonPrimitive(entry.getActor().toString())); + data.add("actorName", new JsonPrimitive(entry.getActorName())); + data.add("type", new JsonPrimitive(entry.getEntryType().name())); + if (entry.getActed() != null) { + data.add("acted", new JsonPrimitive(entry.getActed().toString())); } + data.add("actedName", new JsonPrimitive(entry.getActedName())); + data.add("action", new JsonPrimitive(entry.getAction())); - if (plugin.getApiProvider().getEventFactory().handleLogBroadcast(!plugin.getConfiguration().get(ConfigKeys.LOG_NOTIFY), this)) { - return; + return data; + } + + public static Map.Entry deserialize(JsonObject object) { + LogEntry.LogEntryBuilder builder = LogEntry.builder(); + + UUID id = UUID.fromString(object.get("id").getAsString()); + + builder.actor(UUID.fromString(object.get("actor").getAsString())); + builder.actorName(object.get("actorName").getAsString()); + builder.entryType(Type.valueOf(object.get("type").getAsString())); + if (object.has("acted")) { + builder.actor(UUID.fromString(object.get("acted").getAsString())); } + builder.actedName(object.get("actedName").getAsString()); + builder.action(object.get("action").getAsString()); - final String msg = super.getFormatted(); - - List senders = plugin.getOnlineSenders(); - senders.add(plugin.getConsoleSender()); - - if (sender == null) { - senders.stream() - .filter(CommandPermission.LOG_NOTIFY::isAuthorized) - .filter(s -> !plugin.getIgnoringLogs().contains(s.getUuid())) - .forEach(s -> Message.LOG.send(s, msg)); - } else { - senders.stream() - .filter(CommandPermission.LOG_NOTIFY::isAuthorized) - .filter(s -> !plugin.getIgnoringLogs().contains(s.getUuid())) - .filter(s -> !s.getUuid().equals(sender.getUuid())) - .forEach(s -> Message.LOG.send(s, msg)); - } + return Maps.immutableEntry(id, builder.build()); } public static class ExtendedLogEntryBuilder extends AbstractLogEntryBuilder { diff --git a/common/src/main/java/me/lucko/luckperms/common/actionlog/LogDispatcher.java b/common/src/main/java/me/lucko/luckperms/common/actionlog/LogDispatcher.java new file mode 100644 index 00000000..5296651b --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/actionlog/LogDispatcher.java @@ -0,0 +1,88 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * 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.actionlog; + +import lombok.RequiredArgsConstructor; + +import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.event.log.LogBroadcastEvent; +import me.lucko.luckperms.common.commands.impl.log.LogNotify; +import me.lucko.luckperms.common.commands.sender.Sender; +import me.lucko.luckperms.common.config.ConfigKeys; +import me.lucko.luckperms.common.constants.CommandPermission; +import me.lucko.luckperms.common.locale.Message; +import me.lucko.luckperms.common.messaging.InternalMessagingService; +import me.lucko.luckperms.common.messaging.NoopMessagingService; +import me.lucko.luckperms.common.plugin.LuckPermsPlugin; + +import java.util.List; + +@RequiredArgsConstructor +public class LogDispatcher { + private final LuckPermsPlugin plugin; + + public void dispatch(LogEntry entry, Sender sender) { + if (!plugin.getApiProvider().getEventFactory().handleLogPublish(false, entry)) { + plugin.getStorage().logAction(entry); + } + + InternalMessagingService messagingService = plugin.getMessagingService(); + if (!sender.isImport() && !(messagingService instanceof NoopMessagingService)) { + messagingService.pushLog(entry); + } + + if (!plugin.getApiProvider().getEventFactory().handleLogBroadcast(!plugin.getConfiguration().get(ConfigKeys.LOG_NOTIFY), entry, LogBroadcastEvent.Origin.LOCAL)) { + final String msg = entry.getFormatted(); + + List senders = plugin.getOnlineSenders(); + senders.add(plugin.getConsoleSender()); + + senders.stream() + .filter(CommandPermission.LOG_NOTIFY::isAuthorized) + .filter(s -> !LogNotify.isIgnoring(plugin, s.getUuid())) + .filter(s -> !s.getUuid().equals(sender.getUuid())) + .forEach(s -> Message.LOG.send(s, msg)); + } + } + + public void dispatchFromRemote(LogEntry entry) { + if (!plugin.getConfiguration().get(ConfigKeys.BROADCAST_RECEIVED_LOG_ENTRIES)) { + return; + } + + if (!plugin.getApiProvider().getEventFactory().handleLogBroadcast(!plugin.getConfiguration().get(ConfigKeys.LOG_NOTIFY), entry, LogBroadcastEvent.Origin.REMOTE)) { + final String msg = entry.getFormatted(); + + List senders = plugin.getOnlineSenders(); + senders.add(plugin.getConsoleSender()); + + senders.stream() + .filter(CommandPermission.LOG_NOTIFY::isAuthorized) + .filter(s -> !LogNotify.isIgnoring(plugin, s.getUuid())) + .forEach(s -> Message.LOG.send(s, msg)); + } + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/impl/log/LogNotify.java b/common/src/main/java/me/lucko/luckperms/common/commands/impl/log/LogNotify.java index 6d0a64aa..bfe82926 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/impl/log/LogNotify.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/impl/log/LogNotify.java @@ -25,6 +25,7 @@ package me.lucko.luckperms.common.commands.impl.log; +import me.lucko.luckperms.api.Node; import me.lucko.luckperms.common.actionlog.Log; import me.lucko.luckperms.common.commands.CommandException; import me.lucko.luckperms.common.commands.CommandResult; @@ -34,11 +35,13 @@ import me.lucko.luckperms.common.constants.CommandPermission; import me.lucko.luckperms.common.locale.CommandSpec; import me.lucko.luckperms.common.locale.LocaleManager; import me.lucko.luckperms.common.locale.Message; +import me.lucko.luckperms.common.model.User; +import me.lucko.luckperms.common.node.NodeFactory; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.utils.Predicates; import java.util.List; -import java.util.Set; +import java.util.Optional; import java.util.UUID; public class LogNotify extends SubCommand { @@ -46,45 +49,81 @@ public class LogNotify extends SubCommand { super(CommandSpec.LOG_NOTIFY.spec(locale), "notify", CommandPermission.LOG_NOTIFY, Predicates.notInRange(0, 1)); } + public static boolean isIgnoring(LuckPermsPlugin plugin, UUID uuid) { + User user = plugin.getUserManager().getIfLoaded(plugin.getUuidCache().getUUID(uuid)); + if (user == null) { + return false; + } + + Optional ret = user.getOwnNodes().stream() + .filter(n -> n.getPermission().equalsIgnoreCase("luckperms.log.notify.ignoring")) + .findFirst(); + + // if they don't have the perm, they're not ignoring + // if set to false, ignore it, return false + return ret.map(Node::getValue).orElse(false); + } + + private static void setIgnoring(LuckPermsPlugin plugin, UUID uuid, boolean state) { + User user = plugin.getUserManager().getIfLoaded(plugin.getUuidCache().getUUID(uuid)); + if (user == null) { + return; + } + + if (state) { + // add the perm + user.setPermission(NodeFactory.make("luckperms.log.notify.ignoring")); + } else { + // remove the perm + user.removeIf(n -> n.getPermission().equalsIgnoreCase("luckperms.log.notify.ignoring")); + } + + plugin.getStorage().force().saveUser(user).join(); + } + @Override public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Log log, List args, String label) throws CommandException { - final Set ignoring = plugin.getIgnoringLogs(); + if (sender.isConsole() || sender.isImport()) { + Message.LOG_NOTIFY_CONSOLE.send(sender); + return CommandResult.SUCCESS; + } + final UUID uuid = sender.getUuid(); if (args.size() == 0) { - if (ignoring.contains(uuid)) { + if (isIgnoring(plugin, uuid)) { // toggle on - ignoring.remove(uuid); + setIgnoring(plugin, uuid, false); Message.LOG_NOTIFY_TOGGLE_ON.send(sender); return CommandResult.SUCCESS; } // toggle off - ignoring.add(uuid); + setIgnoring(plugin, uuid, true); Message.LOG_NOTIFY_TOGGLE_OFF.send(sender); return CommandResult.SUCCESS; } if (args.get(0).equalsIgnoreCase("on")) { - if (!ignoring.contains(uuid)) { + if (!isIgnoring(plugin, uuid)) { // already on Message.LOG_NOTIFY_ALREADY_ON.send(sender); return CommandResult.STATE_ERROR; } // toggle on - ignoring.remove(uuid); + setIgnoring(plugin, uuid, false); Message.LOG_NOTIFY_TOGGLE_ON.send(sender); return CommandResult.SUCCESS; } if (args.get(0).equalsIgnoreCase("off")) { - if (ignoring.contains(uuid)) { + if (isIgnoring(plugin, uuid)) { // already off Message.LOG_NOTIFY_ALREADY_OFF.send(sender); return CommandResult.STATE_ERROR; } // toggle off - ignoring.add(uuid); + setIgnoring(plugin, uuid, true); Message.LOG_NOTIFY_TOGGLE_OFF.send(sender); return CommandResult.SUCCESS; } diff --git a/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java b/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java index 24cc14c9..01955274 100644 --- a/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java +++ b/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java @@ -392,7 +392,7 @@ public class ConfigKeys { })); /** - * The name of the messaging service in use, or "none" if not enabled. + * The name of the messaging service in use, or "none" if not enabled */ public static final ConfigKey MESSAGING_SERVICE = EnduringKey.wrap(LowercaseStringKey.of("messaging-service", "none")); @@ -401,6 +401,16 @@ public class ConfigKeys { */ public static final ConfigKey AUTO_PUSH_UPDATES = EnduringKey.wrap(BooleanKey.of("auto-push-updates", true)); + /** + * If LuckPerms should push logging entries to connected servers via the messaging service + */ + public static final ConfigKey PUSH_LOG_ENTRIES = EnduringKey.wrap(BooleanKey.of("push-log-entries", true)); + + /** + * If LuckPerms should broadcast received logging entries to players on this platform + */ + public static final ConfigKey BROADCAST_RECEIVED_LOG_ENTRIES = EnduringKey.wrap(BooleanKey.of("broadcast-received-log-entries", false)); + /** * If redis messaging is enabled */ diff --git a/common/src/main/java/me/lucko/luckperms/common/event/EventFactory.java b/common/src/main/java/me/lucko/luckperms/common/event/EventFactory.java index df0fb6e9..04a9ab7f 100644 --- a/common/src/main/java/me/lucko/luckperms/common/event/EventFactory.java +++ b/common/src/main/java/me/lucko/luckperms/common/event/EventFactory.java @@ -36,13 +36,16 @@ import me.lucko.luckperms.api.caching.UserData; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.cause.CreationCause; import me.lucko.luckperms.api.event.cause.DeletionCause; +import me.lucko.luckperms.api.event.log.LogBroadcastEvent; import me.lucko.luckperms.common.event.impl.EventConfigReload; import me.lucko.luckperms.common.event.impl.EventGroupCreate; import me.lucko.luckperms.common.event.impl.EventGroupDelete; import me.lucko.luckperms.common.event.impl.EventGroupLoad; import me.lucko.luckperms.common.event.impl.EventGroupLoadAll; import me.lucko.luckperms.common.event.impl.EventLogBroadcast; +import me.lucko.luckperms.common.event.impl.EventLogNetworkPublish; import me.lucko.luckperms.common.event.impl.EventLogPublish; +import me.lucko.luckperms.common.event.impl.EventLogReceive; import me.lucko.luckperms.common.event.impl.EventNodeAdd; import me.lucko.luckperms.common.event.impl.EventNodeClear; import me.lucko.luckperms.common.event.impl.EventNodeRemove; @@ -100,9 +103,9 @@ public final class EventFactory { fireEvent(event); } - public boolean handleLogBroadcast(boolean initialState, LogEntry entry) { + public boolean handleLogBroadcast(boolean initialState, LogEntry entry, LogBroadcastEvent.Origin origin) { AtomicBoolean cancel = new AtomicBoolean(initialState); - EventLogBroadcast event = new EventLogBroadcast(cancel, entry); + EventLogBroadcast event = new EventLogBroadcast(cancel, entry, origin); eventBus.fireEvent(event); return cancel.get(); } @@ -114,6 +117,18 @@ public final class EventFactory { return cancel.get(); } + public boolean handleLogNetworkPublish(boolean initialState, UUID id, LogEntry entry) { + AtomicBoolean cancel = new AtomicBoolean(initialState); + EventLogNetworkPublish event = new EventLogNetworkPublish(cancel, id, entry); + eventBus.fireEvent(event); + return cancel.get(); + } + + public void handleLogReceive(UUID id, LogEntry entry) { + EventLogReceive event = new EventLogReceive(id, entry); + fireEvent(event); + } + public void handleNodeAdd(Node node, PermissionHolder target, Collection before, Collection after) { EventNodeAdd event = new EventNodeAdd(node, target.getDelegate(), ImmutableSet.copyOf(before), ImmutableSet.copyOf(after)); fireEvent(event); diff --git a/common/src/main/java/me/lucko/luckperms/common/event/impl/EventLogBroadcast.java b/common/src/main/java/me/lucko/luckperms/common/event/impl/EventLogBroadcast.java index d4891738..f991678e 100644 --- a/common/src/main/java/me/lucko/luckperms/common/event/impl/EventLogBroadcast.java +++ b/common/src/main/java/me/lucko/luckperms/common/event/impl/EventLogBroadcast.java @@ -42,5 +42,6 @@ public class EventLogBroadcast extends AbstractEvent implements LogBroadcastEven private final AtomicBoolean cancellationState; private final LogEntry entry; + private final Origin origin; } diff --git a/common/src/main/java/me/lucko/luckperms/common/event/impl/EventLogNetworkPublish.java b/common/src/main/java/me/lucko/luckperms/common/event/impl/EventLogNetworkPublish.java new file mode 100644 index 00000000..ca88ef3a --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/event/impl/EventLogNetworkPublish.java @@ -0,0 +1,48 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * 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.event.impl; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; + +import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.event.log.LogNetworkPublishEvent; +import me.lucko.luckperms.common.event.AbstractEvent; + +import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; + +@Getter +@ToString +@AllArgsConstructor +public class EventLogNetworkPublish extends AbstractEvent implements LogNetworkPublishEvent { + + private final AtomicBoolean cancellationState; + private final UUID logId; + private final LogEntry entry; + +} diff --git a/common/src/main/java/me/lucko/luckperms/common/event/impl/EventLogReceive.java b/common/src/main/java/me/lucko/luckperms/common/event/impl/EventLogReceive.java new file mode 100644 index 00000000..8f70ec72 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/event/impl/EventLogReceive.java @@ -0,0 +1,46 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * 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.event.impl; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; + +import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.event.log.LogReceiveEvent; +import me.lucko.luckperms.common.event.AbstractEvent; + +import java.util.UUID; + +@Getter +@ToString +@AllArgsConstructor +public class EventLogReceive extends AbstractEvent implements LogReceiveEvent { + + private final UUID logId; + private final LogEntry entry; + +} diff --git a/common/src/main/java/me/lucko/luckperms/common/locale/Message.java b/common/src/main/java/me/lucko/luckperms/common/locale/Message.java index 2a29db1c..f48c57a9 100644 --- a/common/src/main/java/me/lucko/luckperms/common/locale/Message.java +++ b/common/src/main/java/me/lucko/luckperms/common/locale/Message.java @@ -364,6 +364,7 @@ public enum Message { LOG_NO_ENTRIES("&bNo log entries to show.", true), LOG_ENTRY("&b#{0} -> &8(&7{1} ago&8) {2}", true), + LOG_NOTIFY_CONSOLE("&cCannot toggle notifications for console.", true), LOG_NOTIFY_TOGGLE_ON("&aEnabled&b logging output.", true), LOG_NOTIFY_TOGGLE_OFF("&cDisabled&b logging output.", true), LOG_NOTIFY_ALREADY_ON("You are already receiving notifications.", true), diff --git a/common/src/main/java/me/lucko/luckperms/common/messaging/AbstractMessagingService.java b/common/src/main/java/me/lucko/luckperms/common/messaging/AbstractMessagingService.java index 606a721c..398ce9db 100644 --- a/common/src/main/java/me/lucko/luckperms/common/messaging/AbstractMessagingService.java +++ b/common/src/main/java/me/lucko/luckperms/common/messaging/AbstractMessagingService.java @@ -28,11 +28,18 @@ package me.lucko.luckperms.common.messaging; import lombok.Getter; import lombok.RequiredArgsConstructor; +import com.google.gson.Gson; +import com.google.gson.JsonObject; + +import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.buffers.BufferedRequest; +import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import java.util.Collections; import java.util.HashSet; +import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.function.Consumer; @@ -50,7 +57,8 @@ public abstract class AbstractMessagingService implements InternalMessagingServi @Getter private final String name; - private final Set receivedMsgs = Collections.synchronizedSet(new HashSet<>()); + private final Set receivedMessages = Collections.synchronizedSet(new HashSet<>()); + private final Gson gson = new Gson(); @Getter private final BufferedRequest updateBuffer = new BufferedRequest(10000L, r -> getPlugin().doAsync(r)) { @@ -63,54 +71,91 @@ public abstract class AbstractMessagingService implements InternalMessagingServi protected abstract void sendMessage(String channel, String message); - protected void onMessage(String channel, String msg, Consumer callback) { + protected void onMessage(String channel, String msg, Consumer callback) { if (!channel.equals(CHANNEL)) { return; } - UUID uuid = parseUpdateMessage(msg); - if (uuid == null) { - return; + if (msg.startsWith("update:") && msg.length() > "update:".length()) { + UUID uuid = parseUpdateMessage(msg); + if (uuid == null) { + return; + } + + if (!receivedMessages.add(uuid)) { + return; + } + + plugin.getLog().info("[" + name + " Messaging] Received update ping with id: " + uuid.toString()); + + if (plugin.getApiProvider().getEventFactory().handleNetworkPreSync(false, uuid)) { + return; + } + + plugin.getUpdateTaskBuffer().request(); + + if (callback != null) { + callback.accept(msg); + } + + } else if (msg.startsWith("log:") && msg.length() > "log:".length()) { + String logData = msg.substring("log:".length()); + Map.Entry entry = null; + try { + entry = ExtendedLogEntry.deserialize(gson.fromJson(logData, JsonObject.class)); + } catch (Exception e) { + plugin.getLog().warn("Error whilst deserializing log: " + logData); + e.printStackTrace(); + } + + if (entry == null) { + return; + } + + if (!receivedMessages.add(entry.getKey())) { + return; + } + + plugin.getApiProvider().getEventFactory().handleLogReceive(entry.getKey(), entry.getValue()); + plugin.getLogDispatcher().dispatchFromRemote(entry.getValue()); + + if (callback != null) { + callback.accept(msg); + } } + } - if (!receivedMsgs.add(uuid)) { - return; - } + @Override + public void pushLog(LogEntry logEntry) { + plugin.doAsync(() -> { + UUID id = generatePingId(); - plugin.getLog().info("[" + name + " Messaging] Received update ping with id: " + uuid.toString()); + if (plugin.getApiProvider().getEventFactory().handleLogNetworkPublish(!plugin.getConfiguration().get(ConfigKeys.PUSH_LOG_ENTRIES), id, logEntry)) { + return; + } - if (plugin.getApiProvider().getEventFactory().handleNetworkPreSync(false, uuid)) { - return; - } - - plugin.getUpdateTaskBuffer().request(); - - if (callback != null) { - callback.accept(uuid); - } + plugin.getLog().info("[" + name + " Messaging] Sending log with id: " + id.toString()); + sendMessage(CHANNEL, "log:" + gson.toJson(ExtendedLogEntry.serializeWithId(id, logEntry))); + }); } @Override public void pushUpdate() { plugin.doAsync(() -> { - UUID id = generateId(); + UUID id = generatePingId(); plugin.getLog().info("[" + name + " Messaging] Sending ping with id: " + id.toString()); sendMessage(CHANNEL, "update:" + id.toString()); }); } - private UUID generateId() { + private UUID generatePingId() { UUID uuid = UUID.randomUUID(); - receivedMsgs.add(uuid); + receivedMessages.add(uuid); return uuid; } private static UUID parseUpdateMessage(String msg) { - if (!msg.startsWith("update:")) { - return null; - } - String requestId = msg.substring("update:".length()); try { return UUID.fromString(requestId); diff --git a/common/src/main/java/me/lucko/luckperms/common/messaging/InternalMessagingService.java b/common/src/main/java/me/lucko/luckperms/common/messaging/InternalMessagingService.java index 01e2e5bc..5d69a17d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/messaging/InternalMessagingService.java +++ b/common/src/main/java/me/lucko/luckperms/common/messaging/InternalMessagingService.java @@ -25,6 +25,7 @@ package me.lucko.luckperms.common.messaging; +import me.lucko.luckperms.api.LogEntry; import me.lucko.luckperms.api.MessagingService; import me.lucko.luckperms.common.buffers.BufferedRequest; @@ -49,4 +50,11 @@ public interface InternalMessagingService extends MessagingService { */ BufferedRequest getUpdateBuffer(); + /** + * Pushes a log entry to connected servers. + * + * @param logEntry the log entry + */ + void pushLog(LogEntry logEntry); + } diff --git a/common/src/main/java/me/lucko/luckperms/common/messaging/NoopMessagingService.java b/common/src/main/java/me/lucko/luckperms/common/messaging/NoopMessagingService.java index bd34fd09..af81e16b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/messaging/NoopMessagingService.java +++ b/common/src/main/java/me/lucko/luckperms/common/messaging/NoopMessagingService.java @@ -25,6 +25,7 @@ package me.lucko.luckperms.common.messaging; +import me.lucko.luckperms.api.LogEntry; import me.lucko.luckperms.common.buffers.BufferedRequest; public class NoopMessagingService implements InternalMessagingService { @@ -44,6 +45,11 @@ public class NoopMessagingService implements InternalMessagingService { return null; } + @Override + public void pushLog(LogEntry logEntry) { + + } + @Override public void pushUpdate() { diff --git a/common/src/main/java/me/lucko/luckperms/common/plugin/LuckPermsPlugin.java b/common/src/main/java/me/lucko/luckperms/common/plugin/LuckPermsPlugin.java index bf11f31d..4e1fedac 100644 --- a/common/src/main/java/me/lucko/luckperms/common/plugin/LuckPermsPlugin.java +++ b/common/src/main/java/me/lucko/luckperms/common/plugin/LuckPermsPlugin.java @@ -28,6 +28,7 @@ package me.lucko.luckperms.common.plugin; import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.Logger; import me.lucko.luckperms.api.PlatformType; +import me.lucko.luckperms.common.actionlog.LogDispatcher; import me.lucko.luckperms.common.api.ApiProvider; import me.lucko.luckperms.common.buffers.BufferedRequest; import me.lucko.luckperms.common.caching.handlers.CachedStateManager; @@ -181,6 +182,13 @@ public interface LuckPermsPlugin { */ PermissionVault getPermissionVault(); + /** + * Gets the log dispatcher running on the platform + * + * @return the log dispatcher + */ + LogDispatcher getLogDispatcher(); + /** * Gets the LuckPerms Scheduler instance * @@ -380,13 +388,6 @@ public interface LuckPermsPlugin { return null; } - /** - * Gets a set of players ignoring logging output - * - * @return a {@link Set} of {@link UUID}s - */ - Set getIgnoringLogs(); - /** * Gets the update task buffer of the platform, used for scheduling and running update tasks. * diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/backing/file/FileUuidCache.java b/common/src/main/java/me/lucko/luckperms/common/storage/backing/file/FileUuidCache.java index 441ea4df..b15a7148 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/backing/file/FileUuidCache.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/backing/file/FileUuidCache.java @@ -1,3 +1,28 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * 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.backing.file; import com.google.common.base.Splitter; diff --git a/common/src/main/java/me/lucko/luckperms/common/utils/TextUtils.java b/common/src/main/java/me/lucko/luckperms/common/utils/TextUtils.java index 0eb0bcf0..ae0dcc60 100644 --- a/common/src/main/java/me/lucko/luckperms/common/utils/TextUtils.java +++ b/common/src/main/java/me/lucko/luckperms/common/utils/TextUtils.java @@ -1,3 +1,28 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * 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.utils; import lombok.experimental.UtilityClass; diff --git a/common/src/main/java/me/lucko/luckperms/common/verbose/VerboseFilter.java b/common/src/main/java/me/lucko/luckperms/common/verbose/VerboseFilter.java index 4031e99f..11f912af 100644 --- a/common/src/main/java/me/lucko/luckperms/common/verbose/VerboseFilter.java +++ b/common/src/main/java/me/lucko/luckperms/common/verbose/VerboseFilter.java @@ -1,3 +1,28 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * 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.verbose; import lombok.experimental.UtilityClass; diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java b/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java index d89b85d1..4cf6a85c 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java @@ -33,6 +33,7 @@ import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.LuckPermsApi; import me.lucko.luckperms.api.PlatformType; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.common.actionlog.LogDispatcher; import me.lucko.luckperms.common.api.ApiHandler; import me.lucko.luckperms.common.api.ApiProvider; import me.lucko.luckperms.common.backup.ImporterSender; @@ -125,9 +126,6 @@ import java.util.stream.Collectors; @Plugin(id = "luckperms", name = "LuckPerms", version = VersionData.VERSION, authors = {"Luck"}, description = "A permissions plugin") public class LPSpongePlugin implements LuckPermsPlugin { - private final Set ignoringLogs = ConcurrentHashMap.newKeySet(); - private Set uniqueConnections = ConcurrentHashMap.newKeySet(); - @Inject private Logger logger; @@ -173,6 +171,8 @@ public class LPSpongePlugin implements LuckPermsPlugin { private VerboseHandler verboseHandler; private SpongeSenderFactory senderFactory; private PermissionVault permissionVault; + private LogDispatcher logDispatcher; + private Set uniqueConnections = ConcurrentHashMap.newKeySet(); @Listener(order = Order.FIRST) public void onEnable(GamePreInitializationEvent event) { @@ -185,6 +185,7 @@ public class LPSpongePlugin implements LuckPermsPlugin { LuckPermsPlugin.sendStartupBanner(getConsoleSender(), this); verboseHandler = new VerboseHandler(scheduler.async(), getVersion()); permissionVault = new PermissionVault(scheduler.async()); + logDispatcher = new LogDispatcher(this); timings = new LPTimings(this); getLog().info("Loading configuration..."); diff --git a/sponge/src/main/resources/luckperms.conf b/sponge/src/main/resources/luckperms.conf index bcf96b3b..a5412136 100644 --- a/sponge/src/main/resources/luckperms.conf +++ b/sponge/src/main/resources/luckperms.conf @@ -278,6 +278,16 @@ messaging-service="none" # If LuckPerms should automatically push updates after a change has been made with a command. auto-push-updates=true +# If LuckPerms should push logging entries to connected servers via the messaging service. +push-log-entries=true + +# If LuckPerms should broadcast received logging entries to players on this platform. +# +# If you have LuckPerms installed on your backend servers as well as a BungeeCord proxy, you should +# set this option to false on either your backends or your proxies, to avoid players being messaged +# twice about log entries. +broadcast-received-log-entries=true + # Settings for Redis. # Port 6379 is used by default; set address to "host:port" if differs redis {