Skip to content

Commit

Permalink
Add track routes
Browse files Browse the repository at this point in the history
  • Loading branch information
lucko committed Oct 23, 2023
1 parent f3b6307 commit d415fba
Show file tree
Hide file tree
Showing 5 changed files with 452 additions and 26 deletions.
22 changes: 21 additions & 1 deletion src/main/java/me/lucko/luckperms/extension/rest/RestServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import me.lucko.luckperms.extension.rest.controller.ActionController;
import me.lucko.luckperms.extension.rest.controller.GroupController;
import me.lucko.luckperms.extension.rest.controller.PermissionHolderController;
import me.lucko.luckperms.extension.rest.controller.TrackController;
import me.lucko.luckperms.extension.rest.controller.UserController;
import me.lucko.luckperms.extension.rest.util.CustomObjectMapper;
import me.lucko.luckperms.extension.rest.util.StubMessagingService;
Expand Down Expand Up @@ -125,6 +126,7 @@ private void 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());

app.routes(() -> {
Expand All @@ -135,8 +137,11 @@ private void setupRoutes(Javalin app, LuckPerms luckPerms) {
path("group", () -> {
setupControllerRoutes(groupController);
});
path("track", () -> {
setupControllerRoutes(trackController);
});
path("action", () -> {
post(actionController::submit);
setupControllerRoutes(actionController);
});
});
}
Expand Down Expand Up @@ -172,6 +177,21 @@ private void setupControllerRoutes(PermissionHolderController controller) {
});
}

private void setupControllerRoutes(TrackController controller) {
post(controller::create);
get(controller::getAll);

path("{id}", () -> {
get(controller::get);
patch(controller::update);
delete(controller::delete);
});
}

private void setupControllerRoutes(ActionController controller) {
post(controller::submit);
}

