mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-27 09:00:28 +08:00
Made resource resolution more flexible
- API 5.1-R0.2: Added ResolverService#getResolvers method - /players/ now redirects to /players - All error pages now have proper css Affects issues: - Fixed #1378
This commit is contained in:
parent
24fc3f665f
commit
45d6bfb840
@ -7,7 +7,7 @@ dependencies {
|
|||||||
compileOnly "com.google.code.gson:gson:$gsonVersion"
|
compileOnly "com.google.code.gson:gson:$gsonVersion"
|
||||||
}
|
}
|
||||||
|
|
||||||
ext.apiVersion = '5.1-R0.1'
|
ext.apiVersion = '5.1-R0.2'
|
||||||
|
|
||||||
bintray {
|
bintray {
|
||||||
user = System.getenv('BINTRAY_USER')
|
user = System.getenv('BINTRAY_USER')
|
||||||
|
@ -67,6 +67,10 @@ enum Capability {
|
|||||||
* {@link com.djrapitops.plan.delivery.web.ResolverService}
|
* {@link com.djrapitops.plan.delivery.web.ResolverService}
|
||||||
*/
|
*/
|
||||||
PAGE_EXTENSION_RESOLVERS,
|
PAGE_EXTENSION_RESOLVERS,
|
||||||
|
/**
|
||||||
|
* {@link com.djrapitops.plan.delivery.web.ResolverService#getResolvers(String)}
|
||||||
|
*/
|
||||||
|
PAGE_EXTENSION_RESOLVERS_LIST,
|
||||||
/**
|
/**
|
||||||
* {@link com.djrapitops.plan.delivery.web.ResourceService}
|
* {@link com.djrapitops.plan.delivery.web.ResourceService}
|
||||||
*/
|
*/
|
||||||
|
@ -18,6 +18,7 @@ package com.djrapitops.plan.delivery.web;
|
|||||||
|
|
||||||
import com.djrapitops.plan.delivery.web.resolver.Resolver;
|
import com.djrapitops.plan.delivery.web.resolver.Resolver;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@ -74,6 +75,18 @@ public interface ResolverService {
|
|||||||
*/
|
*/
|
||||||
Optional<Resolver> getResolver(String target);
|
Optional<Resolver> getResolver(String target);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain all Resolvers that match the target.
|
||||||
|
* <p>
|
||||||
|
* If first returns Optional.empty next one should be used.
|
||||||
|
* <p>
|
||||||
|
* Requires Capability PAGE_EXTENSION_RESOLVERS_LIST.
|
||||||
|
*
|
||||||
|
* @param target "/example/target"
|
||||||
|
* @return List of Resolvers if registered or empty list.
|
||||||
|
*/
|
||||||
|
List<Resolver> getResolvers(String target);
|
||||||
|
|
||||||
class Holder {
|
class Holder {
|
||||||
static ResolverService service;
|
static ResolverService service;
|
||||||
|
|
||||||
|
@ -68,6 +68,18 @@ public class ResolverSvc implements ResolverService {
|
|||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Resolver> getResolvers(String target) {
|
||||||
|
List<Resolver> resolvers = new ArrayList<>();
|
||||||
|
for (Container container : basicResolvers) {
|
||||||
|
if (container.matcher.test(target)) resolvers.add(container.resolver);
|
||||||
|
}
|
||||||
|
for (Container container : regexResolvers) {
|
||||||
|
if (container.matcher.test(target)) resolvers.add(container.resolver);
|
||||||
|
}
|
||||||
|
return resolvers;
|
||||||
|
}
|
||||||
|
|
||||||
public Optional<String> getPluginInChargeOf(String target) {
|
public Optional<String> getPluginInChargeOf(String target) {
|
||||||
for (Container container : basicResolvers) {
|
for (Container container : basicResolvers) {
|
||||||
if (container.matcher.test(target)) return Optional.of(container.plugin);
|
if (container.matcher.test(target)) return Optional.of(container.plugin);
|
||||||
|
@ -35,6 +35,7 @@ import dagger.Lazy;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@ -100,7 +101,7 @@ public class ResponseResolver {
|
|||||||
resolverService.registerResolver(plugin, "/network", serverPageResolver);
|
resolverService.registerResolver(plugin, "/network", serverPageResolver);
|
||||||
resolverService.registerResolver(plugin, "/server", serverPageResolver);
|
resolverService.registerResolver(plugin, "/server", serverPageResolver);
|
||||||
resolverService.registerResolverForMatches(plugin, Pattern.compile("^/$"), rootPageResolver);
|
resolverService.registerResolverForMatches(plugin, Pattern.compile("^/$"), rootPageResolver);
|
||||||
resolverService.registerResolverForMatches(plugin, Pattern.compile("^/(vendor|css|js|img)/.*"), staticResourceResolver);
|
resolverService.registerResolverForMatches(plugin, Pattern.compile("^.*/(vendor|css|js|img)/.*"), staticResourceResolver);
|
||||||
|
|
||||||
resolverService.registerResolver(plugin, "/v1", rootJSONResolver.getResolver());
|
resolverService.registerResolver(plugin, "/v1", rootJSONResolver.getResolver());
|
||||||
}
|
}
|
||||||
@ -136,30 +137,33 @@ public class ResponseResolver {
|
|||||||
|
|
||||||
Optional<Authentication> authentication = internalRequest.getAuth();
|
Optional<Authentication> authentication = internalRequest.getAuth();
|
||||||
|
|
||||||
Optional<Resolver> foundResolver = resolverService.getResolver(internalRequest.getPath().asString());
|
List<Resolver> foundResolvers = resolverService.getResolvers(internalRequest.getPath().asString());
|
||||||
if (!foundResolver.isPresent()) return responseFactory.pageNotFound404();
|
if (foundResolvers.isEmpty()) return responseFactory.pageNotFound404();
|
||||||
|
|
||||||
Resolver resolver = foundResolver.get();
|
for (Resolver resolver : foundResolvers) {
|
||||||
|
Request request = internalRequest.toAPIRequest();
|
||||||
|
if (resolver.requiresAuth(request)) {
|
||||||
|
// Get required auth
|
||||||
|
boolean isAuthRequired = webServer.get().isAuthRequired();
|
||||||
|
if (isAuthRequired && !authentication.isPresent()) {
|
||||||
|
if (webServer.get().isUsingHTTPS()) {
|
||||||
|
return responseFactory.basicAuth();
|
||||||
|
} else {
|
||||||
|
return responseFactory.forbidden403();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Request request = internalRequest.toAPIRequest();
|
if (!isAuthRequired || resolver.canAccess(request)) {
|
||||||
if (resolver.requiresAuth(request)) {
|
Optional<Response> resolved = resolver.resolve(request);
|
||||||
// Get required auth
|
if (resolved.isPresent()) return resolved.get();
|
||||||
boolean isAuthRequired = webServer.get().isAuthRequired();
|
|
||||||
if (isAuthRequired && !authentication.isPresent()) {
|
|
||||||
if (webServer.get().isUsingHTTPS()) {
|
|
||||||
return responseFactory.basicAuth();
|
|
||||||
} else {
|
} else {
|
||||||
return responseFactory.forbidden403();
|
return responseFactory.forbidden403();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!isAuthRequired || resolver.canAccess(request)) {
|
|
||||||
return resolver.resolve(request).orElseGet(responseFactory::pageNotFound404);
|
|
||||||
} else {
|
} else {
|
||||||
return responseFactory.forbidden403();
|
Optional<Response> resolved = resolver.resolve(request);
|
||||||
|
if (resolved.isPresent()) return resolved.get();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return resolver.resolve(request).orElseGet(responseFactory::pageNotFound404);
|
|
||||||
}
|
}
|
||||||
|
return responseFactory.pageNotFound404();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.djrapitops.plan.delivery.webserver.resolver;
|
package com.djrapitops.plan.delivery.webserver.resolver;
|
||||||
|
|
||||||
|
import com.djrapitops.plan.delivery.rendering.html.Html;
|
||||||
import com.djrapitops.plan.delivery.web.resolver.Resolver;
|
import com.djrapitops.plan.delivery.web.resolver.Resolver;
|
||||||
import com.djrapitops.plan.delivery.web.resolver.Response;
|
import com.djrapitops.plan.delivery.web.resolver.Response;
|
||||||
import com.djrapitops.plan.delivery.web.resolver.request.Request;
|
import com.djrapitops.plan.delivery.web.resolver.request.Request;
|
||||||
@ -23,6 +24,7 @@ import com.djrapitops.plan.delivery.web.resolver.request.URIPath;
|
|||||||
import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
|
import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
|
||||||
import com.djrapitops.plan.delivery.webserver.ResponseFactory;
|
import com.djrapitops.plan.delivery.webserver.ResponseFactory;
|
||||||
import com.djrapitops.plan.identification.UUIDUtility;
|
import com.djrapitops.plan.identification.UUIDUtility;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
@ -60,17 +62,26 @@ public class PlayerPageResolver implements Resolver {
|
|||||||
@Override
|
@Override
|
||||||
public Optional<Response> resolve(Request request) {
|
public Optional<Response> resolve(Request request) {
|
||||||
URIPath path = request.getPath();
|
URIPath path = request.getPath();
|
||||||
Optional<String> part = path.getPart(1);
|
if (StringUtils.containsAny(path.asString(), "/vendor/", "/js/", "/css/", "/img/")) {
|
||||||
if (!part.isPresent()) return Optional.empty();
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
return path.getPart(1)
|
||||||
|
.map(playerName -> getResponse(request.getPath(), playerName));
|
||||||
|
}
|
||||||
|
|
||||||
String playerName = part.get();
|
private Response getResponse(URIPath path, String playerName) {
|
||||||
UUID playerUUID = uuidUtility.getUUIDOf(playerName);
|
UUID playerUUID = uuidUtility.getUUIDOf(playerName);
|
||||||
if (playerUUID == null) return Optional.of(responseFactory.uuidNotFound404());
|
if (playerUUID == null) return responseFactory.uuidNotFound404();
|
||||||
|
|
||||||
boolean raw = path.getPart(2).map("raw"::equalsIgnoreCase).orElse(false);
|
boolean raw = path.getPart(2).map("raw"::equalsIgnoreCase).orElse(false);
|
||||||
return Optional.of(
|
if (raw) {
|
||||||
raw ? responseFactory.rawPlayerPageResponse(playerUUID)
|
return responseFactory.rawPlayerPageResponse(playerUUID);
|
||||||
: responseFactory.playerPageResponse(playerUUID)
|
}
|
||||||
);
|
|
||||||
|
if (path.getPart(2).isPresent()) {
|
||||||
|
// Redirect /player/Name/ to /player/Name
|
||||||
|
return responseFactory.redirectResponse("../" + Html.encodeToURL(playerName));
|
||||||
|
}
|
||||||
|
return responseFactory.playerPageResponse(playerUUID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,8 @@ public class PlayersPageResolver implements Resolver {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Response> resolve(Request request) {
|
public Optional<Response> resolve(Request request) {
|
||||||
|
// Redirect /players/ to /players
|
||||||
|
if (request.getPath().getPart(1).isPresent()) return Optional.of(responseFactory.redirectResponse("/players"));
|
||||||
return Optional.of(responseFactory.playersPageResponse());
|
return Optional.of(responseFactory.playersPageResponse());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ package com.djrapitops.plan.delivery.webserver.resolver;
|
|||||||
import com.djrapitops.plan.delivery.web.resolver.NoAuthResolver;
|
import com.djrapitops.plan.delivery.web.resolver.NoAuthResolver;
|
||||||
import com.djrapitops.plan.delivery.web.resolver.Response;
|
import com.djrapitops.plan.delivery.web.resolver.Response;
|
||||||
import com.djrapitops.plan.delivery.web.resolver.request.Request;
|
import com.djrapitops.plan.delivery.web.resolver.request.Request;
|
||||||
|
import com.djrapitops.plan.delivery.web.resolver.request.URIPath;
|
||||||
import com.djrapitops.plan.delivery.webserver.ResponseFactory;
|
import com.djrapitops.plan.delivery.webserver.ResponseFactory;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
@ -47,7 +48,7 @@ public class StaticResourceResolver implements NoAuthResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Response getResponse(Request request) {
|
private Response getResponse(Request request) {
|
||||||
String resource = request.getPath().asString().substring(1);
|
String resource = getPath(request).asString().substring(1);
|
||||||
if (resource.endsWith(".css")) {
|
if (resource.endsWith(".css")) {
|
||||||
return responseFactory.cssResponse(resource);
|
return responseFactory.cssResponse(resource);
|
||||||
}
|
}
|
||||||
@ -62,4 +63,13 @@ public class StaticResourceResolver implements NoAuthResolver {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private URIPath getPath(Request request) {
|
||||||
|
URIPath path = request.getPath();
|
||||||
|
// Remove everything before /vendor /css /js or /img
|
||||||
|
while (!path.getPart(0).map(part -> part.matches("(vendor|css|js|img)")).orElse(true)) {
|
||||||
|
path = path.omitFirst();
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
}
|
}
|
@ -24,7 +24,7 @@ package com.djrapitops.plan.settings.locale.lang;
|
|||||||
public enum ErrorPageLang implements Lang {
|
public enum ErrorPageLang implements Lang {
|
||||||
UUID_404("Player UUID was not found in the database."),
|
UUID_404("Player UUID was not found in the database."),
|
||||||
NO_SERVERS_404("No Servers online to perform the request."),
|
NO_SERVERS_404("No Servers online to perform the request."),
|
||||||
NOT_PLAYED_404("Player has not played on this server."),
|
NOT_PLAYED_404("Plan has not seen this player."),
|
||||||
UNKNOWN_PAGE_404("Make sure you're accessing a link given by a command, Examples:</p><p>/player/PlayerName<br>/server/ServerName</p>"),
|
UNKNOWN_PAGE_404("Make sure you're accessing a link given by a command, Examples:</p><p>/player/PlayerName<br>/server/ServerName</p>"),
|
||||||
UNAUTHORIZED_401("Unauthorized"),
|
UNAUTHORIZED_401("Unauthorized"),
|
||||||
AUTHENTICATION_FAILED_401("Authentication Failed."),
|
AUTHENTICATION_FAILED_401("Authentication Failed."),
|
||||||
|
@ -295,7 +295,7 @@ HTML ERRORS - AUTHENTICATION_FAILED_401 || Authentication Failed.
|
|||||||
HTML ERRORS - FORBIDDEN_403 || Forbidden
|
HTML ERRORS - FORBIDDEN_403 || Forbidden
|
||||||
HTML ERRORS - NO_SERVERS_404 || No Servers online to perform the request.
|
HTML ERRORS - NO_SERVERS_404 || No Servers online to perform the request.
|
||||||
HTML ERRORS - NOT_FOUND_404 || Not Found
|
HTML ERRORS - NOT_FOUND_404 || Not Found
|
||||||
HTML ERRORS - NOT_PLAYED_404 || Player has not played on this server.
|
HTML ERRORS - NOT_PLAYED_404 || Plan has not seen this player.
|
||||||
HTML ERRORS - PAGE_NOT_FOUND_404 || Page does not exist.
|
HTML ERRORS - PAGE_NOT_FOUND_404 || Page does not exist.
|
||||||
HTML ERRORS - UNAUTHORIZED_401 || Unauthorized
|
HTML ERRORS - UNAUTHORIZED_401 || Unauthorized
|
||||||
HTML ERRORS - UNKNOWN_PAGE_404 || Make sure you're accessing a link given by a command, Examples:</p><p>/player/PlayerName<br>/server/ServerName</p>
|
HTML ERRORS - UNKNOWN_PAGE_404 || Make sure you're accessing a link given by a command, Examples:</p><p>/player/PlayerName<br>/server/ServerName</p>
|
||||||
|
Loading…
Reference in New Issue
Block a user