From 061fc88c51ae752978fca1b9b0cc29ada1a581e9 Mon Sep 17 00:00:00 2001 From: Luck Date: Thu, 11 Jul 2024 21:10:28 +0100 Subject: [PATCH] Add action query API methods --- build.gradle | 2 +- .../luckperms/extension/rest/RestServer.java | 3 +- .../rest/controller/ActionController.java | 35 +++++++- .../rest/controller/GroupController.java | 4 +- .../rest/controller/UserController.java | 4 +- .../extension/rest/model/ActionPage.java | 40 +++++++++ .../extension/rest/model/ActionRequest.java | 71 ++++++++++++++++ src/main/resources/luckperms-openapi.yml | 83 +++++++++++++++++++ 8 files changed, 235 insertions(+), 7 deletions(-) create mode 100644 src/main/java/me/lucko/luckperms/extension/rest/model/ActionPage.java create mode 100644 src/main/java/me/lucko/luckperms/extension/rest/model/ActionRequest.java diff --git a/build.gradle b/build.gradle index 7241180..8e5412e 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ repositories { dependencies { compileOnly 'org.slf4j:slf4j-api:1.7.36' - compileOnly 'net.luckperms:api:5.5-20240307.193022-3' + compileOnly 'net.luckperms:api:5.5-20240616.203859-4' implementation 'io.javalin:javalin:4.6.4' implementation 'io.javalin:javalin-openapi:4.6.4' } diff --git a/src/main/java/me/lucko/luckperms/extension/rest/RestServer.java b/src/main/java/me/lucko/luckperms/extension/rest/RestServer.java index e0e3dbc..c6d84ff 100644 --- a/src/main/java/me/lucko/luckperms/extension/rest/RestServer.java +++ b/src/main/java/me/lucko/luckperms/extension/rest/RestServer.java @@ -136,7 +136,7 @@ private AutoCloseable setupRoutes(Javalin app, LuckPerms luckPerms) { UserController userController = new UserController(luckPerms.getUserManager(), luckPerms.getTrackManager(), messagingService, this.objectMapper); GroupController groupController = new GroupController(luckPerms.getGroupManager(), messagingService, this.objectMapper); TrackController trackController = new TrackController(luckPerms.getTrackManager(), luckPerms.getGroupManager(), messagingService, this.objectMapper); - ActionController actionController = new ActionController(luckPerms.getActionLogger()); + ActionController actionController = new ActionController(luckPerms.getActionLogger(), this.objectMapper); MessagingController messagingController = new MessagingController(luckPerms.getMessagingService().orElse(null), luckPerms.getUserManager(), this.objectMapper); EventController eventController = new EventController(luckPerms.getEventBus()); @@ -202,6 +202,7 @@ private void setupControllerRoutes(TrackController controller) { } private void setupControllerRoutes(ActionController controller) { + get(controller::get); post(controller::submit); } diff --git a/src/main/java/me/lucko/luckperms/extension/rest/controller/ActionController.java b/src/main/java/me/lucko/luckperms/extension/rest/controller/ActionController.java index b49eb92..86c23e9 100644 --- a/src/main/java/me/lucko/luckperms/extension/rest/controller/ActionController.java +++ b/src/main/java/me/lucko/luckperms/extension/rest/controller/ActionController.java @@ -25,18 +25,51 @@ package me.lucko.luckperms.extension.rest.controller; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import io.javalin.http.Context; +import me.lucko.luckperms.extension.rest.model.ActionPage; +import me.lucko.luckperms.extension.rest.model.ActionRequest; import net.luckperms.api.actionlog.Action; import net.luckperms.api.actionlog.ActionLogger; +import net.luckperms.api.actionlog.filter.ActionFilter; import java.util.concurrent.CompletableFuture; public class ActionController { private final ActionLogger actionLogger; + private final ObjectMapper objectMapper; - public ActionController(ActionLogger actionLogger) { + public ActionController(ActionLogger actionLogger, ObjectMapper objectMapper) { this.actionLogger = actionLogger; + this.objectMapper = objectMapper; + } + + // GET /action + public void get(Context ctx) throws JsonProcessingException { + ActionFilter filter = ActionRequest.parseFilter(this.objectMapper, ctx); + + Integer pageSize = ctx.queryParamAsClass("pageSize", Integer.class).getOrDefault(null); + Integer pageNumber = ctx.queryParamAsClass("pageNumber", Integer.class).getOrDefault(null); + + if (pageSize == null && pageNumber == null) { + CompletableFuture future = this.actionLogger.queryActions(filter) + .thenApply(list -> new ActionPage(list, list.size())); + ctx.future(future); + } else { + if (pageSize == null) { + ctx.status(400).result("pageSize query parameter is required when pageNumber is provided"); + return; + } else if (pageNumber == null) { + ctx.status(400).result("pageNumber query parameter is required when pageSize is provided"); + return; + } + + CompletableFuture future = this.actionLogger.queryActions(filter, pageSize, pageNumber) + .thenApply(ActionPage::from); + ctx.future(future); + } } // POST /action diff --git a/src/main/java/me/lucko/luckperms/extension/rest/controller/GroupController.java b/src/main/java/me/lucko/luckperms/extension/rest/controller/GroupController.java index 1047cd8..626410b 100644 --- a/src/main/java/me/lucko/luckperms/extension/rest/controller/GroupController.java +++ b/src/main/java/me/lucko/luckperms/extension/rest/controller/GroupController.java @@ -320,7 +320,7 @@ public void metaGet(Context ctx) { }); } - // GET /group/{id}/permissionCheck + // GET /group/{id}/permission-check @Override public void permissionCheck(Context ctx) { String name = ctx.pathParam("id"); @@ -340,7 +340,7 @@ public void permissionCheck(Context ctx) { }); } - // POST /group/{id}/permissionCheck + // POST /group/{id}/permission-check @Override public void permissionCheckCustom(Context ctx) { String name = ctx.pathParam("id"); diff --git a/src/main/java/me/lucko/luckperms/extension/rest/controller/UserController.java b/src/main/java/me/lucko/luckperms/extension/rest/controller/UserController.java index d3aa742..154aa46 100644 --- a/src/main/java/me/lucko/luckperms/extension/rest/controller/UserController.java +++ b/src/main/java/me/lucko/luckperms/extension/rest/controller/UserController.java @@ -297,7 +297,7 @@ public void metaGet(Context ctx) throws JsonProcessingException { ctx.future(future); } - // GET /user/{id}/permissionCheck + // GET /user/{id}/permission-check @Override public void permissionCheck(Context ctx) throws JsonProcessingException { UUID uniqueId = pathParamAsUuid(ctx); @@ -313,7 +313,7 @@ public void permissionCheck(Context ctx) throws JsonProcessingException { ctx.future(future); } - // POST /user/{id}/permissionCheck + // POST /user/{id}/permission-check @Override public void permissionCheckCustom(Context ctx) throws JsonProcessingException { UUID uniqueId = pathParamAsUuid(ctx); diff --git a/src/main/java/me/lucko/luckperms/extension/rest/model/ActionPage.java b/src/main/java/me/lucko/luckperms/extension/rest/model/ActionPage.java new file mode 100644 index 0000000..d717a63 --- /dev/null +++ b/src/main/java/me/lucko/luckperms/extension/rest/model/ActionPage.java @@ -0,0 +1,40 @@ +/* + * 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.extension.rest.model; + +import net.luckperms.api.actionlog.Action; +import net.luckperms.api.util.Page; + +import java.util.List; + +public record ActionPage(List entries, int overallSize) { + public static ActionPage from(Page page) { + return new ActionPage( + page.entries(), + page.overallSize() + ); + } +} diff --git a/src/main/java/me/lucko/luckperms/extension/rest/model/ActionRequest.java b/src/main/java/me/lucko/luckperms/extension/rest/model/ActionRequest.java new file mode 100644 index 0000000..03343b0 --- /dev/null +++ b/src/main/java/me/lucko/luckperms/extension/rest/model/ActionRequest.java @@ -0,0 +1,71 @@ +/* + * 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.extension.rest.model; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.javalin.http.Context; +import net.luckperms.api.actionlog.filter.ActionFilter; + +import java.util.UUID; + +public class ActionRequest { + + private static UUID parseUuid(ObjectMapper objectMapper, String s) throws JsonProcessingException { + String uuidString = "\"" + s + "\""; + return objectMapper.readValue(uuidString, UUID.class); + } + + public static ActionFilter parseFilter(ObjectMapper objectMapper, Context ctx) throws JsonProcessingException { + String source = ctx.queryParam("source"); + if (source != null && !source.isEmpty()) { + return ActionFilter.source(parseUuid(objectMapper, source)); + } + + String user = ctx.queryParam("user"); + if (user != null && !user.isEmpty()) { + return ActionFilter.user(parseUuid(objectMapper, user)); + } + + String group = ctx.queryParam("group"); + if (group != null && !group.isEmpty()) { + return ActionFilter.group(group); + } + + String track = ctx.queryParam("track"); + if (track != null && !track.isEmpty()) { + return ActionFilter.track(track); + } + + String search = ctx.queryParam("search"); + if (search != null && !search.isEmpty()) { + return ActionFilter.search(search); + } + + return ActionFilter.any(); + } + +} diff --git a/src/main/resources/luckperms-openapi.yml b/src/main/resources/luckperms-openapi.yml index 9cd0930..198bfff 100644 --- a/src/main/resources/luckperms-openapi.yml +++ b/src/main/resources/luckperms-openapi.yml @@ -1248,6 +1248,89 @@ paths: tags: - Tracks /action: + get: + summary: Query actions + operationId: get-actions + responses: + '200': + description: Ok + content: + application/json: + schema: + type: object + properties: + entries: + type: array + items: + $ref: '#/components/schemas/Action' + overallSize: + type: integer + examples: + example-1: + value: + entries: + - timestamp: 1658428395 + source: + uniqueId: c1d60c50-70b5-4722-8057-87767557e50d + name: Luck + target: + uniqueId: 069a79f4-44e9-4726-a5be-fca90e38aaf5 + name: Notch + type: user + description: permission set minecraft.command.ban true + overallSize: 1 + '400': + description: Missing required information + description: | + Query actions from the action logger. + + If pageSize or pageNumber are specified, both must be specified. + If neither are specified, no pagination will be used and all results will be returned. + parameters: + - schema: + type: integer + minimum: 1 + in: query + name: pageSize + description: The number of actions to return on each page + - schema: + type: integer + minimum: 1 + in: query + name: pageNumber + description: The page to return + - schema: + type: string + minLength: 1 + in: query + name: source + description: Filter by source user unique id + - schema: + type: string + minLength: 1 + in: query + name: user + description: Filter by target user unique id + - schema: + type: string + minLength: 1 + in: query + name: group + description: Filter by target group name + - schema: + type: string + minLength: 1 + in: query + name: track + description: Filter by target track name + - schema: + type: string + minLength: 1 + in: query + name: search + description: Filter by search value in source name, target name or description. + tags: + - Actions post: summary: Submit a new action operationId: submit-action