Refactored JSONResolvers to use the new API

This commit is contained in:
Rsl1122 2020-03-01 20:35:00 +02:00 committed by Risto Lahtela
parent 2b1b459a37
commit 1ab5f3473d
20 changed files with 345 additions and 269 deletions

View File

@ -22,34 +22,45 @@ import com.djrapitops.plan.delivery.web.resolver.request.URIPath;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
/** /**
* Utility Resolver for organizing resolution in a tree-like structure. * Utility Resolver for organizing resolution in a tree-like structure.
* <p> * <p>
* CompositeResolver removes first part of the target with {@link URIPath#omitFirst()} * CompositeResolver removes first part of the target with {@link URIPath#omitFirst()}
* before calling the child Resolvers. * before calling the child Resolvers.
* <p>
* Example: {@code resolverService.registerResolver("/test/", compositeResolver);}
* The Resolvers added to CompositeResolver will be given Request with URIPath "/".
* *
* @author Rsl1122 * @author Rsl1122
*/ */
public final class CompositeResolver implements Resolver { public final class CompositeResolver implements Resolver {
private final List<String> prefixes; private final List<String> prefixes;
private final List<Resolver> resolvers; private final List<Function<Request, Optional<Response>>> resolvers;
private final List<Predicate<Request>> canAccess;
CompositeResolver() { CompositeResolver() {
this.prefixes = new ArrayList<>(); this.prefixes = new ArrayList<>();
this.resolvers = new ArrayList<>(); this.resolvers = new ArrayList<>();
this.canAccess = new ArrayList<>();
} }
public static CompositeResolver.Builder builder() { public static CompositeResolver.Builder builder() {
return new Builder(); return new Builder();
} }
private Optional<Resolver> getResolver(URIPath target) { private Optional<Function<Request, Optional<Response>>> getResolver(URIPath target) {
return target.getPart(0).flatMap(this::find); return target.getPart(0).flatMap(this::findResolver);
} }
private Optional<Resolver> find(String prefix) { private Optional<Predicate<Request>> getAccessCheck(URIPath target) {
return target.getPart(0).flatMap(this::findAccessCheck);
}
private Optional<Function<Request, Optional<Response>>> findResolver(String prefix) {
for (int i = 0; i < prefixes.size(); i++) { for (int i = 0; i < prefixes.size(); i++) {
if (prefixes.get(i).equals(prefix)) { if (prefixes.get(i).equals(prefix)) {
return Optional.of(resolvers.get(i)); return Optional.of(resolvers.get(i));
@ -58,24 +69,44 @@ public final class CompositeResolver implements Resolver {
return Optional.empty(); return Optional.empty();
} }
private Optional<Predicate<Request>> findAccessCheck(String prefix) {
for (int i = 0; i < prefixes.size(); i++) {
if (prefixes.get(i).equals(prefix)) {
return Optional.of(canAccess.get(i));
}
}
return Optional.empty();
}
void add(String prefix, Resolver resolver) { void add(String prefix, Resolver resolver) {
if (prefix == null) throw new IllegalArgumentException("Prefix can not be null"); if (prefix == null) throw new IllegalArgumentException("Prefix can not be null");
if (resolver == null) throw new IllegalArgumentException("Resolver can not be null"); if (resolver == null) throw new IllegalArgumentException("Resolver can not be null");
prefixes.add(prefix); prefixes.add(prefix);
resolvers.add(resolver); resolvers.add(resolver::resolve);
canAccess.add(resolver::canAccess);
}
void add(String prefix, Function<Request, Response> resolver, Predicate<Request> accessCheck) {
if (prefix == null) throw new IllegalArgumentException("Prefix can not be null");
if (resolver == null) throw new IllegalArgumentException("Resolver can not be null");
if (accessCheck == null) throw new IllegalArgumentException("Resolver can not be null");
prefixes.add(prefix);
resolvers.add(request -> Optional.ofNullable(resolver.apply(request)));
canAccess.add(accessCheck);
} }
@Override @Override
public boolean canAccess(Request request) { public boolean canAccess(Request request) {
return getResolver(request.getPath()) Request forThis = request.omitFirstInPath();
.map(resolver -> resolver.canAccess(request)) return getAccessCheck(forThis.getPath())
.map(resolver -> resolver.test(forThis))
.orElse(true); .orElse(true);
} }
@Override @Override
public Optional<Response> resolve(Request request) { public Optional<Response> resolve(Request request) {
return getResolver(request.getPath()) Request forThis = request.omitFirstInPath();
.flatMap(resolver -> resolver.resolve(request)); return getResolver(forThis.getPath()).flatMap(resolver -> resolver.apply(forThis));
} }
public static class Builder { public static class Builder {
@ -97,6 +128,18 @@ public final class CompositeResolver implements Resolver {
return this; return this;
} }
/**
* Add a new resolver to the CompositeResolver by using functional interfaces
*
* @param prefix Start of the target (first part of the target string, eg "example" in "/example/target/", or "" in "/")
* @param resolver Resolver to call for this target, {@link URIPath#omitFirst()} will be called for Resolver method calls.
* @return this builder.
*/
public Builder add(String prefix, Function<Request, Response> resolver, Predicate<Request> accessCheck) {
composite.add(prefix, resolver, accessCheck);
return this;
}
public CompositeResolver build() { public CompositeResolver build() {
return composite; return composite;
} }

View File

@ -17,6 +17,7 @@
package com.djrapitops.plan.delivery.web.resolver; package com.djrapitops.plan.delivery.web.resolver;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@ -46,6 +47,10 @@ public final class Response {
return bytes; return bytes;
} }
public String getAsString() {
return new String(bytes, StandardCharsets.UTF_8);
}
public int getCode() { public int getCode() {
return code; return code;
} }

View File

@ -51,6 +51,21 @@ public final class Request {
this.headers = headers; this.headers = headers;
} }
// Special constructor that figures out URIPath and URIQuery from "/path/and?query=params"
public Request(String method, String target, WebUser user, Map<String, String> headers) {
this.method = method;
if (target.contains("?")) {
String[] halves = target.split("\\?", 2);
this.path = new URIPath(halves[0]);
this.query = new URIQuery(halves[1]);
} else {
this.path = new URIPath(target);
this.query = new URIQuery("");
}
this.user = user;
this.headers = headers;
}
/** /**
* Get HTTP method. * Get HTTP method.
* *
@ -96,4 +111,8 @@ public final class Request {
public Optional<String> getHeader(String key) { public Optional<String> getHeader(String key) {
return Optional.ofNullable(headers.get(key)); return Optional.ofNullable(headers.get(key));
} }
public Request omitFirstInPath() {
return new Request(method, path.omitFirst(), query, user, headers);
}
} }

View File

@ -18,10 +18,9 @@ package com.djrapitops.plan.delivery.export;
import com.djrapitops.plan.delivery.rendering.pages.Page; import com.djrapitops.plan.delivery.rendering.pages.Page;
import com.djrapitops.plan.delivery.rendering.pages.PageFactory; import com.djrapitops.plan.delivery.rendering.pages.PageFactory;
import com.djrapitops.plan.delivery.webserver.RequestTarget; import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.webserver.pages.json.RootJSONResolver; import com.djrapitops.plan.delivery.webserver.pages.json.RootJSONResolver;
import com.djrapitops.plan.delivery.webserver.response.Response_old;
import com.djrapitops.plan.delivery.webserver.response.errors.ErrorResponse;
import com.djrapitops.plan.exceptions.connection.NotFoundException; import com.djrapitops.plan.exceptions.connection.NotFoundException;
import com.djrapitops.plan.exceptions.connection.WebException; import com.djrapitops.plan.exceptions.connection.WebException;
import com.djrapitops.plan.identification.Server; import com.djrapitops.plan.identification.Server;
@ -36,8 +35,9 @@ import org.apache.commons.lang3.StringUtils;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.io.IOException; import java.io.IOException;
import java.net.URI;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Collections;
import java.util.Optional;
/** /**
* Handles exporting of /network page html, data and resources. * Handles exporting of /network page html, data and resources.
@ -121,9 +121,9 @@ public class NetworkPageExporter extends FileExporter {
} }
private void exportJSON(Path toDirectory, String resource) throws NotFoundException, IOException { private void exportJSON(Path toDirectory, String resource) throws NotFoundException, IOException {
Response_old found = getJSONResponse(resource); Optional<Response> found = getJSONResponse(resource);
if (found instanceof ErrorResponse) { if (!found.isPresent()) {
throw new NotFoundException(resource + " was not properly exported: " + found.getContent()); throw new NotFoundException(resource + " was not properly exported: not found");
} }
String jsonResourceName = toFileName(toJSONResourceName(resource)) + ".json"; String jsonResourceName = toFileName(toJSONResourceName(resource)) + ".json";
@ -131,7 +131,7 @@ public class NetworkPageExporter extends FileExporter {
String relativePlayerLink = toRelativePathFromRoot("player"); String relativePlayerLink = toRelativePathFromRoot("player");
export(toDirectory.resolve("data").resolve(jsonResourceName), export(toDirectory.resolve("data").resolve(jsonResourceName),
// Replace ../player in urls to fix player page links // Replace ../player in urls to fix player page links
StringUtils.replaceEach(found.getContent(), StringUtils.replaceEach(found.get().getAsString(),
new String[]{"../player", "./player"}, new String[]{"../player", "./player"},
new String[]{relativePlayerLink, relativePlayerLink} new String[]{relativePlayerLink, relativePlayerLink}
) )
@ -143,9 +143,9 @@ public class NetworkPageExporter extends FileExporter {
return StringUtils.replaceEach(resource, new String[]{"?", "&", "type=", "server="}, new String[]{"-", "_", "", ""}); return StringUtils.replaceEach(resource, new String[]{"?", "&", "type=", "server="}, new String[]{"-", "_", "", ""});
} }
private Response_old getJSONResponse(String resource) { private Optional<Response> getJSONResponse(String resource) {
try { try {
return jsonHandler.resolve(null, new RequestTarget(URI.create(resource))); return jsonHandler.getResolver().resolve(new Request("GET", "/v1/" + resource, null, Collections.emptyMap()));
} catch (WebException e) { } catch (WebException e) {
// The rest of the exceptions should not be thrown // The rest of the exceptions should not be thrown
throw new IllegalStateException("Unexpected exception thrown: " + e.toString(), e); throw new IllegalStateException("Unexpected exception thrown: " + e.toString(), e);

View File

@ -18,10 +18,9 @@ package com.djrapitops.plan.delivery.export;
import com.djrapitops.plan.delivery.rendering.pages.Page; import com.djrapitops.plan.delivery.rendering.pages.Page;
import com.djrapitops.plan.delivery.rendering.pages.PageFactory; import com.djrapitops.plan.delivery.rendering.pages.PageFactory;
import com.djrapitops.plan.delivery.webserver.RequestTarget; import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.webserver.pages.json.RootJSONResolver; import com.djrapitops.plan.delivery.webserver.pages.json.RootJSONResolver;
import com.djrapitops.plan.delivery.webserver.response.Response_old;
import com.djrapitops.plan.delivery.webserver.response.errors.ErrorResponse;
import com.djrapitops.plan.exceptions.connection.NotFoundException; import com.djrapitops.plan.exceptions.connection.NotFoundException;
import com.djrapitops.plan.exceptions.connection.WebException; import com.djrapitops.plan.exceptions.connection.WebException;
import com.djrapitops.plan.settings.locale.Locale; import com.djrapitops.plan.settings.locale.Locale;
@ -36,8 +35,9 @@ import org.apache.commons.lang3.StringUtils;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.io.IOException; import java.io.IOException;
import java.net.URI;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Collections;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
/** /**
@ -104,14 +104,14 @@ public class PlayerPageExporter extends FileExporter {
} }
private void exportJSON(ExportPaths exportPaths, Path toDirectory, String resource, String playerName) throws NotFoundException, IOException { private void exportJSON(ExportPaths exportPaths, Path toDirectory, String resource, String playerName) throws NotFoundException, IOException {
Response_old found = getJSONResponse(resource); Optional<Response> found = getJSONResponse(resource);
if (found instanceof ErrorResponse) { if (!found.isPresent()) {
throw new NotFoundException(resource + " was not properly exported: " + found.getContent()); throw new NotFoundException(resource + " was not properly exported: no response");
} }
String jsonResourceName = toFileName(toJSONResourceName(resource)) + ".json"; String jsonResourceName = toFileName(toJSONResourceName(resource)) + ".json";
export(toDirectory.resolve(jsonResourceName), found.getContent()); export(toDirectory.resolve(jsonResourceName), found.get().getBytes());
exportPaths.put("../v1/player?player=" + playerName, "./" + jsonResourceName); exportPaths.put("../v1/player?player=" + playerName, "./" + jsonResourceName);
} }
@ -119,9 +119,9 @@ public class PlayerPageExporter extends FileExporter {
return StringUtils.replaceEach(resource, new String[]{"?", "&", "type=", "player="}, new String[]{"-", "_", "", ""}); return StringUtils.replaceEach(resource, new String[]{"?", "&", "type=", "player="}, new String[]{"-", "_", "", ""});
} }
private Response_old getJSONResponse(String resource) { private Optional<Response> getJSONResponse(String resource) {
try { try {
return jsonHandler.resolve(null, new RequestTarget(URI.create(resource))); return jsonHandler.getResolver().resolve(new Request("GET", "/v1/" + resource, null, Collections.emptyMap()));
} catch (WebException e) { } catch (WebException e) {
// The rest of the exceptions should not be thrown // The rest of the exceptions should not be thrown
throw new IllegalStateException("Unexpected exception thrown: " + e.toString(), e); throw new IllegalStateException("Unexpected exception thrown: " + e.toString(), e);

View File

@ -18,10 +18,9 @@ package com.djrapitops.plan.delivery.export;
import com.djrapitops.plan.delivery.rendering.pages.Page; import com.djrapitops.plan.delivery.rendering.pages.Page;
import com.djrapitops.plan.delivery.rendering.pages.PageFactory; import com.djrapitops.plan.delivery.rendering.pages.PageFactory;
import com.djrapitops.plan.delivery.webserver.RequestTarget; import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.webserver.pages.json.RootJSONResolver; import com.djrapitops.plan.delivery.webserver.pages.json.RootJSONResolver;
import com.djrapitops.plan.delivery.webserver.response.Response_old;
import com.djrapitops.plan.delivery.webserver.response.errors.ErrorResponse;
import com.djrapitops.plan.exceptions.connection.NotFoundException; import com.djrapitops.plan.exceptions.connection.NotFoundException;
import com.djrapitops.plan.exceptions.connection.WebException; import com.djrapitops.plan.exceptions.connection.WebException;
import com.djrapitops.plan.identification.ServerInfo; import com.djrapitops.plan.identification.ServerInfo;
@ -36,8 +35,9 @@ import org.apache.commons.lang3.StringUtils;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.io.IOException; import java.io.IOException;
import java.net.URI;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Collections;
import java.util.Optional;
/** /**
* Handles exporting of /players page html, data and resources. * Handles exporting of /players page html, data and resources.
@ -99,16 +99,16 @@ public class PlayersPageExporter extends FileExporter {
} }
private void exportJSON(Path toDirectory) throws NotFoundException, IOException { private void exportJSON(Path toDirectory) throws NotFoundException, IOException {
Response_old found = getJSONResponse("players"); Optional<Response> found = getJSONResponse("players");
if (found instanceof ErrorResponse) { if (!found.isPresent()) {
throw new NotFoundException("players page was not properly exported: " + found.getContent()); throw new NotFoundException("players page was not properly exported: not found");
} }
String jsonResourceName = toFileName(toJSONResourceName("players")) + ".json"; String jsonResourceName = toFileName(toJSONResourceName("players")) + ".json";
export(toDirectory.resolve("data").resolve(jsonResourceName), export(toDirectory.resolve("data").resolve(jsonResourceName),
// Replace ../player in urls to fix player page links // Replace ../player in urls to fix player page links
StringUtils.replace(found.getContent(), "../player", toRelativePathFromRoot("player")) StringUtils.replace(found.get().getAsString(), "../player", toRelativePathFromRoot("player"))
); );
exportPaths.put("./v1/players", toRelativePathFromRoot("data/" + jsonResourceName)); exportPaths.put("./v1/players", toRelativePathFromRoot("data/" + jsonResourceName));
} }
@ -117,9 +117,9 @@ public class PlayersPageExporter extends FileExporter {
return StringUtils.replaceEach(resource, new String[]{"?", "&", "type=", "server="}, new String[]{"-", "_", "", ""}); return StringUtils.replaceEach(resource, new String[]{"?", "&", "type=", "server="}, new String[]{"-", "_", "", ""});
} }
private Response_old getJSONResponse(String resource) { private Optional<Response> getJSONResponse(String resource) {
try { try {
return jsonHandler.resolve(null, new RequestTarget(URI.create(resource))); return jsonHandler.getResolver().resolve(new Request("GET", "/v1/" + resource, null, Collections.emptyMap()));
} catch (WebException e) { } catch (WebException e) {
// The rest of the exceptions should not be thrown // The rest of the exceptions should not be thrown
throw new IllegalStateException("Unexpected exception thrown: " + e.toString(), e); throw new IllegalStateException("Unexpected exception thrown: " + e.toString(), e);

View File

@ -18,10 +18,9 @@ package com.djrapitops.plan.delivery.export;
import com.djrapitops.plan.delivery.rendering.pages.Page; import com.djrapitops.plan.delivery.rendering.pages.Page;
import com.djrapitops.plan.delivery.rendering.pages.PageFactory; import com.djrapitops.plan.delivery.rendering.pages.PageFactory;
import com.djrapitops.plan.delivery.webserver.RequestTarget; import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.webserver.pages.json.RootJSONResolver; import com.djrapitops.plan.delivery.webserver.pages.json.RootJSONResolver;
import com.djrapitops.plan.delivery.webserver.response.Response_old;
import com.djrapitops.plan.delivery.webserver.response.errors.ErrorResponse;
import com.djrapitops.plan.exceptions.connection.NotFoundException; import com.djrapitops.plan.exceptions.connection.NotFoundException;
import com.djrapitops.plan.exceptions.connection.WebException; import com.djrapitops.plan.exceptions.connection.WebException;
import com.djrapitops.plan.identification.Server; import com.djrapitops.plan.identification.Server;
@ -37,8 +36,9 @@ import org.apache.commons.lang3.StringUtils;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.io.IOException; import java.io.IOException;
import java.net.URI;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Collections;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
/** /**
@ -133,16 +133,16 @@ public class ServerPageExporter extends FileExporter {
} }
private void exportJSON(Path toDirectory, String resource) throws NotFoundException, IOException { private void exportJSON(Path toDirectory, String resource) throws NotFoundException, IOException {
Response_old found = getJSONResponse(resource); Optional<Response> found = getJSONResponse(resource);
if (found instanceof ErrorResponse) { if (!found.isPresent()) {
throw new NotFoundException(resource + " was not properly exported: " + found.getContent()); throw new NotFoundException(resource + " was not properly exported: not found");
} }
String jsonResourceName = toFileName(toJSONResourceName(resource)) + ".json"; String jsonResourceName = toFileName(toJSONResourceName(resource)) + ".json";
export(toDirectory.resolve("data").resolve(jsonResourceName), export(toDirectory.resolve("data").resolve(jsonResourceName),
// Replace ../player in urls to fix player page links // Replace ../player in urls to fix player page links
StringUtils.replace(found.getContent(), "../player", toRelativePathFromRoot("player")) StringUtils.replace(found.get().getAsString(), "../player", toRelativePathFromRoot("player"))
); );
exportPaths.put("../v1/" + resource, toRelativePathFromRoot("data/" + jsonResourceName)); exportPaths.put("../v1/" + resource, toRelativePathFromRoot("data/" + jsonResourceName));
} }
@ -151,9 +151,9 @@ public class ServerPageExporter extends FileExporter {
return StringUtils.replaceEach(resource, new String[]{"?", "&", "type=", "server="}, new String[]{"-", "_", "", ""}); return StringUtils.replaceEach(resource, new String[]{"?", "&", "type=", "server="}, new String[]{"-", "_", "", ""});
} }
private Response_old getJSONResponse(String resource) { private Optional<Response> getJSONResponse(String resource) {
try { try {
return jsonHandler.resolve(null, new RequestTarget(URI.create(resource))); return jsonHandler.getResolver().resolve(new Request("GET", "/v1/" + resource, null, Collections.emptyMap()));
} catch (WebException e) { } catch (WebException e) {
// The rest of the exceptions should not be thrown // The rest of the exceptions should not be thrown
throw new IllegalStateException("Unexpected exception thrown: " + e.toString(), e); throw new IllegalStateException("Unexpected exception thrown: " + e.toString(), e);

View File

@ -50,7 +50,7 @@ import java.util.regex.Pattern;
* @author Rsl1122 * @author Rsl1122
*/ */
@Singleton @Singleton
public class ResponseResolver extends CompositePageResolver { public class ResponseResolver {
private final DebugPageResolver debugPageResolver; private final DebugPageResolver debugPageResolver;
private final PlayersPageResolver playersPageResolver; private final PlayersPageResolver playersPageResolver;
@ -62,6 +62,7 @@ public class ResponseResolver extends CompositePageResolver {
private final ErrorHandler errorHandler; private final ErrorHandler errorHandler;
private final ResolverService resolverService; private final ResolverService resolverService;
private final ResponseFactory responseFactory;
private final Lazy<WebServer> webServer; private final Lazy<WebServer> webServer;
@Inject @Inject
@ -80,8 +81,8 @@ public class ResponseResolver extends CompositePageResolver {
ErrorHandler errorHandler ErrorHandler errorHandler
) { ) {
super(responseFactory);
this.resolverService = resolverService; this.resolverService = resolverService;
this.responseFactory = responseFactory;
this.webServer = webServer; this.webServer = webServer;
this.debugPageResolver = debugPageResolver; this.debugPageResolver = debugPageResolver;
this.playersPageResolver = playersPageResolver; this.playersPageResolver = playersPageResolver;
@ -94,17 +95,17 @@ public class ResponseResolver extends CompositePageResolver {
} }
public void registerPages() { public void registerPages() {
String pluginName = "Plan"; String plugin = "Plan";
resolverService.registerResolver(pluginName, "/debug", debugPageResolver); resolverService.registerResolver(plugin, "/debug", debugPageResolver);
resolverService.registerResolver(pluginName, "/players", playersPageResolver); resolverService.registerResolver(plugin, "/players", playersPageResolver);
resolverService.registerResolver(pluginName, "/player", playerPageResolver); resolverService.registerResolver(plugin, "/player", playerPageResolver);
resolverService.registerResolver(pluginName, "/favicon.ico", noAuthResolverFor(responseFactory.faviconResponse())); resolverService.registerResolver(plugin, "/favicon.ico", noAuthResolverFor(responseFactory.faviconResponse()));
resolverService.registerResolver(pluginName, "/network", serverPageResolver); resolverService.registerResolver(plugin, "/network", serverPageResolver);
resolverService.registerResolver(pluginName, "/server", serverPageResolver); resolverService.registerResolver(plugin, "/server", serverPageResolver);
resolverService.registerResolverForMatches(pluginName, Pattern.compile("^/$"), rootPageResolver); resolverService.registerResolverForMatches(plugin, Pattern.compile("^/$"), rootPageResolver);
resolverService.registerResolverForMatches(pluginName, Pattern.compile("^/(vendor|css|js|img)/.*"), staticResourceResolver); resolverService.registerResolverForMatches(plugin, Pattern.compile("^/(vendor|css|js|img)/.*"), staticResourceResolver);
registerPage("v1", rootJSONResolver); resolverService.registerResolver(plugin, "/v1", rootJSONResolver.getResolver());
} }
public NoAuthResolver noAuthResolverFor(Response response) { public NoAuthResolver noAuthResolverFor(Response response) {

View File

@ -16,9 +16,9 @@
*/ */
package com.djrapitops.plan.delivery.webserver.cache; package com.djrapitops.plan.delivery.webserver.cache;
import com.djrapitops.plan.delivery.web.resolver.MimeType;
import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.webserver.pages.json.RootJSONResolver; import com.djrapitops.plan.delivery.webserver.pages.json.RootJSONResolver;
import com.djrapitops.plan.delivery.webserver.response.Response_old;
import com.djrapitops.plan.delivery.webserver.response.data.JSONResponse;
import com.djrapitops.plan.storage.file.ResourceCache; import com.djrapitops.plan.storage.file.ResourceCache;
import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.AbsRunnable;
import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Cache;
@ -27,6 +27,7 @@ import org.apache.commons.lang3.StringUtils;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -39,7 +40,7 @@ import java.util.stream.Collectors;
*/ */
public class JSONCache { public class JSONCache {
private static final Cache<String, String> cache = Caffeine.newBuilder() private static final Cache<String, byte[]> cache = Caffeine.newBuilder()
.expireAfterAccess(2, TimeUnit.MINUTES) .expireAfterAccess(2, TimeUnit.MINUTES)
.build(); .build();
@ -47,33 +48,42 @@ public class JSONCache {
// Static class // Static class
} }
public static Response_old getOrCache(String identifier, Supplier<JSONResponse> jsonResponseSupplier) { public static Response getOrCache(String identifier, Supplier<Response> jsonResponseSupplier) {
String found = cache.getIfPresent(identifier); byte[] found = cache.getIfPresent(identifier);
if (found == null) { if (found == null) {
JSONResponse response = jsonResponseSupplier.get(); Response response = jsonResponseSupplier.get();
cache.put(identifier, response.getContent()); cache.put(identifier, response.getBytes());
return response; return response;
} }
return new JSONResponse(found); return Response.builder()
.setMimeType(MimeType.JSON)
.setContent(found)
.build();
} }
public static String getOrCacheString(DataID dataID, UUID serverUUID, Supplier<String> stringSupplier) { public static String getOrCacheString(DataID dataID, UUID serverUUID, Supplier<String> stringSupplier) {
String identifier = dataID.of(serverUUID); String identifier = dataID.of(serverUUID);
String found = cache.getIfPresent(identifier); byte[] found = cache.getIfPresent(identifier);
if (found == null) { if (found == null) {
String result = stringSupplier.get(); String result = stringSupplier.get();
cache.put(identifier, result); cache.put(identifier, result.getBytes(StandardCharsets.UTF_8));
return result; return result;
} }
return found; return new String(found, StandardCharsets.UTF_8);
} }
public static Response_old getOrCache(DataID dataID, Supplier<JSONResponse> jsonResponseSupplier) { public static <T> Response getOrCache(DataID dataID, Supplier<T> jsonResponseSupplier) {
return getOrCache(dataID.name(), jsonResponseSupplier); return getOrCache(dataID.name(), () -> Response.builder()
.setMimeType(MimeType.JSON)
.setJSONContent(jsonResponseSupplier.get())
.build());
} }
public static Response_old getOrCache(DataID dataID, UUID serverUUID, Supplier<JSONResponse> jsonResponseSupplier) { public static <T> Response getOrCache(DataID dataID, UUID serverUUID, Supplier<T> jsonResponseSupplier) {
return getOrCache(dataID.of(serverUUID), jsonResponseSupplier); return getOrCache(dataID.of(serverUUID), () -> Response.builder()
.setMimeType(MimeType.JSON)
.setJSONContent(jsonResponseSupplier.get())
.build());
} }
public static void invalidate(String identifier) { public static void invalidate(String identifier) {

View File

@ -17,22 +17,19 @@
package com.djrapitops.plan.delivery.webserver.pages.json; package com.djrapitops.plan.delivery.webserver.pages.json;
import com.djrapitops.plan.delivery.rendering.json.graphs.GraphJSONCreator; import com.djrapitops.plan.delivery.rendering.json.graphs.GraphJSONCreator;
import com.djrapitops.plan.delivery.webserver.RequestInternal; import com.djrapitops.plan.delivery.web.resolver.Resolver;
import com.djrapitops.plan.delivery.webserver.RequestTarget; import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.webserver.auth.Authentication; import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
import com.djrapitops.plan.delivery.webserver.cache.DataID; import com.djrapitops.plan.delivery.webserver.cache.DataID;
import com.djrapitops.plan.delivery.webserver.cache.JSONCache; import com.djrapitops.plan.delivery.webserver.cache.JSONCache;
import com.djrapitops.plan.delivery.webserver.pages.PageResolver;
import com.djrapitops.plan.delivery.webserver.response.Response_old;
import com.djrapitops.plan.delivery.webserver.response.data.JSONResponse;
import com.djrapitops.plan.exceptions.WebUserAuthException;
import com.djrapitops.plan.exceptions.connection.BadRequestException; import com.djrapitops.plan.exceptions.connection.BadRequestException;
import com.djrapitops.plan.exceptions.connection.WebException;
import com.djrapitops.plan.identification.Identifiers; import com.djrapitops.plan.identification.Identifiers;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.util.Collections; import java.util.Collections;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
/** /**
@ -41,7 +38,7 @@ import java.util.UUID;
* @author Rsl1122 * @author Rsl1122
*/ */
@Singleton @Singleton
public class GraphsJSONResolver implements PageResolver { public class GraphsJSONResolver implements Resolver {
private final Identifiers identifiers; private final Identifiers identifiers;
private final GraphJSONCreator graphJSON; private final GraphJSONCreator graphJSON;
@ -56,14 +53,23 @@ public class GraphsJSONResolver implements PageResolver {
} }
@Override @Override
public Response_old resolve(RequestInternal request, RequestTarget target) throws WebException { public boolean canAccess(Request request) {
String type = target.getParameter("type") return request.getUser().orElse(new WebUser("")).hasPermission("page.server");
}
@Override
public Optional<Response> resolve(Request request) {
return Optional.of(getResponse(request));
}
private Response getResponse(Request request) {
String type = request.getQuery().get("type")
.orElseThrow(() -> new BadRequestException("'type' parameter was not defined.")); .orElseThrow(() -> new BadRequestException("'type' parameter was not defined."));
DataID dataID = getDataID(type); DataID dataID = getDataID(type);
if (target.getParameter("server").isPresent()) { if (request.getQuery().get("server").isPresent()) {
UUID serverUUID = identifiers.getServerUUID(target); // Can throw BadRequestException UUID serverUUID = identifiers.getServerUUID(request); // Can throw BadRequestException
return JSONCache.getOrCache(dataID, serverUUID, () -> generateGraphDataJSONOfType(dataID, serverUUID)); return JSONCache.getOrCache(dataID, serverUUID, () -> generateGraphDataJSONOfType(dataID, serverUUID));
} }
// Assume network // Assume network
@ -86,48 +92,43 @@ public class GraphsJSONResolver implements PageResolver {
} }
} }
private JSONResponse generateGraphDataJSONOfType(DataID id, UUID serverUUID) { private Object generateGraphDataJSONOfType(DataID id, UUID serverUUID) {
switch (id) { switch (id) {
case GRAPH_PERFORMANCE: case GRAPH_PERFORMANCE:
return new JSONResponse(graphJSON.performanceGraphJSON(serverUUID)); return graphJSON.performanceGraphJSON(serverUUID);
case GRAPH_ONLINE: case GRAPH_ONLINE:
return new JSONResponse(graphJSON.playersOnlineGraph(serverUUID)); return graphJSON.playersOnlineGraph(serverUUID);
case GRAPH_UNIQUE_NEW: case GRAPH_UNIQUE_NEW:
return new JSONResponse(graphJSON.uniqueAndNewGraphJSON(serverUUID)); return graphJSON.uniqueAndNewGraphJSON(serverUUID);
case GRAPH_CALENDAR: case GRAPH_CALENDAR:
return new JSONResponse(graphJSON.serverCalendarJSON(serverUUID)); return graphJSON.serverCalendarJSON(serverUUID);
case GRAPH_WORLD_PIE: case GRAPH_WORLD_PIE:
return new JSONResponse(graphJSON.serverWorldPieJSONAsMap(serverUUID)); return graphJSON.serverWorldPieJSONAsMap(serverUUID);
case GRAPH_ACTIVITY: case GRAPH_ACTIVITY:
return new JSONResponse(graphJSON.activityGraphsJSONAsMap(serverUUID)); return graphJSON.activityGraphsJSONAsMap(serverUUID);
case GRAPH_WORLD_MAP: case GRAPH_WORLD_MAP:
return new JSONResponse(graphJSON.geolocationGraphsJSONAsMap(serverUUID)); return graphJSON.geolocationGraphsJSONAsMap(serverUUID);
case GRAPH_PING: case GRAPH_PING:
return new JSONResponse(graphJSON.pingGraphsJSON(serverUUID)); return graphJSON.pingGraphsJSON(serverUUID);
case GRAPH_PUNCHCARD: case GRAPH_PUNCHCARD:
return new JSONResponse(graphJSON.punchCardJSONAsMap(serverUUID)); return graphJSON.punchCardJSONAsMap(serverUUID);
default: default:
return new JSONResponse(Collections.singletonMap("error", "Undefined ID: " + id.name())); return Collections.singletonMap("error", "Undefined ID: " + id.name());
} }
} }
private JSONResponse generateGraphDataJSONOfType(DataID id) { private Object generateGraphDataJSONOfType(DataID id) {
switch (id) { switch (id) {
case GRAPH_ACTIVITY: case GRAPH_ACTIVITY:
return new JSONResponse(graphJSON.activityGraphsJSONAsMap()); return graphJSON.activityGraphsJSONAsMap();
case GRAPH_UNIQUE_NEW: case GRAPH_UNIQUE_NEW:
return new JSONResponse(graphJSON.uniqueAndNewGraphJSON()); return graphJSON.uniqueAndNewGraphJSON();
case GRAPH_SERVER_PIE: case GRAPH_SERVER_PIE:
return new JSONResponse(graphJSON.serverPreferencePieJSONAsMap()); return graphJSON.serverPreferencePieJSONAsMap();
case GRAPH_WORLD_MAP: case GRAPH_WORLD_MAP:
return new JSONResponse(graphJSON.geolocationGraphsJSONAsMap()); return graphJSON.geolocationGraphsJSONAsMap();
default: default:
return new JSONResponse(Collections.singletonMap("error", "Undefined ID: " + id.name())); return Collections.singletonMap("error", "Undefined ID: " + id.name());
} }
} }
@Override
public boolean isAuthorized(Authentication auth, RequestTarget target) throws WebUserAuthException {
return auth.getWebUser().getPermLevel() <= 0;
}
} }

View File

@ -21,11 +21,8 @@ import com.djrapitops.plan.delivery.rendering.json.network.NetworkOverviewJSONCr
import com.djrapitops.plan.delivery.rendering.json.network.NetworkPlayerBaseOverviewJSONCreator; import com.djrapitops.plan.delivery.rendering.json.network.NetworkPlayerBaseOverviewJSONCreator;
import com.djrapitops.plan.delivery.rendering.json.network.NetworkSessionsOverviewJSONCreator; import com.djrapitops.plan.delivery.rendering.json.network.NetworkSessionsOverviewJSONCreator;
import com.djrapitops.plan.delivery.rendering.json.network.NetworkTabJSONCreator; import com.djrapitops.plan.delivery.rendering.json.network.NetworkTabJSONCreator;
import com.djrapitops.plan.delivery.webserver.RequestTarget; import com.djrapitops.plan.delivery.web.resolver.CompositeResolver;
import com.djrapitops.plan.delivery.webserver.auth.Authentication;
import com.djrapitops.plan.delivery.webserver.cache.DataID; import com.djrapitops.plan.delivery.webserver.cache.DataID;
import com.djrapitops.plan.delivery.webserver.pages.CompositePageResolver;
import com.djrapitops.plan.delivery.webserver.response.ResponseFactory;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -36,31 +33,31 @@ import javax.inject.Singleton;
* @author Rsl1122 * @author Rsl1122
*/ */
@Singleton @Singleton
public class NetworkJSONResolver extends CompositePageResolver { public class NetworkJSONResolver {
private final CompositeResolver resolver;
@Inject @Inject
public NetworkJSONResolver( public NetworkJSONResolver(
ResponseFactory responseFactory,
JSONFactory jsonFactory, JSONFactory jsonFactory,
NetworkOverviewJSONCreator networkOverviewJSONCreator, NetworkOverviewJSONCreator networkOverviewJSONCreator,
NetworkPlayerBaseOverviewJSONCreator networkPlayerBaseOverviewJSONCreator, NetworkPlayerBaseOverviewJSONCreator networkPlayerBaseOverviewJSONCreator,
NetworkSessionsOverviewJSONCreator networkSessionsOverviewJSONCreator NetworkSessionsOverviewJSONCreator networkSessionsOverviewJSONCreator
) { ) {
super(responseFactory); resolver = CompositeResolver.builder()
.add("overview", forJSON(DataID.SERVER_OVERVIEW, networkOverviewJSONCreator))
registerPage("overview", DataID.SERVER_OVERVIEW, networkOverviewJSONCreator); .add("playerbaseOverview", forJSON(DataID.PLAYERBASE_OVERVIEW, networkPlayerBaseOverviewJSONCreator))
registerPage("playerbaseOverview", DataID.PLAYERBASE_OVERVIEW, networkPlayerBaseOverviewJSONCreator); .add("sessionsOverview", forJSON(DataID.SESSIONS_OVERVIEW, networkSessionsOverviewJSONCreator))
registerPage("sessionsOverview", DataID.SESSIONS_OVERVIEW, networkSessionsOverviewJSONCreator); .add("servers", forJSON(DataID.SERVERS, jsonFactory::serversAsJSONMaps))
registerPage("servers", DataID.SERVERS, jsonFactory::serversAsJSONMaps); .add("pingTable", forJSON(DataID.PING_TABLE, jsonFactory::pingPerGeolocation))
registerPage("pingTable", DataID.PING_TABLE, jsonFactory::pingPerGeolocation); .build();
} }
private <T> void registerPage(String identifier, DataID dataID, NetworkTabJSONCreator<T> tabJSONCreator) { private <T> NetworkTabJSONResolver<T> forJSON(DataID dataID, NetworkTabJSONCreator<T> tabJSONCreator) {
registerPage(identifier, new NetworkTabJSONResolver<>(dataID, tabJSONCreator)); return new NetworkTabJSONResolver<>(dataID, tabJSONCreator);
} }
@Override public CompositeResolver getResolver() {
public boolean isAuthorized(Authentication auth, RequestTarget target) { return resolver;
return true;
} }
} }

View File

@ -17,16 +17,14 @@
package com.djrapitops.plan.delivery.webserver.pages.json; package com.djrapitops.plan.delivery.webserver.pages.json;
import com.djrapitops.plan.delivery.rendering.json.network.NetworkTabJSONCreator; import com.djrapitops.plan.delivery.rendering.json.network.NetworkTabJSONCreator;
import com.djrapitops.plan.delivery.webserver.RequestInternal; import com.djrapitops.plan.delivery.web.resolver.Resolver;
import com.djrapitops.plan.delivery.webserver.RequestTarget; import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.webserver.auth.Authentication; import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
import com.djrapitops.plan.delivery.webserver.cache.DataID; import com.djrapitops.plan.delivery.webserver.cache.DataID;
import com.djrapitops.plan.delivery.webserver.cache.JSONCache; import com.djrapitops.plan.delivery.webserver.cache.JSONCache;
import com.djrapitops.plan.delivery.webserver.pages.PageResolver;
import com.djrapitops.plan.delivery.webserver.response.Response_old;
import com.djrapitops.plan.delivery.webserver.response.data.JSONResponse;
import com.djrapitops.plan.exceptions.WebUserAuthException;
import java.util.Optional;
import java.util.function.Supplier; import java.util.function.Supplier;
/** /**
@ -34,7 +32,7 @@ import java.util.function.Supplier;
* *
* @author Rsl1122 * @author Rsl1122
*/ */
public class NetworkTabJSONResolver<T> implements PageResolver { public class NetworkTabJSONResolver<T> implements Resolver {
private final DataID dataID; private final DataID dataID;
private final Supplier<T> jsonCreator; private final Supplier<T> jsonCreator;
@ -45,12 +43,17 @@ public class NetworkTabJSONResolver<T> implements PageResolver {
} }
@Override @Override
public Response_old resolve(RequestInternal request, RequestTarget target) { public boolean canAccess(Request request) {
return JSONCache.getOrCache(dataID, () -> new JSONResponse(jsonCreator.get())); return request.getUser().orElse(new WebUser("")).hasPermission("page.network");
} }
@Override @Override
public boolean isAuthorized(Authentication auth, RequestTarget target) throws WebUserAuthException { public Optional<Response> resolve(Request request) {
return auth.getWebUser().getPermLevel() <= 0; return Optional.of(getResponse());
} }
private Response getResponse() {
return JSONCache.getOrCache(dataID, jsonCreator);
}
} }

View File

@ -16,24 +16,21 @@
*/ */
package com.djrapitops.plan.delivery.webserver.pages.json; package com.djrapitops.plan.delivery.webserver.pages.json;
import com.djrapitops.plan.delivery.domain.WebUser_old;
import com.djrapitops.plan.delivery.rendering.json.PlayerJSONCreator; import com.djrapitops.plan.delivery.rendering.json.PlayerJSONCreator;
import com.djrapitops.plan.delivery.webserver.RequestInternal; import com.djrapitops.plan.delivery.web.resolver.MimeType;
import com.djrapitops.plan.delivery.webserver.RequestTarget; import com.djrapitops.plan.delivery.web.resolver.Resolver;
import com.djrapitops.plan.delivery.webserver.auth.Authentication; import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.webserver.pages.PageResolver; import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.webserver.response.Response_old; import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
import com.djrapitops.plan.delivery.webserver.response.data.JSONResponse;
import com.djrapitops.plan.exceptions.WebUserAuthException;
import com.djrapitops.plan.exceptions.connection.WebException;
import com.djrapitops.plan.identification.Identifiers; import com.djrapitops.plan.identification.Identifiers;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
@Singleton @Singleton
public class PlayerJSONResolver implements PageResolver { public class PlayerJSONResolver implements Resolver {
private final Identifiers identifiers; private final Identifiers identifiers;
private final PlayerJSONCreator jsonCreator; private final PlayerJSONCreator jsonCreator;
@ -45,15 +42,24 @@ public class PlayerJSONResolver implements PageResolver {
} }
@Override @Override
public Response_old resolve(RequestInternal request, RequestTarget target) throws WebException { public boolean canAccess(Request request) {
UUID playerUUID = identifiers.getPlayerUUID(target); // Can throw BadRequestException WebUser user = request.getUser().orElse(new WebUser(""));
return new JSONResponse(jsonCreator.createJSONAsMap(playerUUID)); UUID playerUUID = identifiers.getPlayerUUID(request);
UUID webUserUUID = identifiers.getPlayerUUID(user.getName());
boolean isOwnPage = playerUUID.equals(webUserUUID);
return user.hasPermission("page.player.other") || (user.hasPermission("page.player.self") && isOwnPage);
} }
@Override @Override
public boolean isAuthorized(Authentication auth, RequestTarget target) throws WebUserAuthException { public Optional<Response> resolve(Request request) {
WebUser_old webUser = auth.getWebUser(); return Optional.of(getResponse(request));
return webUser.getPermLevel() <= 1 || webUser.getName().equalsIgnoreCase(target.get(target.size() - 1)); }
private Response getResponse(Request request) {
UUID playerUUID = identifiers.getPlayerUUID(request); // Can throw BadRequestException
return Response.builder()
.setMimeType(MimeType.JSON)
.setJSONContent(jsonCreator.createJSONAsMap(playerUUID))
.build();
} }
} }

View File

@ -17,21 +17,18 @@
package com.djrapitops.plan.delivery.webserver.pages.json; package com.djrapitops.plan.delivery.webserver.pages.json;
import com.djrapitops.plan.delivery.rendering.json.JSONFactory; import com.djrapitops.plan.delivery.rendering.json.JSONFactory;
import com.djrapitops.plan.delivery.webserver.RequestInternal; import com.djrapitops.plan.delivery.web.resolver.Resolver;
import com.djrapitops.plan.delivery.webserver.RequestTarget; import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.webserver.auth.Authentication; import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
import com.djrapitops.plan.delivery.webserver.cache.DataID; import com.djrapitops.plan.delivery.webserver.cache.DataID;
import com.djrapitops.plan.delivery.webserver.cache.JSONCache; import com.djrapitops.plan.delivery.webserver.cache.JSONCache;
import com.djrapitops.plan.delivery.webserver.pages.PageResolver;
import com.djrapitops.plan.delivery.webserver.response.Response_old;
import com.djrapitops.plan.delivery.webserver.response.data.JSONResponse;
import com.djrapitops.plan.exceptions.WebUserAuthException;
import com.djrapitops.plan.exceptions.connection.WebException;
import com.djrapitops.plan.identification.Identifiers; import com.djrapitops.plan.identification.Identifiers;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.util.Collections; import java.util.Collections;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
/** /**
@ -40,7 +37,7 @@ import java.util.UUID;
* @author Rsl1122 * @author Rsl1122
*/ */
@Singleton @Singleton
public class PlayerKillsJSONResolver implements PageResolver { public class PlayerKillsJSONResolver implements Resolver {
private final Identifiers identifiers; private final Identifiers identifiers;
private final JSONFactory jsonFactory; private final JSONFactory jsonFactory;
@ -55,15 +52,17 @@ public class PlayerKillsJSONResolver implements PageResolver {
} }
@Override @Override
public Response_old resolve(RequestInternal request, RequestTarget target) throws WebException { public boolean canAccess(Request request) {
UUID serverUUID = identifiers.getServerUUID(target); return request.getUser().orElse(new WebUser("")).hasPermission("page.server");
return JSONCache.getOrCache(DataID.KILLS, serverUUID, () ->
new JSONResponse(Collections.singletonMap("player_kills", jsonFactory.serverPlayerKillsAsJSONMap(serverUUID)))
);
} }
@Override @Override
public boolean isAuthorized(Authentication auth, RequestTarget target) throws WebUserAuthException { public Optional<Response> resolve(Request request) {
return auth.getWebUser().getPermLevel() <= 0; return Optional.of(getResponse(request));
}
private Response getResponse(Request request) {
UUID serverUUID = identifiers.getServerUUID(request);
return JSONCache.getOrCache(DataID.KILLS, serverUUID, () -> Collections.singletonMap("player_kills", jsonFactory.serverPlayerKillsAsJSONMap(serverUUID)));
} }
} }

View File

@ -17,20 +17,17 @@
package com.djrapitops.plan.delivery.webserver.pages.json; package com.djrapitops.plan.delivery.webserver.pages.json;
import com.djrapitops.plan.delivery.rendering.json.JSONFactory; import com.djrapitops.plan.delivery.rendering.json.JSONFactory;
import com.djrapitops.plan.delivery.webserver.RequestInternal; import com.djrapitops.plan.delivery.web.resolver.Resolver;
import com.djrapitops.plan.delivery.webserver.RequestTarget; import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.webserver.auth.Authentication; import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
import com.djrapitops.plan.delivery.webserver.cache.DataID; import com.djrapitops.plan.delivery.webserver.cache.DataID;
import com.djrapitops.plan.delivery.webserver.cache.JSONCache; import com.djrapitops.plan.delivery.webserver.cache.JSONCache;
import com.djrapitops.plan.delivery.webserver.pages.PageResolver;
import com.djrapitops.plan.delivery.webserver.response.Response_old;
import com.djrapitops.plan.delivery.webserver.response.data.JSONResponse;
import com.djrapitops.plan.exceptions.WebUserAuthException;
import com.djrapitops.plan.exceptions.connection.WebException;
import com.djrapitops.plan.identification.Identifiers; import com.djrapitops.plan.identification.Identifiers;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
/** /**
@ -39,7 +36,7 @@ import java.util.UUID;
* @author Rsl1122 * @author Rsl1122
*/ */
@Singleton @Singleton
public class PlayersTableJSONResolver implements PageResolver { public class PlayersTableJSONResolver implements Resolver {
private final Identifiers identifiers; private final Identifiers identifiers;
private final JSONFactory jsonFactory; private final JSONFactory jsonFactory;
@ -54,21 +51,26 @@ public class PlayersTableJSONResolver implements PageResolver {
} }
@Override @Override
public Response_old resolve(RequestInternal request, RequestTarget target) throws WebException { public boolean canAccess(Request request) {
if (target.getParameter("server").isPresent()) { WebUser user = request.getUser().orElse(new WebUser(""));
UUID serverUUID = identifiers.getServerUUID(target); // Can throw BadRequestException if (request.getQuery().get("server").isPresent()) {
return JSONCache.getOrCache(DataID.PLAYERS, serverUUID, () -> new JSONResponse(jsonFactory.serverPlayersTableJSON(serverUUID))); return user.hasPermission("page.server");
} }
// Assume players page // Assume players page
return JSONCache.getOrCache(DataID.PLAYERS, () -> new JSONResponse(jsonFactory.networkPlayersTableJSON())); return user.hasPermission("page.players");
} }
@Override @Override
public boolean isAuthorized(Authentication auth, RequestTarget target) throws WebUserAuthException { public Optional<Response> resolve(Request request) {
if (target.getParameter("server").isPresent()) { return Optional.of(getResponse(request));
return auth.getWebUser().getPermLevel() <= 0; }
private Response getResponse(Request request) {
if (request.getQuery().get("server").isPresent()) {
UUID serverUUID = identifiers.getServerUUID(request); // Can throw BadRequestException
return JSONCache.getOrCache(DataID.PLAYERS, serverUUID, () -> jsonFactory.serverPlayersTableJSON(serverUUID));
} }
// Assume players page // Assume players page
return auth.getWebUser().getPermLevel() <= 1; return JSONCache.getOrCache(DataID.PLAYERS, jsonFactory::networkPlayersTableJSON);
} }
} }

View File

@ -17,11 +17,8 @@
package com.djrapitops.plan.delivery.webserver.pages.json; package com.djrapitops.plan.delivery.webserver.pages.json;
import com.djrapitops.plan.delivery.rendering.json.*; import com.djrapitops.plan.delivery.rendering.json.*;
import com.djrapitops.plan.delivery.webserver.RequestTarget; import com.djrapitops.plan.delivery.web.resolver.CompositeResolver;
import com.djrapitops.plan.delivery.webserver.auth.Authentication;
import com.djrapitops.plan.delivery.webserver.cache.DataID; import com.djrapitops.plan.delivery.webserver.cache.DataID;
import com.djrapitops.plan.delivery.webserver.pages.CompositePageResolver;
import com.djrapitops.plan.delivery.webserver.response.ResponseFactory;
import com.djrapitops.plan.identification.Identifiers; import com.djrapitops.plan.identification.Identifiers;
import javax.inject.Inject; import javax.inject.Inject;
@ -33,13 +30,13 @@ import javax.inject.Singleton;
* @author Rsl1122 * @author Rsl1122
*/ */
@Singleton @Singleton
public class RootJSONResolver extends CompositePageResolver { public class RootJSONResolver {
private final Identifiers identifiers; private final Identifiers identifiers;
private final CompositeResolver resolver;
@Inject @Inject
public RootJSONResolver( public RootJSONResolver(
ResponseFactory responseFactory,
Identifiers identifiers, Identifiers identifiers,
JSONFactory jsonFactory, JSONFactory jsonFactory,
@ -57,32 +54,30 @@ public class RootJSONResolver extends CompositePageResolver {
PlayerJSONResolver playerJSONResolver, PlayerJSONResolver playerJSONResolver,
NetworkJSONResolver networkJSONResolver NetworkJSONResolver networkJSONResolver
) { ) {
super(responseFactory);
this.identifiers = identifiers; this.identifiers = identifiers;
registerPage("players", playersTableJSONResolver, 1); resolver = CompositeResolver.builder()
registerPage("sessions", sessionsJSONResolver, 0); .add("players", playersTableJSONResolver)
registerPage("kills", playerKillsJSONResolver, 0); .add("sessions", sessionsJSONResolver)
registerPage("pingTable", DataID.PING_TABLE, jsonFactory::pingPerGeolocation); .add("kills", playerKillsJSONResolver)
registerPage("graph", graphsJSONResolver, 0); .add("graph", graphsJSONResolver)
.add("pingTable", forJSON(DataID.PING_TABLE, jsonFactory::pingPerGeolocation))
registerPage("serverOverview", DataID.SERVER_OVERVIEW, serverOverviewJSONCreator); .add("serverOverview", forJSON(DataID.SERVER_OVERVIEW, serverOverviewJSONCreator))
registerPage("onlineOverview", DataID.ONLINE_OVERVIEW, onlineActivityOverviewJSONCreator); .add("onlineOverview", forJSON(DataID.ONLINE_OVERVIEW, onlineActivityOverviewJSONCreator))
registerPage("sessionsOverview", DataID.SESSIONS_OVERVIEW, sessionsOverviewJSONCreator); .add("sessionsOverview", forJSON(DataID.SESSIONS_OVERVIEW, sessionsOverviewJSONCreator))
registerPage("playerVersus", DataID.PVP_PVE, pvPPvEJSONCreator); .add("playerVersus", forJSON(DataID.PVP_PVE, pvPPvEJSONCreator))
registerPage("playerbaseOverview", DataID.PLAYERBASE_OVERVIEW, playerBaseOverviewJSONCreator); .add("playerbaseOverview", forJSON(DataID.PLAYERBASE_OVERVIEW, playerBaseOverviewJSONCreator))
registerPage("performanceOverview", DataID.PERFORMANCE_OVERVIEW, performanceJSONCreator); .add("performanceOverview", forJSON(DataID.PERFORMANCE_OVERVIEW, performanceJSONCreator))
.add("player", playerJSONResolver)
registerPage("player", playerJSONResolver, 2); .add("network", networkJSONResolver.getResolver())
registerPage("network", networkJSONResolver, 0); .build();
} }
private <T> void registerPage(String identifier, DataID dataID, ServerTabJSONCreator<T> tabJSONCreator) { private <T> ServerTabJSONResolver<T> forJSON(DataID dataID, ServerTabJSONCreator<T> tabJSONCreator) {
registerPage(identifier, new ServerTabJSONResolver<>(dataID, identifiers, tabJSONCreator), 0); return new ServerTabJSONResolver<>(dataID, identifiers, tabJSONCreator);
} }
@Override public CompositeResolver getResolver() {
public boolean isAuthorized(Authentication auth, RequestTarget target) { return resolver;
return true;
} }
} }

View File

@ -17,18 +17,15 @@
package com.djrapitops.plan.delivery.webserver.pages.json; package com.djrapitops.plan.delivery.webserver.pages.json;
import com.djrapitops.plan.delivery.rendering.json.ServerTabJSONCreator; import com.djrapitops.plan.delivery.rendering.json.ServerTabJSONCreator;
import com.djrapitops.plan.delivery.webserver.RequestInternal; import com.djrapitops.plan.delivery.web.resolver.Resolver;
import com.djrapitops.plan.delivery.webserver.RequestTarget; import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.webserver.auth.Authentication; import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
import com.djrapitops.plan.delivery.webserver.cache.DataID; import com.djrapitops.plan.delivery.webserver.cache.DataID;
import com.djrapitops.plan.delivery.webserver.cache.JSONCache; import com.djrapitops.plan.delivery.webserver.cache.JSONCache;
import com.djrapitops.plan.delivery.webserver.pages.PageResolver;
import com.djrapitops.plan.delivery.webserver.response.Response_old;
import com.djrapitops.plan.delivery.webserver.response.data.JSONResponse;
import com.djrapitops.plan.exceptions.WebUserAuthException;
import com.djrapitops.plan.exceptions.connection.WebException;
import com.djrapitops.plan.identification.Identifiers; import com.djrapitops.plan.identification.Identifiers;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.function.Function; import java.util.function.Function;
@ -37,7 +34,7 @@ import java.util.function.Function;
* *
* @author Rsl1122 * @author Rsl1122
*/ */
public class ServerTabJSONResolver<T> implements PageResolver { public class ServerTabJSONResolver<T> implements Resolver {
private final DataID dataID; private final DataID dataID;
private final Identifiers identifiers; private final Identifiers identifiers;
@ -54,13 +51,14 @@ public class ServerTabJSONResolver<T> implements PageResolver {
} }
@Override @Override
public Response_old resolve(RequestInternal request, RequestTarget target) throws WebException { public boolean canAccess(Request request) {
UUID serverUUID = identifiers.getServerUUID(target); // Can throw BadRequestException return request.getUser().orElse(new WebUser("")).hasPermission("page.server");
return JSONCache.getOrCache(dataID, serverUUID, () -> new JSONResponse(jsonCreator.apply(serverUUID)));
} }
@Override @Override
public boolean isAuthorized(Authentication auth, RequestTarget target) throws WebUserAuthException { public Optional<Response> resolve(Request request) {
return auth.getWebUser().getPermLevel() <= 0; UUID serverUUID = identifiers.getServerUUID(request); // Can throw BadRequestException
return Optional.of(JSONCache.getOrCache(dataID, serverUUID, () -> jsonCreator.apply(serverUUID)));
} }
} }

View File

@ -17,21 +17,18 @@
package com.djrapitops.plan.delivery.webserver.pages.json; package com.djrapitops.plan.delivery.webserver.pages.json;
import com.djrapitops.plan.delivery.rendering.json.JSONFactory; import com.djrapitops.plan.delivery.rendering.json.JSONFactory;
import com.djrapitops.plan.delivery.webserver.RequestInternal; import com.djrapitops.plan.delivery.web.resolver.Resolver;
import com.djrapitops.plan.delivery.webserver.RequestTarget; import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.webserver.auth.Authentication; import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
import com.djrapitops.plan.delivery.webserver.cache.DataID; import com.djrapitops.plan.delivery.webserver.cache.DataID;
import com.djrapitops.plan.delivery.webserver.cache.JSONCache; import com.djrapitops.plan.delivery.webserver.cache.JSONCache;
import com.djrapitops.plan.delivery.webserver.pages.PageResolver;
import com.djrapitops.plan.delivery.webserver.response.Response_old;
import com.djrapitops.plan.delivery.webserver.response.data.JSONResponse;
import com.djrapitops.plan.exceptions.WebUserAuthException;
import com.djrapitops.plan.exceptions.connection.WebException;
import com.djrapitops.plan.identification.Identifiers; import com.djrapitops.plan.identification.Identifiers;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.util.Collections; import java.util.Collections;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
/** /**
@ -40,7 +37,7 @@ import java.util.UUID;
* @author Rsl1122 * @author Rsl1122
*/ */
@Singleton @Singleton
public class SessionsJSONResolver implements PageResolver { public class SessionsJSONResolver implements Resolver {
private final Identifiers identifiers; private final Identifiers identifiers;
private final JSONFactory jsonFactory; private final JSONFactory jsonFactory;
@ -55,21 +52,21 @@ public class SessionsJSONResolver implements PageResolver {
} }
@Override @Override
public Response_old resolve(RequestInternal request, RequestTarget target) throws WebException { public boolean canAccess(Request request) {
if (target.getParameter("server").isPresent()) { return request.getUser().orElse(new WebUser("")).hasPermission("page.server");
UUID serverUUID = identifiers.getServerUUID(target);
return JSONCache.getOrCache(DataID.SESSIONS, serverUUID, () ->
new JSONResponse(Collections.singletonMap("sessions", jsonFactory.serverSessionsAsJSONMap(serverUUID)))
);
}
// Assume network
return JSONCache.getOrCache(DataID.SESSIONS, () ->
new JSONResponse(Collections.singletonMap("sessions", jsonFactory.networkSessionsAsJSONMap()))
);
} }
@Override @Override
public boolean isAuthorized(Authentication auth, RequestTarget target) throws WebUserAuthException { public Optional<Response> resolve(Request request) {
return auth.getWebUser().getPermLevel() <= 0; return Optional.of(getResponse(request));
}
private Response getResponse(Request request) {
if (request.getQuery().get("server").isPresent()) {
UUID serverUUID = identifiers.getServerUUID(request);
return JSONCache.getOrCache(DataID.SESSIONS, serverUUID, () -> Collections.singletonMap("sessions", jsonFactory.serverSessionsAsJSONMap(serverUUID)));
}
// Assume network
return JSONCache.getOrCache(DataID.SESSIONS, () -> Collections.singletonMap("sessions", jsonFactory.networkSessionsAsJSONMap()));
} }
} }

View File

@ -21,7 +21,7 @@ package com.djrapitops.plan.exceptions.connection;
* *
* @author Rsl1122 * @author Rsl1122
*/ */
public class WebException extends Exception { public class WebException extends IllegalStateException {
public WebException() { public WebException() {
} }

View File

@ -16,7 +16,7 @@
*/ */
package com.djrapitops.plan.identification; package com.djrapitops.plan.identification;
import com.djrapitops.plan.delivery.webserver.RequestTarget; import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.exceptions.connection.BadRequestException; import com.djrapitops.plan.exceptions.connection.BadRequestException;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries; import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
@ -36,21 +36,20 @@ import java.util.UUID;
public class Identifiers { public class Identifiers {
protected final DBSystem dbSystem; protected final DBSystem dbSystem;
private final UUIDUtility uuidUtility;
@Inject @Inject
public Identifiers(DBSystem dbSystem) { public Identifiers(DBSystem dbSystem, UUIDUtility uuidUtility) {
this.dbSystem = dbSystem; this.dbSystem = dbSystem;
this.uuidUtility = uuidUtility;
} }
public UUID getServerUUID(RequestTarget target) throws BadRequestException { public UUID getServerUUID(Request request) throws BadRequestException {
String serverIndentifier = target.getParameter("server") String serverIndentifier = request.getQuery().get("server")
.orElseThrow(() -> new BadRequestException("'server' parameter was not defined.")); .orElseThrow(() -> new BadRequestException("'server' parameter was not defined."));
Optional<UUID> parsed = UUIDUtility.parseFromString(serverIndentifier); Optional<UUID> parsed = UUIDUtility.parseFromString(serverIndentifier);
if (parsed.isPresent()) { return parsed.orElseGet(() -> getServerUUIDFromName(serverIndentifier));
return parsed.get();
}
return getServerUUIDFromName(serverIndentifier);
} }
private UUID getServerUUIDFromName(String serverName) throws BadRequestException { private UUID getServerUUIDFromName(String serverName) throws BadRequestException {
@ -59,15 +58,12 @@ public class Identifiers {
.orElseThrow(() -> new BadRequestException("Given 'server' was not found in the database: '" + serverName + "'")); .orElseThrow(() -> new BadRequestException("Given 'server' was not found in the database: '" + serverName + "'"));
} }
public UUID getPlayerUUID(RequestTarget target) throws BadRequestException { public UUID getPlayerUUID(Request request) throws BadRequestException {
String playerIdentifier = target.getParameter("player") String playerIdentifier = request.getQuery().get("player")
.orElseThrow(() -> new BadRequestException("'player' parameter was not defined.")).trim(); .orElseThrow(() -> new BadRequestException("'player' parameter was not defined.")).trim();
Optional<UUID> parsed = UUIDUtility.parseFromString(playerIdentifier); Optional<UUID> parsed = UUIDUtility.parseFromString(playerIdentifier);
if (parsed.isPresent()) { return parsed.orElseGet(() -> getPlayerUUIDFromName(playerIdentifier));
return parsed.get();
}
return getPlayerUUIDFromName(playerIdentifier);
} }
private UUID getPlayerUUIDFromName(String playerName) throws BadRequestException { private UUID getPlayerUUIDFromName(String playerName) throws BadRequestException {
@ -75,4 +71,8 @@ public class Identifiers {
.query(UserIdentifierQueries.fetchPlayerUUIDOf(playerName)) .query(UserIdentifierQueries.fetchPlayerUUIDOf(playerName))
.orElseThrow(() -> new BadRequestException("Given 'player' was not found in the database: '" + playerName + "'")); .orElseThrow(() -> new BadRequestException("Given 'player' was not found in the database: '" + playerName + "'"));
} }
public UUID getPlayerUUID(String name) {
return uuidUtility.getUUIDOf(name);
}
} }