mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-21 05:50:18 +08:00
Refactored Root page redirect
- Fixed issue where response code was not set - Fixed ResponseSender not setting values for response headers - Changed ResponseResolver to mostly use Response instead of _old
This commit is contained in:
parent
6ed6dd1f9f
commit
77dbc74cc5
@ -49,6 +49,7 @@ public class ResponseBuilder {
|
|||||||
* @return this builder.
|
* @return this builder.
|
||||||
*/
|
*/
|
||||||
public ResponseBuilder setStatus(int code) {
|
public ResponseBuilder setStatus(int code) {
|
||||||
|
response.code = code;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,6 +86,8 @@ public class ResponseBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ResponseBuilder setContent(String content, Charset charset) {
|
public ResponseBuilder setContent(String content, Charset charset) {
|
||||||
|
if (content == null) return setContent(new byte[0]);
|
||||||
|
if (charset == null) return setContent(content); // UTF-8 used
|
||||||
String mimeType = getMimeType();
|
String mimeType = getMimeType();
|
||||||
response.charset = charset;
|
response.charset = charset;
|
||||||
|
|
||||||
|
@ -29,26 +29,35 @@ import com.djrapitops.plan.version.VersionCheckSystem;
|
|||||||
public class ErrorMessagePage implements Page {
|
public class ErrorMessagePage implements Page {
|
||||||
|
|
||||||
private final String template;
|
private final String template;
|
||||||
|
private final Icon icon;
|
||||||
private final String errorTitle;
|
private final String errorTitle;
|
||||||
private final String errorMsg;
|
private final String errorMsg;
|
||||||
|
|
||||||
private final VersionCheckSystem versionCheckSystem;
|
private final VersionCheckSystem versionCheckSystem;
|
||||||
|
|
||||||
public ErrorMessagePage(
|
public ErrorMessagePage(
|
||||||
String template, String errorTitle, String errorMsg,
|
String template, Icon icon, String errorTitle, String errorMsg,
|
||||||
VersionCheckSystem versionCheckSystem
|
VersionCheckSystem versionCheckSystem
|
||||||
) {
|
) {
|
||||||
this.template = template;
|
this.template = template;
|
||||||
|
this.icon = icon;
|
||||||
this.errorTitle = errorTitle;
|
this.errorTitle = errorTitle;
|
||||||
this.errorMsg = errorMsg;
|
this.errorMsg = errorMsg;
|
||||||
this.versionCheckSystem = versionCheckSystem;
|
this.versionCheckSystem = versionCheckSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ErrorMessagePage(
|
||||||
|
String template, String errorTitle, String errorMsg,
|
||||||
|
VersionCheckSystem versionCheckSystem
|
||||||
|
) {
|
||||||
|
this(template, Icon.called("exclamation-circle").build(), errorTitle, errorMsg, versionCheckSystem);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toHtml() {
|
public String toHtml() {
|
||||||
|
|
||||||
PlaceholderReplacer placeholders = new PlaceholderReplacer();
|
PlaceholderReplacer placeholders = new PlaceholderReplacer();
|
||||||
placeholders.put("title", Icon.called("exclamation-circle") + " " + errorTitle);
|
placeholders.put("title", icon.toHtml() + " " + errorTitle);
|
||||||
placeholders.put("titleText", errorTitle);
|
placeholders.put("titleText", errorTitle);
|
||||||
placeholders.put("paragraph", errorMsg);
|
placeholders.put("paragraph", errorMsg);
|
||||||
placeholders.put("version", versionCheckSystem.getUpdateButton().orElse(versionCheckSystem.getCurrentVersionButton()));
|
placeholders.put("version", versionCheckSystem.getUpdateButton().orElse(versionCheckSystem.getCurrentVersionButton()));
|
||||||
|
@ -18,6 +18,7 @@ package com.djrapitops.plan.delivery.rendering.pages;
|
|||||||
|
|
||||||
import com.djrapitops.plan.delivery.domain.container.PlayerContainer;
|
import com.djrapitops.plan.delivery.domain.container.PlayerContainer;
|
||||||
import com.djrapitops.plan.delivery.formatting.Formatters;
|
import com.djrapitops.plan.delivery.formatting.Formatters;
|
||||||
|
import com.djrapitops.plan.delivery.rendering.html.icon.Icon;
|
||||||
import com.djrapitops.plan.exceptions.connection.NotFoundException;
|
import com.djrapitops.plan.exceptions.connection.NotFoundException;
|
||||||
import com.djrapitops.plan.extension.implementation.results.ExtensionData;
|
import com.djrapitops.plan.extension.implementation.results.ExtensionData;
|
||||||
import com.djrapitops.plan.extension.implementation.storage.queries.ExtensionPlayerDataQuery;
|
import com.djrapitops.plan.extension.implementation.storage.queries.ExtensionPlayerDataQuery;
|
||||||
@ -182,6 +183,12 @@ public class PageFactory {
|
|||||||
versionCheckSystem.get());
|
versionCheckSystem.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Page errorPage(Icon icon, String title, String error) throws IOException {
|
||||||
|
return new ErrorMessagePage(
|
||||||
|
getResource("web/error.html"), icon, title, error,
|
||||||
|
versionCheckSystem.get());
|
||||||
|
}
|
||||||
|
|
||||||
public String getResource(String name) throws IOException {
|
public String getResource(String name) throws IOException {
|
||||||
return files.get().getCustomizableResourceOrDefault(name).asString();
|
return files.get().getCustomizableResourceOrDefault(name).asString();
|
||||||
}
|
}
|
||||||
|
@ -16,12 +16,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.djrapitops.plan.delivery.webserver;
|
package com.djrapitops.plan.delivery.webserver;
|
||||||
|
|
||||||
|
import com.djrapitops.plan.delivery.web.resolver.Response;
|
||||||
import com.djrapitops.plan.delivery.webserver.auth.Authentication;
|
import com.djrapitops.plan.delivery.webserver.auth.Authentication;
|
||||||
import com.djrapitops.plan.delivery.webserver.auth.BasicAuthentication;
|
import com.djrapitops.plan.delivery.webserver.auth.BasicAuthentication;
|
||||||
import com.djrapitops.plan.delivery.webserver.response.PromptAuthorizationResponse;
|
|
||||||
import com.djrapitops.plan.delivery.webserver.response.ResponseFactory;
|
import com.djrapitops.plan.delivery.webserver.response.ResponseFactory;
|
||||||
import com.djrapitops.plan.delivery.webserver.response.Response_old;
|
|
||||||
import com.djrapitops.plan.delivery.webserver.response.errors.ForbiddenResponse;
|
|
||||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||||
import com.djrapitops.plan.settings.config.paths.PluginSettings;
|
import com.djrapitops.plan.settings.config.paths.PluginSettings;
|
||||||
import com.djrapitops.plan.settings.config.paths.WebserverSettings;
|
import com.djrapitops.plan.settings.config.paths.WebserverSettings;
|
||||||
@ -90,30 +88,30 @@ public class RequestHandler implements HttpHandler {
|
|||||||
@Override
|
@Override
|
||||||
public void handle(HttpExchange exchange) {
|
public void handle(HttpExchange exchange) {
|
||||||
Headers requestHeaders = exchange.getRequestHeaders();
|
Headers requestHeaders = exchange.getRequestHeaders();
|
||||||
Headers responseHeaders = exchange.getResponseHeaders();
|
|
||||||
|
|
||||||
RequestInternal request = new RequestInternal(exchange, locale);
|
RequestInternal request = new RequestInternal(exchange, locale);
|
||||||
request.setAuth(getAuthorization(requestHeaders));
|
request.setAuth(getAuthorization(requestHeaders));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Response_old response = shouldPreventRequest(request.getRemoteAddress()) // Forbidden response (Optional)
|
Response response = shouldPreventRequest(request.getRemoteAddress()) // Forbidden response (Optional)
|
||||||
.orElseGet(() -> responseResolver.getResponse(request)); // Or the actual requested response
|
.orElseGet(() -> responseResolver.getResponse(request)); // Or the actual requested response
|
||||||
|
|
||||||
// Increase attempt count and block if too high
|
// Increase attempt count and block if too high
|
||||||
Optional<Response_old> forbid = handlePasswordBruteForceAttempts(request, response);
|
Optional<Response> forbid = handlePasswordBruteForceAttempts(request, response);
|
||||||
if (forbid.isPresent()) {
|
if (forbid.isPresent()) {
|
||||||
response = forbid.get();
|
response = forbid.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Authentication failed, but was not blocked
|
// Authentication failed, but was not blocked
|
||||||
if (response instanceof PromptAuthorizationResponse) {
|
// if (response.getCode() == 401) {
|
||||||
responseHeaders.set("WWW-Authenticate", response.getHeader("WWW-Authenticate").orElse("Basic realm=\"Plan WebUser (/plan register)\""));
|
//// responseHeaders.set("WWW-Authenticate", Optional.ofNullable(response.getHeaders().get("WWW-Authenticate")).orElse("Basic realm=\"Plan WebUser (/plan register)\""));
|
||||||
}
|
//// }
|
||||||
|
|
||||||
responseHeaders.set("Access-Control-Allow-Origin", config.get(WebserverSettings.CORS_ALLOW_ORIGIN));
|
response.getHeaders().putIfAbsent("Access-Control-Allow-Origin", config.get(WebserverSettings.CORS_ALLOW_ORIGIN));
|
||||||
responseHeaders.set("Access-Control-Allow-Methods", "GET, OPTIONS");
|
response.getHeaders().putIfAbsent("Access-Control-Allow-Methods", "GET, OPTIONS");
|
||||||
response.setResponseHeaders(responseHeaders);
|
|
||||||
response.send(exchange, locale, theme);
|
ResponseSender sender = new ResponseSender(exchange, response);
|
||||||
|
sender.send();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (config.isTrue(PluginSettings.DEV_MODE)) {
|
if (config.isTrue(PluginSettings.DEV_MODE)) {
|
||||||
logger.warn("THIS ERROR IS ONLY LOGGED IN DEV MODE:");
|
logger.warn("THIS ERROR IS ONLY LOGGED IN DEV MODE:");
|
||||||
@ -124,7 +122,7 @@ public class RequestHandler implements HttpHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<Response_old> shouldPreventRequest(String accessor) {
|
private Optional<Response> shouldPreventRequest(String accessor) {
|
||||||
Integer attempts = failedLoginAttempts.getIfPresent(accessor);
|
Integer attempts = failedLoginAttempts.getIfPresent(accessor);
|
||||||
if (attempts == null) {
|
if (attempts == null) {
|
||||||
attempts = 0;
|
attempts = 0;
|
||||||
@ -137,8 +135,8 @@ public class RequestHandler implements HttpHandler {
|
|||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<Response_old> handlePasswordBruteForceAttempts(RequestInternal request, Response_old response) {
|
private Optional<Response> handlePasswordBruteForceAttempts(RequestInternal request, Response response) {
|
||||||
if (request.getAuth().isPresent() && response instanceof PromptAuthorizationResponse) {
|
if (request.getAuth().isPresent() && response.getCode() == 401) {
|
||||||
// Authentication was attempted, but failed so new attempt is going to be given if not forbidden
|
// Authentication was attempted, but failed so new attempt is going to be given if not forbidden
|
||||||
|
|
||||||
failedLoginAttempts.cleanUp();
|
failedLoginAttempts.cleanUp();
|
||||||
@ -158,7 +156,7 @@ public class RequestHandler implements HttpHandler {
|
|||||||
// Attempts only increased if less than 5 attempts to prevent frustration from the cache value not
|
// Attempts only increased if less than 5 attempts to prevent frustration from the cache value not
|
||||||
// getting removed.
|
// getting removed.
|
||||||
failedLoginAttempts.put(accessor, attempts + 1);
|
failedLoginAttempts.put(accessor, attempts + 1);
|
||||||
} else if (!(response instanceof PromptAuthorizationResponse) && !(response instanceof ForbiddenResponse)) {
|
} else if (response.getCode() != 401 && response.getCode() != 403) {
|
||||||
// Successful login
|
// Successful login
|
||||||
failedLoginAttempts.invalidate(request.getRemoteAddress());
|
failedLoginAttempts.invalidate(request.getRemoteAddress());
|
||||||
}
|
}
|
||||||
@ -166,8 +164,8 @@ public class RequestHandler implements HttpHandler {
|
|||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<Response_old> createForbiddenResponse() {
|
private Optional<Response> createForbiddenResponse() {
|
||||||
return Optional.of(responseFactory.forbidden403_old("You have too many failed login attempts. Please wait 2 minutes until attempting again."));
|
return Optional.of(responseFactory.forbidden403("You have too many failed login attempts. Please wait 2 minutes until attempting again."));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Authentication getAuthorization(Headers requestHeaders) {
|
private Authentication getAuthorization(Headers requestHeaders) {
|
||||||
|
@ -41,6 +41,7 @@ import dagger.Lazy;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves All URLs.
|
* Resolves All URLs.
|
||||||
@ -57,6 +58,7 @@ public class ResponseResolver extends CompositePageResolver {
|
|||||||
private final PlayersPageResolver playersPageResolver;
|
private final PlayersPageResolver playersPageResolver;
|
||||||
private final PlayerPageResolver playerPageResolver;
|
private final PlayerPageResolver playerPageResolver;
|
||||||
private final ServerPageResolver serverPageResolver;
|
private final ServerPageResolver serverPageResolver;
|
||||||
|
private final RootPageResolver rootPageResolver;
|
||||||
private final RootJSONResolver rootJSONResolver;
|
private final RootJSONResolver rootJSONResolver;
|
||||||
private final ErrorHandler errorHandler;
|
private final ErrorHandler errorHandler;
|
||||||
|
|
||||||
@ -75,6 +77,7 @@ public class ResponseResolver extends CompositePageResolver {
|
|||||||
PlayersPageResolver playersPageResolver,
|
PlayersPageResolver playersPageResolver,
|
||||||
PlayerPageResolver playerPageResolver,
|
PlayerPageResolver playerPageResolver,
|
||||||
ServerPageResolver serverPageResolver,
|
ServerPageResolver serverPageResolver,
|
||||||
|
RootPageResolver rootPageResolver,
|
||||||
RootJSONResolver rootJSONResolver,
|
RootJSONResolver rootJSONResolver,
|
||||||
|
|
||||||
ErrorHandler errorHandler
|
ErrorHandler errorHandler
|
||||||
@ -87,6 +90,7 @@ public class ResponseResolver extends CompositePageResolver {
|
|||||||
this.playersPageResolver = playersPageResolver;
|
this.playersPageResolver = playersPageResolver;
|
||||||
this.playerPageResolver = playerPageResolver;
|
this.playerPageResolver = playerPageResolver;
|
||||||
this.serverPageResolver = serverPageResolver;
|
this.serverPageResolver = serverPageResolver;
|
||||||
|
this.rootPageResolver = rootPageResolver;
|
||||||
this.rootJSONResolver = rootJSONResolver;
|
this.rootJSONResolver = rootJSONResolver;
|
||||||
this.errorHandler = errorHandler;
|
this.errorHandler = errorHandler;
|
||||||
}
|
}
|
||||||
@ -99,9 +103,7 @@ public class ResponseResolver extends CompositePageResolver {
|
|||||||
resolverService.registerResolver(pluginName, "/favicon.ico", noAuthResolverFor(responseFactory.faviconResponse()));
|
resolverService.registerResolver(pluginName, "/favicon.ico", noAuthResolverFor(responseFactory.faviconResponse()));
|
||||||
resolverService.registerResolver(pluginName, "/network", serverPageResolver);
|
resolverService.registerResolver(pluginName, "/network", serverPageResolver);
|
||||||
resolverService.registerResolver(pluginName, "/server", serverPageResolver);
|
resolverService.registerResolver(pluginName, "/server", serverPageResolver);
|
||||||
|
resolverService.registerResolverForMatches(pluginName, Pattern.compile("^/$"), rootPageResolver);
|
||||||
// TODO Figure out how to deal with stuff like this
|
|
||||||
registerPage("", new RootPageResolver(responseFactory, webServer.get(), serverInfo));
|
|
||||||
|
|
||||||
registerPage("v1", rootJSONResolver);
|
registerPage("v1", rootJSONResolver);
|
||||||
}
|
}
|
||||||
@ -110,33 +112,33 @@ public class ResponseResolver extends CompositePageResolver {
|
|||||||
return (request) -> Optional.of(response);
|
return (request) -> Optional.of(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Response_old getResponse(RequestInternal request) {
|
public Response getResponse(RequestInternal request) {
|
||||||
try {
|
try {
|
||||||
return tryToGetResponse(request);
|
return tryToGetResponse(request);
|
||||||
} catch (NotFoundException e) {
|
} catch (NotFoundException e) {
|
||||||
return responseFactory.notFound404_old(e.getMessage());
|
return responseFactory.notFound404(e.getMessage());
|
||||||
} catch (WebUserAuthException e) {
|
} catch (WebUserAuthException e) {
|
||||||
return responseFactory.basicAuthFail_old(e);
|
return responseFactory.basicAuthFail(e);
|
||||||
} catch (ForbiddenException e) {
|
} catch (ForbiddenException e) {
|
||||||
return responseFactory.forbidden403_old(e.getMessage());
|
return responseFactory.forbidden403(e.getMessage());
|
||||||
} catch (BadRequestException e) {
|
} catch (BadRequestException e) {
|
||||||
return responseFactory.badRequest_old(e.getMessage(), request.getTargetString());
|
return responseFactory.badRequest(e.getMessage(), request.getTargetString());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
errorHandler.log(L.ERROR, this.getClass(), e);
|
errorHandler.log(L.ERROR, this.getClass(), e);
|
||||||
return responseFactory.internalErrorResponse_old(e, request.getTargetString());
|
return responseFactory.internalErrorResponse(e, request.getTargetString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Response_old tryToGetResponse(RequestInternal internalRequest) throws WebException {
|
private Response tryToGetResponse(RequestInternal internalRequest) throws WebException {
|
||||||
if ("OPTIONS" .equalsIgnoreCase(internalRequest.getRequestMethod())) {
|
if ("OPTIONS" .equalsIgnoreCase(internalRequest.getRequestMethod())) {
|
||||||
return new OptionsResponse();
|
return new OptionsResponse().toNewResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<Authentication> authentication = internalRequest.getAuth();
|
Optional<Authentication> authentication = internalRequest.getAuth();
|
||||||
|
|
||||||
Optional<Resolver> foundResolver = resolverService.getResolver(internalRequest.getPath().asString());
|
Optional<Resolver> foundResolver = resolverService.getResolver(internalRequest.getPath().asString());
|
||||||
// TODO Replace with 404 after refactoring
|
// TODO Replace with 404 after refactoring
|
||||||
if (!foundResolver.isPresent()) return tryToGetResponse_old(internalRequest);
|
if (!foundResolver.isPresent()) return tryToGetResponse_old(internalRequest).toNewResponse();
|
||||||
|
|
||||||
Resolver resolver = foundResolver.get();
|
Resolver resolver = foundResolver.get();
|
||||||
|
|
||||||
@ -146,19 +148,19 @@ public class ResponseResolver extends CompositePageResolver {
|
|||||||
boolean isAuthRequired = webServer.get().isAuthRequired();
|
boolean isAuthRequired = webServer.get().isAuthRequired();
|
||||||
if (isAuthRequired && !authentication.isPresent()) {
|
if (isAuthRequired && !authentication.isPresent()) {
|
||||||
if (webServer.get().isUsingHTTPS()) {
|
if (webServer.get().isUsingHTTPS()) {
|
||||||
return responseFactory.basicAuth_old();
|
return responseFactory.basicAuth();
|
||||||
} else {
|
} else {
|
||||||
return responseFactory.forbidden403_old();
|
return responseFactory.forbidden403();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isAuthRequired || resolver.canAccess(request)) {
|
if (!isAuthRequired || resolver.canAccess(request)) {
|
||||||
return resolver.resolve(request).map(Response_old::from).orElseGet(responseFactory::pageNotFound404_old);
|
return resolver.resolve(request).orElseGet(responseFactory::pageNotFound404);
|
||||||
} else {
|
} else {
|
||||||
return responseFactory.forbidden403_old();
|
return responseFactory.forbidden403();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return resolver.resolve(request).map(Response_old::from).orElseGet(responseFactory::pageNotFound404_old);
|
return resolver.resolve(request).orElseGet(responseFactory::pageNotFound404);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,10 +50,10 @@ public class ResponseSender {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setResponseHeaders() {
|
private void setResponseHeaders() {
|
||||||
Headers headers = exchange.getResponseHeaders();
|
Headers headers = exchange.getResponseHeaders();
|
||||||
for (Map.Entry<String, String> header : response.getHeaders().entrySet()) {
|
for (Map.Entry<String, String> header : response.getHeaders().entrySet()) {
|
||||||
headers.set(header.getKey(), header.getKey());
|
headers.set(header.getKey(), header.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,21 +16,19 @@
|
|||||||
*/
|
*/
|
||||||
package com.djrapitops.plan.delivery.webserver.pages;
|
package com.djrapitops.plan.delivery.webserver.pages;
|
||||||
|
|
||||||
import com.djrapitops.plan.delivery.domain.WebUser_old;
|
|
||||||
import com.djrapitops.plan.delivery.rendering.html.Html;
|
import com.djrapitops.plan.delivery.rendering.html.Html;
|
||||||
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.webserver.RequestInternal;
|
import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
|
||||||
import com.djrapitops.plan.delivery.webserver.RequestTarget;
|
|
||||||
import com.djrapitops.plan.delivery.webserver.WebServer;
|
import com.djrapitops.plan.delivery.webserver.WebServer;
|
||||||
import com.djrapitops.plan.delivery.webserver.auth.Authentication;
|
|
||||||
import com.djrapitops.plan.delivery.webserver.response.ResponseFactory;
|
import com.djrapitops.plan.delivery.webserver.response.ResponseFactory;
|
||||||
import com.djrapitops.plan.delivery.webserver.response.Response_old;
|
|
||||||
import com.djrapitops.plan.exceptions.connection.WebException;
|
|
||||||
import com.djrapitops.plan.identification.Server;
|
import com.djrapitops.plan.identification.Server;
|
||||||
import com.djrapitops.plan.identification.ServerInfo;
|
import com.djrapitops.plan.identification.ServerInfo;
|
||||||
|
import dagger.Lazy;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,13 +36,15 @@ import java.util.Optional;
|
|||||||
*
|
*
|
||||||
* @author Rsl1122
|
* @author Rsl1122
|
||||||
*/
|
*/
|
||||||
public class RootPageResolver implements PageResolver, NoAuthResolver {
|
@Singleton
|
||||||
|
public class RootPageResolver implements NoAuthResolver {
|
||||||
|
|
||||||
private final ResponseFactory responseFactory;
|
private final ResponseFactory responseFactory;
|
||||||
private final WebServer webServer;
|
private final Lazy<WebServer> webServer;
|
||||||
private final ServerInfo serverInfo;
|
private final ServerInfo serverInfo;
|
||||||
|
|
||||||
public RootPageResolver(ResponseFactory responseFactory, WebServer webServer, ServerInfo serverInfo) {
|
@Inject
|
||||||
|
public RootPageResolver(ResponseFactory responseFactory, Lazy<WebServer> webServer, ServerInfo serverInfo) {
|
||||||
this.responseFactory = responseFactory;
|
this.responseFactory = responseFactory;
|
||||||
this.webServer = webServer;
|
this.webServer = webServer;
|
||||||
this.serverInfo = serverInfo;
|
this.serverInfo = serverInfo;
|
||||||
@ -52,38 +52,31 @@ public class RootPageResolver implements PageResolver, NoAuthResolver {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Response> resolve(Request request) {
|
public Optional<Response> resolve(Request request) {
|
||||||
return Optional.empty();
|
return Optional.of(getResponse(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private Response getResponse(Request request) {
|
||||||
public Response_old resolve(RequestInternal request, RequestTarget target) throws WebException {
|
|
||||||
Server server = serverInfo.getServer();
|
Server server = serverInfo.getServer();
|
||||||
if (!webServer.isAuthRequired()) {
|
if (!webServer.get().isAuthRequired()) {
|
||||||
return responseFactory.redirectResponse_old(server.isProxy() ? "network" : "server/" + Html.encodeToURL(server.getIdentifiableName()));
|
String redirectTo = server.isProxy() ? "network" : "server/" + Html.encodeToURL(server.getIdentifiableName());
|
||||||
|
return responseFactory.redirectResponse(redirectTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<Authentication> auth = request.getAuth();
|
Optional<WebUser> webUser = request.getUser();
|
||||||
if (!auth.isPresent()) {
|
if (!webUser.isPresent()) {
|
||||||
return responseFactory.basicAuth_old();
|
return responseFactory.basicAuth();
|
||||||
}
|
}
|
||||||
|
|
||||||
WebUser_old webUser = auth.get().getWebUser();
|
WebUser user = webUser.get();
|
||||||
|
|
||||||
int permLevel = webUser.getPermLevel();
|
if (user.hasPermission("page.server")) {
|
||||||
switch (permLevel) {
|
return responseFactory.redirectResponse(server.isProxy() ? "network" : "server/" + Html.encodeToURL(server.getIdentifiableName()));
|
||||||
case 0:
|
} else if (user.hasPermission("page.players")) {
|
||||||
return responseFactory.redirectResponse_old(server.isProxy() ? "network" : "server/" + Html.encodeToURL(server.getIdentifiableName()));
|
return responseFactory.redirectResponse("players");
|
||||||
case 1:
|
} else if (user.hasPermission("page.player.self")) {
|
||||||
return responseFactory.redirectResponse_old("players");
|
return responseFactory.redirectResponse("player/" + Html.encodeToURL(user.getName()));
|
||||||
case 2:
|
} else {
|
||||||
return responseFactory.redirectResponse_old("player/" + Html.encodeToURL(webUser.getName()));
|
return responseFactory.forbidden403(user.getName() + " has insufficient permissions to be redirected to any page. Needs one of: 'page.server', 'page.players' or 'page.player.self'");
|
||||||
default:
|
|
||||||
return responseFactory.forbidden403_old();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAuthorized(Authentication auth, RequestTarget target) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,17 @@
|
|||||||
package com.djrapitops.plan.delivery.webserver.response;
|
package com.djrapitops.plan.delivery.webserver.response;
|
||||||
|
|
||||||
import com.djrapitops.plan.delivery.domain.container.PlayerContainer;
|
import com.djrapitops.plan.delivery.domain.container.PlayerContainer;
|
||||||
|
import com.djrapitops.plan.delivery.rendering.html.icon.Family;
|
||||||
|
import com.djrapitops.plan.delivery.rendering.html.icon.Icon;
|
||||||
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.web.resolver.MimeType;
|
import com.djrapitops.plan.delivery.web.resolver.MimeType;
|
||||||
import com.djrapitops.plan.delivery.web.resolver.Response;
|
import com.djrapitops.plan.delivery.web.resolver.Response;
|
||||||
import com.djrapitops.plan.delivery.webserver.response.errors.*;
|
import com.djrapitops.plan.delivery.webserver.auth.FailReason;
|
||||||
|
import com.djrapitops.plan.delivery.webserver.response.errors.ErrorResponse;
|
||||||
|
import com.djrapitops.plan.delivery.webserver.response.errors.ForbiddenResponse;
|
||||||
|
import com.djrapitops.plan.delivery.webserver.response.errors.InternalErrorResponse;
|
||||||
|
import com.djrapitops.plan.delivery.webserver.response.errors.NotFoundResponse;
|
||||||
import com.djrapitops.plan.delivery.webserver.response.pages.RawDataResponse;
|
import com.djrapitops.plan.delivery.webserver.response.pages.RawDataResponse;
|
||||||
import com.djrapitops.plan.exceptions.WebUserAuthException;
|
import com.djrapitops.plan.exceptions.WebUserAuthException;
|
||||||
import com.djrapitops.plan.exceptions.connection.NotFoundException;
|
import com.djrapitops.plan.exceptions.connection.NotFoundException;
|
||||||
@ -36,6 +42,8 @@ import com.djrapitops.plan.version.VersionCheckSystem;
|
|||||||
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.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -137,6 +145,10 @@ public class ResponseFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Response internalErrorResponse(Throwable e, String s) {
|
||||||
|
return forInternalError(e, s);
|
||||||
|
}
|
||||||
|
|
||||||
public Response networkPageResponse() {
|
public Response networkPageResponse() {
|
||||||
Optional<Response> error = checkDbClosedError();
|
Optional<Response> error = checkDbClosedError();
|
||||||
if (error.isPresent()) return error.get();
|
if (error.isPresent()) return error.get();
|
||||||
@ -205,17 +217,6 @@ public class ResponseFactory {
|
|||||||
return new ByteResponse(type, FileResponse.format(fileName), files);
|
return new ByteResponse(type, FileResponse.format(fileName), files);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Redirect somewhere
|
|
||||||
*
|
|
||||||
* @param location Starts with '/'
|
|
||||||
* @return Redirection response.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public Response_old redirectResponse_old(String location) {
|
|
||||||
return new RedirectResponse(location);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Response redirectResponse(String location) {
|
public Response redirectResponse(String location) {
|
||||||
return Response.builder().redirectTo(location).build();
|
return Response.builder().redirectTo(location).build();
|
||||||
}
|
}
|
||||||
@ -236,6 +237,10 @@ public class ResponseFactory {
|
|||||||
return notFound404_old(locale.getString(ErrorPageLang.UNKNOWN_PAGE_404));
|
return notFound404_old(locale.getString(ErrorPageLang.UNKNOWN_PAGE_404));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Response pageNotFound404() {
|
||||||
|
return notFound404(locale.getString(ErrorPageLang.UNKNOWN_PAGE_404));
|
||||||
|
}
|
||||||
|
|
||||||
public Response uuidNotFound404() {
|
public Response uuidNotFound404() {
|
||||||
return notFound404(locale.getString(ErrorPageLang.UUID_404));
|
return notFound404(locale.getString(ErrorPageLang.UUID_404));
|
||||||
}
|
}
|
||||||
@ -257,7 +262,7 @@ public class ResponseFactory {
|
|||||||
try {
|
try {
|
||||||
return Response.builder()
|
return Response.builder()
|
||||||
.setMimeType(MimeType.HTML)
|
.setMimeType(MimeType.HTML)
|
||||||
.setContent(pageFactory.errorPage("404 " + message, message).toHtml())
|
.setContent(pageFactory.errorPage(Icon.called("map-signs").build(), "404 " + message, message).toHtml())
|
||||||
.setStatus(404)
|
.setStatus(404)
|
||||||
.build();
|
.build();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -265,13 +270,47 @@ public class ResponseFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
public Response basicAuthFail(WebUserAuthException e) {
|
||||||
public ErrorResponse basicAuthFail_old(WebUserAuthException e) {
|
|
||||||
try {
|
try {
|
||||||
return PromptAuthorizationResponse.getBasicAuthResponse(e, versionCheckSystem, files);
|
FailReason failReason = e.getFailReason();
|
||||||
} catch (IOException jarReadFailed) {
|
String reason = failReason.getReason();
|
||||||
return internalErrorResponse_old(e, "Failed to generate PromptAuthorizationResponse");
|
if (failReason == FailReason.ERROR) {
|
||||||
|
StringBuilder errorBuilder = new StringBuilder("</p><pre>");
|
||||||
|
for (String line : getStackTrace(e.getCause())) {
|
||||||
|
errorBuilder.append(line);
|
||||||
}
|
}
|
||||||
|
errorBuilder.append("</pre>");
|
||||||
|
|
||||||
|
reason += errorBuilder.toString();
|
||||||
|
}
|
||||||
|
return Response.builder()
|
||||||
|
.setMimeType(MimeType.HTML)
|
||||||
|
.setContent(pageFactory.errorPage(Icon.called("lock").build(), "401 Unauthorized", "Authentication Failed.</p><p><b>Reason: " + reason + "</b></p><p>").toHtml())
|
||||||
|
.setStatus(401)
|
||||||
|
.setHeader("WWW-Authenticate", "Basic realm=\"" + failReason.getReason() + "\"")
|
||||||
|
.build();
|
||||||
|
} catch (IOException jarReadFailed) {
|
||||||
|
return forInternalError(e, "Failed to generate PromptAuthorizationResponse");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getStackTrace(Throwable throwable) {
|
||||||
|
List<String> stackTrace = new ArrayList<>();
|
||||||
|
stackTrace.add(throwable.toString());
|
||||||
|
for (StackTraceElement element : throwable.getStackTrace()) {
|
||||||
|
stackTrace.add(" " + element.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
Throwable cause = throwable.getCause();
|
||||||
|
if (cause != null) {
|
||||||
|
List<String> causeTrace = getStackTrace(cause);
|
||||||
|
if (!causeTrace.isEmpty()) {
|
||||||
|
causeTrace.set(0, "Caused by: " + causeTrace.get(0));
|
||||||
|
stackTrace.addAll(causeTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stackTrace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@ -289,7 +328,7 @@ public class ResponseFactory {
|
|||||||
try {
|
try {
|
||||||
return Response.builder()
|
return Response.builder()
|
||||||
.setMimeType(MimeType.HTML)
|
.setMimeType(MimeType.HTML)
|
||||||
.setContent(pageFactory.errorPage("403 Forbidden", message).toHtml())
|
.setContent(pageFactory.errorPage(Icon.called("hand-paper").of(Family.REGULAR).build(), "403 Forbidden", message).toHtml())
|
||||||
.setStatus(403)
|
.setStatus(403)
|
||||||
.build();
|
.build();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -315,9 +354,29 @@ public class ResponseFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
public Response basicAuth() {
|
||||||
public BadRequestResponse badRequest_old(String errorMessage, String target) {
|
try {
|
||||||
return new BadRequestResponse(errorMessage + " (when requesting '" + target + "')");
|
String tips = "<br>- Ensure you have registered a user with <b>/plan register</b><br>"
|
||||||
|
+ "- Check that the username and password are correct<br>"
|
||||||
|
+ "- Username and password are case-sensitive<br>"
|
||||||
|
+ "<br>If you have forgotten your password, ask a staff member to delete your old user and re-register.";
|
||||||
|
return Response.builder()
|
||||||
|
.setMimeType(MimeType.HTML)
|
||||||
|
.setContent(pageFactory.errorPage(Icon.called("lock").build(), "401 Unauthorized", "Authentication Failed." + tips).toHtml())
|
||||||
|
.setStatus(401)
|
||||||
|
.setHeader("WWW-Authenticate", "Basic realm=\"Plan WebUser (/plan register)\"")
|
||||||
|
.build();
|
||||||
|
} catch (IOException e) {
|
||||||
|
return forInternalError(e, "Failed to generate PromptAuthorizationResponse");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Response badRequest(String errorMessage, String target) {
|
||||||
|
return Response.builder()
|
||||||
|
.setMimeType(MimeType.HTML)
|
||||||
|
.setContent("400 Bad Request: " + errorMessage + " (when requesting '" + target + "')")
|
||||||
|
.setStatus(400)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Response playerPageResponse(UUID playerUUID) {
|
public Response playerPageResponse(UUID playerUUID) {
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.djrapitops.plan.delivery.webserver.response;
|
package com.djrapitops.plan.delivery.webserver.response;
|
||||||
|
|
||||||
|
import com.djrapitops.plan.delivery.web.resolver.Response;
|
||||||
import com.djrapitops.plan.settings.locale.Locale;
|
import com.djrapitops.plan.settings.locale.Locale;
|
||||||
import com.djrapitops.plan.settings.theme.Theme;
|
import com.djrapitops.plan.settings.theme.Theme;
|
||||||
import com.sun.net.httpserver.Headers;
|
import com.sun.net.httpserver.Headers;
|
||||||
@ -25,7 +26,6 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@ -96,20 +96,12 @@ public abstract class Response_old {
|
|||||||
return getHeader(null).map(h -> Integer.parseInt(StringUtils.split(h, ' ')[1])).orElse(500);
|
return getHeader(null).map(h -> Integer.parseInt(StringUtils.split(h, ' ')[1])).orElse(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
public Response toNewResponse() {
|
||||||
public static Response_old from(com.djrapitops.plan.delivery.web.resolver.Response apiResponse) {
|
return Response.builder()
|
||||||
Response_old response = new Response_old() {};
|
.setStatus(getCode())
|
||||||
response.setContent(apiResponse.getCharset().map(charset -> new String(apiResponse.getBytes(), charset))
|
.setMimeType(type)
|
||||||
.orElse(new String(apiResponse.getBytes())));
|
.setContent(content)
|
||||||
response.setHeader("HTTP/1.1 " + apiResponse.getCode() + " ");
|
.build();
|
||||||
for (Map.Entry<String, String> header : apiResponse.getHeaders().entrySet()) {
|
|
||||||
if (header.getKey().equals("Content-Type")) {
|
|
||||||
response.type = header.getValue();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
response.header += header.getKey() + ": " + header.getValue() + ";\r\n";
|
|
||||||
}
|
|
||||||
return response;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
Reference in New Issue
Block a user