private void setupAuth(JavalinConfig config) {
if (RestConfig.getBoolean("auth", false)) {
Set<String> keys = ImmutableSet.copyOf(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <[email protected]>
* 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.bind;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import net.luckperms.api.cacheddata.CachedMetaData;
import net.luckperms.api.model.group.Group;
import net.luckperms.api.model.user.User;
import net.luckperms.api.node.Node;
import net.luckperms.api.query.QueryOptions;
import net.luckperms.api.track.Track;

import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

public class TrackSerializer extends JsonSerializer<Track> {

@Override
public void serialize(Track value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writePOJO(Model.from(value));
}

record Model(String name, List<String> groups) {
static Model from(Track track) {
return new Model(
track.getName(),
track.getGroups()
);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <[email protected]>
* 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.controller;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.javalin.http.Context;
import me.lucko.luckperms.extension.rest.RestConfig;
import me.lucko.luckperms.extension.rest.model.GroupSearchResult;
import me.lucko.luckperms.extension.rest.model.PermissionCheckRequest;
import me.lucko.luckperms.extension.rest.model.PermissionCheckResult;
import me.lucko.luckperms.extension.rest.model.SearchRequest;
import me.lucko.luckperms.extension.rest.util.ParamUtils;
import net.luckperms.api.cacheddata.CachedMetaData;
import net.luckperms.api.messaging.MessagingService;
import net.luckperms.api.model.data.TemporaryNodeMergeStrategy;
import net.luckperms.api.model.group.Group;
import net.luckperms.api.model.group.GroupManager;
import net.luckperms.api.node.Node;
import net.luckperms.api.node.matcher.NodeMatcher;
import net.luckperms.api.query.QueryOptions;
import net.luckperms.api.track.Track;
import net.luckperms.api.track.TrackManager;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

public class TrackController {
private static final boolean CACHE = RestConfig.getBoolean("cache.tracks", true);

private final TrackManager trackManager;
private final GroupManager groupManager;
private final MessagingService messagingService;
private final ObjectMapper objectMapper;

public TrackController(TrackManager trackManager, GroupManager groupManager, MessagingService messagingService, ObjectMapper objectMapper) {
this.trackManager = trackManager;
this.groupManager = groupManager;
this.messagingService = messagingService;
this.objectMapper = objectMapper;
}

private CompletableFuture<Track> loadTrackCached(String name) {
if (CACHE) {
return CompletableFuture.completedFuture(this.trackManager.getTrack(name));
} else {
return this.trackManager.loadTrack(name).thenApply(opt -> opt.orElse(null));
}
}

private CompletableFuture<Set<Track>> loadTracksCached() {
if (CACHE) {
return CompletableFuture.completedFuture(this.trackManager.getLoadedTracks());
} else {
return this.trackManager.loadAllTracks().thenApply(x -> this.trackManager.getLoadedTracks());
}
}

// POST /track
public void create(Context ctx) {
CreateReq body = ctx.bodyAsClass(CreateReq.class);

if (this.trackManager.isLoaded(body.name)) {
ctx.status(409).result("Track already exists!");
return;
}

CompletableFuture<Track> future = this.trackManager.createAndLoadTrack(body.name);
ctx.future(future, result -> ctx.status(201).json(result));
}

record CreateReq(@JsonProperty(required = true) String name) { }

// GET /track
public void getAll(Context ctx) {
CompletableFuture<List<String>> future = loadTracksCached()
.thenApply(tracks -> tracks.stream()
.map(Track::getName)
.collect(Collectors.toList())
);
ctx.future(future);
}

// GET /track/{id}
public void get(Context ctx) {
String name = ctx.pathParam("id");
CompletableFuture<Track> future = loadTrackCached(name);
ctx.future(future, result -> {
if (result == null) {
ctx.status(404).result("Track doesn't exist");
} else {
ctx.json(result);
}
});
}

// PATCH /track/{id}
public void update(Context ctx) {
String name = ctx.pathParam("id");
UpdateReq body = ctx.bodyAsClass(UpdateReq.class);

List<Group> groups = new ArrayList<>();
for (String group : body.groups()) {
Group g = this.groupManager.getGroup(group);
if (g == null) {
ctx.status(404).result("Group " + group + " does not exist");
return;
}
groups.add(g);
}

CompletableFuture<Track> future = this.trackManager.loadTrack(name).thenCompose(opt -> {
if (opt.isPresent()) {
Track track = opt.get();
track.clearGroups();
for (Group group : groups) {
track.appendGroup(group);
}
return this.trackManager.saveTrack(track).thenApply(v -> {
this.messagingService.pushUpdate();
return track;
});
} else {
return CompletableFuture.completedFuture(null);
}
});

ctx.future(future, result -> {
if (result == null) {
ctx.status(404).result("Track doesn't exist");
} else {
ctx.result("ok");
}
});
}

record UpdateReq(@JsonProperty(required = true) List<String> groups) { }

// DELETE /track/{id}
public void delete(Context ctx) {
String name = ctx.pathParam("id");

CompletableFuture<Boolean> future = this.trackManager.loadTrack(name).thenCompose(opt -> {
if (opt.isPresent()) {
return this.trackManager.deleteTrack(opt.get()).thenApply(x -> {
this.messagingService.pushUpdate();
return true;
});
} else {
return CompletableFuture.completedFuture(false);
}
});
ctx.future(future, result -> {
if (result == Boolean.FALSE) {
ctx.status(404).result("Track doesn't exist");
} else {
ctx.status(200).result("ok");
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import me.lucko.luckperms.extension.rest.bind.NodeSerializer;
import me.lucko.luckperms.extension.rest.bind.PromotionResultSerializer;
import me.lucko.luckperms.extension.rest.bind.QueryOptionsDeserializer;
import me.lucko.luckperms.extension.rest.bind.TrackSerializer;
import me.lucko.luckperms.extension.rest.bind.UserSerializer;
import net.luckperms.api.actionlog.Action;
import net.luckperms.api.cacheddata.CachedMetaData;
Expand All @@ -51,6 +52,7 @@
import net.luckperms.api.query.QueryOptions;
import net.luckperms.api.track.DemotionResult;
import net.luckperms.api.track.PromotionResult;
import net.luckperms.api.track.Track;

public class CustomObjectMapper extends ObjectMapper {

Expand All @@ -72,6 +74,7 @@ public CustomObjectMapper() {
module.addSerializer(Node.class, new NodeSerializer());
module.addSerializer(PromotionResult.class, new PromotionResultSerializer());
module.addDeserializer(QueryOptions.class, new QueryOptionsDeserializer());
module.addSerializer(Track.class, new TrackSerializer());
module.addSerializer(User.class, new UserSerializer());
this.registerModule(module);
}
Expand Down
Loading

0 comments on commit d415fba

Please sign in to comment.