mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-21 05:50:18 +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"
|
||||
}
|
||||
|
||||
ext.apiVersion = '5.1-R0.1'
|
||||
ext.apiVersion = '5.1-R0.2'
|
||||
|
||||
bintray {
|
||||
user = System.getenv('BINTRAY_USER')
|
||||
|
@ -67,6 +67,10 @@ enum Capability {
|
||||
* {@link com.djrapitops.plan.delivery.web.ResolverService}
|
||||
*/
|
||||
PAGE_EXTENSION_RESOLVERS,
|
||||
/**
|
||||
* {@link com.djrapitops.plan.delivery.web.ResolverService#getResolvers(String)}
|
||||
*/
|
||||
PAGE_EXTENSION_RESOLVERS_LIST,
|
||||
/**
|
||||
* {@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 java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -74,6 +75,18 @@ public interface ResolverService {
|
||||
*/
|
||||
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 {
|
||||
static ResolverService service;
|
||||
|
||||
|
@ -68,6 +68,18 @@ public class ResolverSvc implements ResolverService {
|
||||
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) {
|
||||
for (Container container : basicResolvers) {
|
||||
if (container.matcher.test(target)) return Optional.of(container.plugin);
|
||||
|
@ -35,6 +35,7 @@ import dagger.Lazy;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -100,7 +101,7 @@ public class ResponseResolver {
|
||||
resolverService.registerResolver(plugin, "/network", serverPageResolver);
|
||||
resolverService.registerResolver(plugin, "/server", serverPageResolver);
|
||||
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());
|
||||
}
|
||||
@ -136,30 +137,33 @@ public class ResponseResolver {
|
||||
|
||||
Optional<Authentication> authentication = internalRequest.getAuth();
|
||||
|
||||
Optional<Resolver> foundResolver = resolverService.getResolver(internalRequest.getPath().asString());
|
||||
if (!foundResolver.isPresent()) return responseFactory.pageNotFound404();
|
||||
List<Resolver> foundResolvers = resolverService.getResolvers(internalRequest.getPath().asString());
|
||||
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 (resolver.requiresAuth(request)) {
|
||||
// Get required auth
|
||||
boolean isAuthRequired = webServer.get().isAuthRequired();
|
||||
if (isAuthRequired && !authentication.isPresent()) {
|
||||
if (webServer.get().isUsingHTTPS()) {
|
||||
return responseFactory.basicAuth();
|
||||
if (!isAuthRequired || resolver.canAccess(request)) {
|
||||
Optional<Response> resolved = resolver.resolve(request);
|
||||
if (resolved.isPresent()) return resolved.get();
|
||||
} else {
|
||||
return responseFactory.forbidden403();
|
||||
}
|
||||
}
|
||||
|
||||
if (!isAuthRequired || resolver.canAccess(request)) {
|
||||
return resolver.resolve(request).orElseGet(responseFactory::pageNotFound404);
|
||||
} 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;
|
||||
|
||||
import com.djrapitops.plan.delivery.rendering.html.Html;
|
||||
import com.djrapitops.plan.delivery.web.resolver.Resolver;
|
||||
import com.djrapitops.plan.delivery.web.resolver.Response;
|
||||
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.webserver.ResponseFactory;
|
||||
import com.djrapitops.plan.identification.UUIDUtility;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -60,17 +62,26 @@ public class PlayerPageResolver implements Resolver {
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
URIPath path = request.getPath();
|
||||
Optional<String> part = path.getPart(1);
|
||||
if (!part.isPresent()) return Optional.empty();
|
||||
if (StringUtils.containsAny(path.asString(), "/vendor/", "/js/", "/css/", "/img/")) {
|
||||
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);
|
||||
if (playerUUID == null) return Optional.of(responseFactory.uuidNotFound404());
|
||||
if (playerUUID == null) return responseFactory.uuidNotFound404();
|
||||
|
||||
boolean raw = path.getPart(2).map("raw"::equalsIgnoreCase).orElse(false);
|
||||
return Optional.of(
|
||||
raw ? responseFactory.rawPlayerPageResponse(playerUUID)
|
||||
: responseFactory.playerPageResponse(playerUUID)
|
||||
);
|
||||
if (raw) {
|
||||
return responseFactory.rawPlayerPageResponse(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
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
@ -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.Response;
|
||||
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 org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@ -47,7 +48,7 @@ public class StaticResourceResolver implements NoAuthResolver {
|
||||
}
|
||||
|
||||
private Response getResponse(Request request) {
|
||||
String resource = request.getPath().asString().substring(1);
|
||||
String resource = getPath(request).asString().substring(1);
|
||||
if (resource.endsWith(".css")) {
|
||||
return responseFactory.cssResponse(resource);
|
||||
}
|
||||
@ -62,4 +63,13 @@ public class StaticResourceResolver implements NoAuthResolver {
|
||||
}
|
||||
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 {
|
||||
UUID_404("Player UUID was not found in the database."),
|
||||
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>"),
|
||||
UNAUTHORIZED_401("Unauthorized"),
|
||||
AUTHENTICATION_FAILED_401("Authentication Failed."),
|
||||
|
@ -295,7 +295,7 @@ HTML ERRORS - AUTHENTICATION_FAILED_401 || Authentication Failed.
|
||||
HTML ERRORS - FORBIDDEN_403 || Forbidden
|
||||
HTML ERRORS - NO_SERVERS_404 || No Servers online to perform the request.
|
||||
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 - 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>
|
||||
|
Loading…
Reference in New Issue
Block a user