mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-24 11:38:40 +01:00
Log action serialization changes
This commit is contained in:
parent
4667ffc681
commit
eff93c788b
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.actionlog;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
|
||||
import me.lucko.luckperms.api.actionlog.Action;
|
||||
import me.lucko.luckperms.common.util.gson.JObject;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class ActionJsonSerializer {
|
||||
private ActionJsonSerializer() {}
|
||||
|
||||
public static JsonObject serialize(Action logEntry) {
|
||||
return new JObject()
|
||||
.add("timestamp", new JsonPrimitive(logEntry.getTimestamp().getEpochSecond()))
|
||||
.add("source", new JObject()
|
||||
.add("uniqueId", new JsonPrimitive(logEntry.getSource().getUniqueId().toString()))
|
||||
.add("name", new JsonPrimitive(logEntry.getSource().getName()))
|
||||
)
|
||||
.add("target", new JObject()
|
||||
.add("type", new JsonPrimitive(logEntry.getTarget().getType().name())))
|
||||
.consume(obj -> {
|
||||
if (logEntry.getTarget().getUniqueId().isPresent()) {
|
||||
obj.add("uniqueId", new JsonPrimitive(logEntry.getTarget().getUniqueId().get().toString()));
|
||||
}
|
||||
})
|
||||
.add("name", new JsonPrimitive(logEntry.getTarget().getName())
|
||||
)
|
||||
.add("description", new JsonPrimitive(logEntry.getDescription()))
|
||||
.toJson();
|
||||
}
|
||||
|
||||
public static LoggedAction deserialize(JsonElement element) {
|
||||
Preconditions.checkArgument(element.isJsonObject());
|
||||
JsonObject data = element.getAsJsonObject();
|
||||
|
||||
LoggedAction.Builder builder = LoggedAction.build();
|
||||
|
||||
if (data.has("timestamp")) { // sigh - this wasn't included in the first implementations
|
||||
builder.timestamp(Instant.ofEpochSecond(data.get("timestamp").getAsLong()));
|
||||
}
|
||||
|
||||
if (data.has("source")) {
|
||||
JsonObject source = data.get("source").getAsJsonObject();
|
||||
builder.source(UUID.fromString(source.get("uniqueId").getAsString()));
|
||||
builder.sourceName(source.get("name").getAsString());
|
||||
} else {
|
||||
builder.source(UUID.fromString(data.get("actor").getAsString()));
|
||||
builder.sourceName(data.get("actorName").getAsString());
|
||||
}
|
||||
|
||||
if (data.has("target")) {
|
||||
JsonObject target = data.get("target").getAsJsonObject();
|
||||
builder.targetType(LoggedAction.parseType(target.get("type").getAsString()));
|
||||
if (target.has("uniqueId")) {
|
||||
builder.target(UUID.fromString(target.get("uniqueId").getAsString()));
|
||||
}
|
||||
builder.targetName(target.get("name").getAsString());
|
||||
} else {
|
||||
builder.targetType(LoggedAction.parseType(data.get("type").getAsString()));
|
||||
if (data.has("acted")) {
|
||||
builder.target(UUID.fromString(data.get("acted").getAsString()));
|
||||
}
|
||||
builder.targetName(data.get("actedName").getAsString());
|
||||
}
|
||||
|
||||
if (data.has("description")) {
|
||||
builder.description(data.get("description").getAsString());
|
||||
} else {
|
||||
builder.description(data.get("action").getAsString());
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* 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.actionlog;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
|
||||
import me.lucko.luckperms.api.actionlog.Action;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class LogEntryJsonSerializer {
|
||||
private LogEntryJsonSerializer() {}
|
||||
|
||||
public static JsonObject serialize(Action logEntry) {
|
||||
JsonObject data = new JsonObject();
|
||||
data.add("timestamp", new JsonPrimitive(logEntry.getTimestamp().getEpochSecond()));
|
||||
data.add("actor", new JsonPrimitive(logEntry.getSource().getUniqueId().toString()));
|
||||
data.add("actorName", new JsonPrimitive(logEntry.getSource().getName()));
|
||||
data.add("type", new JsonPrimitive(logEntry.getTarget().getType().name()));
|
||||
if (logEntry.getTarget().getUniqueId().isPresent()) {
|
||||
data.add("acted", new JsonPrimitive(logEntry.getTarget().getUniqueId().get().toString()));
|
||||
}
|
||||
data.add("actedName", new JsonPrimitive(logEntry.getTarget().getName()));
|
||||
data.add("action", new JsonPrimitive(logEntry.getDescription()));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static LoggedAction deserialize(JsonElement element) {
|
||||
Preconditions.checkArgument(element.isJsonObject());
|
||||
JsonObject data = element.getAsJsonObject();
|
||||
|
||||
LoggedAction.Builder builder = LoggedAction.build();
|
||||
|
||||
if (data.has("timestamp")) { // sigh - this wasn't included in the first implementations
|
||||
builder.timestamp(Instant.ofEpochSecond(data.get("timestamp").getAsLong()));
|
||||
}
|
||||
|
||||
builder.source(UUID.fromString(data.get("actor").getAsString()));
|
||||
builder.sourceName(data.get("actorName").getAsString());
|
||||
builder.targetType(LoggedAction.parseType(data.get("type").getAsString()));
|
||||
if (data.has("acted")) {
|
||||
builder.source(UUID.fromString(data.get("acted").getAsString()));
|
||||
}
|
||||
builder.targetName(data.get("actedName").getAsString());
|
||||
builder.description(data.get("action").getAsString());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
}
|
@ -86,21 +86,18 @@ public class LoggedAction implements Action {
|
||||
this.action = description;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Instant getTimestamp() {
|
||||
public @NonNull Instant getTimestamp() {
|
||||
return Instant.ofEpochSecond(this.timestamp);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Source getSource() {
|
||||
public @NonNull Source getSource() {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Target getTarget() {
|
||||
public @NonNull Target getTarget() {
|
||||
return this.target;
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ import com.google.gson.JsonElement;
|
||||
|
||||
import me.lucko.luckperms.api.actionlog.Action;
|
||||
import me.lucko.luckperms.api.messenger.message.type.ActionLogMessage;
|
||||
import me.lucko.luckperms.common.actionlog.LogEntryJsonSerializer;
|
||||
import me.lucko.luckperms.common.actionlog.ActionJsonSerializer;
|
||||
import me.lucko.luckperms.common.messaging.LuckPermsMessagingService;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
@ -45,7 +45,7 @@ public class ActionLogMessageImpl extends AbstractMessage implements ActionLogMe
|
||||
throw new IllegalStateException("Missing content");
|
||||
}
|
||||
|
||||
return new ActionLogMessageImpl(id, LogEntryJsonSerializer.deserialize(content));
|
||||
return new ActionLogMessageImpl(id, ActionJsonSerializer.deserialize(content));
|
||||
}
|
||||
|
||||
private final Action logEntry;
|
||||
@ -63,7 +63,7 @@ public class ActionLogMessageImpl extends AbstractMessage implements ActionLogMe
|
||||
@Override
|
||||
public @NonNull String asEncodedString() {
|
||||
return LuckPermsMessagingService.encodeMessageAsString(
|
||||
TYPE, getId(), LogEntryJsonSerializer.serialize(this.logEntry)
|
||||
TYPE, getId(), ActionJsonSerializer.serialize(this.logEntry)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -154,7 +154,7 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio
|
||||
this.uuidDataFile = MoreFiles.createFileIfNotExists(this.dataDirectory.resolve("uuidcache.txt"));
|
||||
this.uuidCache.load(this.uuidDataFile);
|
||||
|
||||
this.actionLogger.init(this.dataDirectory.resolve("actions.json"));
|
||||
this.actionLogger.init(this.dataDirectory.resolve("actions.txt"), this.dataDirectory.resolve("actions.json"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -28,19 +28,22 @@ package me.lucko.luckperms.common.storage.implementation.file;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
|
||||
import me.lucko.luckperms.api.actionlog.Action;
|
||||
import me.lucko.luckperms.common.actionlog.ActionJsonSerializer;
|
||||
import me.lucko.luckperms.common.actionlog.Log;
|
||||
import me.lucko.luckperms.common.actionlog.LogEntryJsonSerializer;
|
||||
import me.lucko.luckperms.common.cache.BufferedRequest;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.util.gson.GsonProvider;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -69,8 +72,33 @@ public class FileActionLogger {
|
||||
this.saveBuffer = new SaveBuffer(plugin);
|
||||
}
|
||||
|
||||
public void init(Path contentFile) {
|
||||
public void init(Path contentFile, Path legacyFile) {
|
||||
this.contentFile = contentFile;
|
||||
|
||||
if (Files.exists(legacyFile)) {
|
||||
// migrate
|
||||
JsonArray array;
|
||||
|
||||
try (JsonReader reader = new JsonReader(Files.newBufferedReader(legacyFile, StandardCharsets.UTF_8))) {
|
||||
array = GsonProvider.parser().parse(reader).getAsJsonArray();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
for (JsonElement element : array) {
|
||||
this.entryQueue.add(ActionJsonSerializer.deserialize(element));
|
||||
}
|
||||
|
||||
flush();
|
||||
|
||||
try {
|
||||
Files.delete(legacyFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void logAction(Action entry) {
|
||||
@ -87,30 +115,14 @@ public class FileActionLogger {
|
||||
}
|
||||
|
||||
try {
|
||||
// read existing array data into memory
|
||||
JsonArray array;
|
||||
|
||||
if (Files.exists(this.contentFile)) {
|
||||
try (JsonReader reader = new JsonReader(Files.newBufferedReader(this.contentFile, StandardCharsets.UTF_8))) {
|
||||
array = GsonProvider.parser().parse(reader).getAsJsonArray();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
array = new JsonArray();
|
||||
}
|
||||
} else {
|
||||
array = new JsonArray();
|
||||
}
|
||||
List<String> toWrite = new ArrayList<>(this.entryQueue.size());
|
||||
|
||||
// poll the queue for new entries
|
||||
for (Action e; (e = this.entryQueue.poll()) != null; ) {
|
||||
array.add(LogEntryJsonSerializer.serialize(e));
|
||||
toWrite.add(GsonProvider.normal().toJson(ActionJsonSerializer.serialize(e)));
|
||||
}
|
||||
|
||||
// write the full content back to the file
|
||||
try (JsonWriter writer = new JsonWriter(Files.newBufferedWriter(this.contentFile, StandardCharsets.UTF_8))) {
|
||||
writer.setIndent(" ");
|
||||
GsonProvider.normal().toJson(array, writer);
|
||||
}
|
||||
Files.write(this.contentFile, toWrite, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.APPEND);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -120,13 +132,24 @@ public class FileActionLogger {
|
||||
}
|
||||
|
||||
public Log getLog() throws IOException {
|
||||
if (!Files.exists(this.contentFile)) {
|
||||
return Log.empty();
|
||||
}
|
||||
|
||||
Log.Builder log = Log.builder();
|
||||
try (JsonReader reader = new JsonReader(Files.newBufferedReader(this.contentFile, StandardCharsets.UTF_8))) {
|
||||
JsonArray array = GsonProvider.parser().parse(reader).getAsJsonArray();
|
||||
for (JsonElement element : array) {
|
||||
log.add(LogEntryJsonSerializer.deserialize(element));
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(this.contentFile, StandardCharsets.UTF_8)) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
try {
|
||||
JsonElement parsed = GsonProvider.parser().parse(line);
|
||||
log.add(ActionJsonSerializer.deserialize(parsed));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return log.build();
|
||||
}
|
||||
|
||||
|
@ -166,18 +166,25 @@ public class MongoStorage implements StorageImplementation {
|
||||
@Override
|
||||
public void logAction(Action entry) {
|
||||
MongoCollection<Document> c = this.database.getCollection(this.prefix + "action");
|
||||
|
||||
Document doc = new Document()
|
||||
.append("timestamp", entry.getTimestamp().getEpochSecond())
|
||||
.append("actor", entry.getSource().getUniqueId())
|
||||
.append("actorName", entry.getSource().getName())
|
||||
.append("type", Character.toString(LoggedAction.getTypeCharacter(entry.getTarget().getType())))
|
||||
.append("actedName", entry.getTarget().getName())
|
||||
.append("action", entry.getDescription());
|
||||
.append("source", new Document()
|
||||
.append("uniqueId", entry.getSource().getUniqueId())
|
||||
.append("name", entry.getSource().getName())
|
||||
);
|
||||
|
||||
Document target = new Document()
|
||||
.append("type", entry.getTarget().getType().name())
|
||||
.append("name", entry.getTarget().getName());
|
||||
|
||||
if (entry.getTarget().getUniqueId().isPresent()) {
|
||||
doc.append("acted", entry.getTarget().getUniqueId().get());
|
||||
target.append("uniqueId", entry.getTarget().getUniqueId().get());
|
||||
}
|
||||
|
||||
doc.append("target", target);
|
||||
doc.append("description", entry.getDescription());
|
||||
|
||||
c.insertOne(doc);
|
||||
}
|
||||
|
||||
@ -189,6 +196,29 @@ public class MongoStorage implements StorageImplementation {
|
||||
while (cursor.hasNext()) {
|
||||
Document d = cursor.next();
|
||||
|
||||
if (d.containsKey("source")) {
|
||||
// new format
|
||||
Document source = d.get("source", Document.class);
|
||||
Document target = d.get("target", Document.class);
|
||||
|
||||
UUID targetUniqueId = null;
|
||||
if (target.containsKey("uniqueId")) {
|
||||
targetUniqueId = target.get("uniqueId", UUID.class);
|
||||
}
|
||||
|
||||
LoggedAction e = LoggedAction.build()
|
||||
.timestamp(Instant.ofEpochSecond(d.getLong("timestamp")))
|
||||
.source(source.get("uniqueId", UUID.class))
|
||||
.sourceName(source.getString("name"))
|
||||
.targetType(LoggedAction.parseType(target.getString("type")))
|
||||
.target(targetUniqueId)
|
||||
.targetName(target.getString("name"))
|
||||
.description(d.getString("description"))
|
||||
.build();
|
||||
|
||||
log.add(e);
|
||||
} else {
|
||||
// old format
|
||||
UUID actedUuid = null;
|
||||
if (d.containsKey("acted")) {
|
||||
actedUuid = d.get("acted", UUID.class);
|
||||
@ -207,6 +237,7 @@ public class MongoStorage implements StorageImplementation {
|
||||
log.add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return log.build();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user