Refactored /players page to use ResolverService

- Changed all css, js and png requests on player page to use relative address.
- Changed the export accordingly

Deprecated a lot of the old response factory methods
This commit is contained in:
Rsl1122 2020-02-14 10:43:47 +02:00 committed by Risto Lahtela
parent 2914966650
commit e997289a20
8 changed files with 183 additions and 129 deletions

View File

@ -131,48 +131,50 @@ public class PlayerPageExporter extends FileExporter {
private void exportRequiredResources(ExportPaths exportPaths, Path toDirectory) throws IOException {
// Style
exportResources(exportPaths, toDirectory,
"img/Flaticon_circle.png",
"css/sb-admin-2.css",
"css/style.css",
"vendor/jquery/jquery.min.js",
"vendor/bootstrap/js/bootstrap.bundle.min.js",
"vendor/jquery-easing/jquery.easing.min.js",
"vendor/datatables/jquery.dataTables.min.js",
"vendor/datatables/dataTables.bootstrap4.min.js",
"vendor/highcharts/highstock.js",
"vendor/highcharts/map.js",
"vendor/highcharts/world.js",
"vendor/highcharts/drilldown.js",
"vendor/highcharts/highcharts-more.js",
"vendor/highcharts/no-data-to-display.js",
"vendor/fullcalendar/fullcalendar.min.css",
"vendor/momentjs/moment.js",
"vendor/fullcalendar/fullcalendar.min.js",
"vendor/fontawesome-free/css/all.min.css",
"vendor/fontawesome-free/webfonts/fa-brands-400.eot",
"vendor/fontawesome-free/webfonts/fa-brands-400.ttf",
"vendor/fontawesome-free/webfonts/fa-brands-400.woff",
"vendor/fontawesome-free/webfonts/fa-brands-400.woff2",
"vendor/fontawesome-free/webfonts/fa-regular-400.eot",
"vendor/fontawesome-free/webfonts/fa-regular-400.ttf",
"vendor/fontawesome-free/webfonts/fa-regular-400.woff",
"vendor/fontawesome-free/webfonts/fa-regular-400.woff2",
"vendor/fontawesome-free/webfonts/fa-solid-900.eot",
"vendor/fontawesome-free/webfonts/fa-solid-900.ttf",
"vendor/fontawesome-free/webfonts/fa-solid-900.woff",
"vendor/fontawesome-free/webfonts/fa-solid-900.woff2",
"js/sb-admin-2.js",
"js/xmlhttprequests.js",
"js/color-selector.js",
"js/sessionAccordion.js",
"js/graphs.js",
"js/player-values.js"
"../img/Flaticon_circle.png",
"../css/sb-admin-2.css",
"../css/style.css",
"../vendor/jquery/jquery.min.js",
"../vendor/bootstrap/js/bootstrap.bundle.min.js",
"../vendor/jquery-easing/jquery.easing.min.js",
"../vendor/datatables/jquery.dataTables.min.js",
"../vendor/datatables/dataTables.bootstrap4.min.js",
"../vendor/highcharts/highstock.js",
"../vendor/highcharts/map.js",
"../vendor/highcharts/world.js",
"../vendor/highcharts/drilldown.js",
"../vendor/highcharts/highcharts-more.js",
"../vendor/highcharts/no-data-to-display.js",
"../vendor/fullcalendar/fullcalendar.min.css",
"../vendor/momentjs/moment.js",
"../vendor/fullcalendar/fullcalendar.min.js",
"../vendor/fontawesome-free/css/all.min.css",
"../vendor/fontawesome-free/webfonts/fa-brands-400.eot",
"../vendor/fontawesome-free/webfonts/fa-brands-400.ttf",
"../vendor/fontawesome-free/webfonts/fa-brands-400.woff",
"../vendor/fontawesome-free/webfonts/fa-brands-400.woff2",
"../vendor/fontawesome-free/webfonts/fa-regular-400.eot",
"../vendor/fontawesome-free/webfonts/fa-regular-400.ttf",
"../vendor/fontawesome-free/webfonts/fa-regular-400.woff",
"../vendor/fontawesome-free/webfonts/fa-regular-400.woff2",
"../vendor/fontawesome-free/webfonts/fa-solid-900.eot",
"../vendor/fontawesome-free/webfonts/fa-solid-900.ttf",
"../vendor/fontawesome-free/webfonts/fa-solid-900.woff",
"../vendor/fontawesome-free/webfonts/fa-solid-900.woff2",
"../js/sb-admin-2.js",
"../js/xmlhttprequests.js",
"../js/color-selector.js",
"../js/sessionAccordion.js",
"../js/graphs.js",
"../js/player-values.js"
);
}
private void exportResources(ExportPaths exportPaths, Path toDirectory, String... resourceNames) throws IOException {
for (String resourceName : resourceNames) {
exportResource(exportPaths, toDirectory, resourceName);
String nonRelativePath = toNonRelativePath(resourceName);
exportResource(exportPaths, toDirectory, nonRelativePath);
exportPaths.put(resourceName, toRelativePathFromRoot(nonRelativePath));
}
}
@ -187,8 +189,6 @@ public class PlayerPageExporter extends FileExporter {
} else {
export(to, resource);
}
exportPaths.put(resourceName, toRelativePathFromRoot(resourceName));
}
private String toRelativePathFromRoot(String resourceName) {

View File

@ -174,14 +174,10 @@ public class PageFactory {
}
}
public Page errorPage(String title, String error) {
try {
return new ErrorMessagePage(
getResource("web/error.html"), title, error,
versionCheckSystem.get());
} catch (IOException noParse) {
return internalErrorPage("Failed to create error message page for error: '" + error + "'", noParse);
}
public Page errorPage(String title, String error) throws IOException {
return new ErrorMessagePage(
getResource("web/error.html"), title, error,
versionCheckSystem.get());
}
public String getResource(String name) throws IOException {

View File

@ -20,9 +20,7 @@ import com.djrapitops.plan.delivery.web.resolver.Resolver;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Optional;
import java.util.*;
import java.util.function.Predicate;
import java.util.regex.Pattern;
@ -34,8 +32,8 @@ import java.util.regex.Pattern;
@Singleton
public class ResolverSvc implements ResolverService {
private final Collection<Container> basicResolvers;
private final Collection<Container> regexResolvers;
private final List<Container> basicResolvers;
private final List<Container> regexResolvers;
@Inject
public ResolverSvc() {
@ -49,12 +47,14 @@ public class ResolverSvc implements ResolverService {
@Override
public void registerResolver(String pluginName, String start, Resolver resolver) {
basicResolvers.add(new Container(pluginName, checking -> checking.startsWith(start), resolver));
basicResolvers.add(new Container(pluginName, checking -> checking.startsWith(start), resolver, start));
Collections.sort(basicResolvers);
}
@Override
public void registerResolverForMatches(String pluginName, Pattern pattern, Resolver resolver) {
regexResolvers.add(new Container(pluginName, pattern.asPredicate(), resolver));
regexResolvers.add(new Container(pluginName, pattern.asPredicate(), resolver, pattern.pattern()));
Collections.sort(regexResolvers);
}
@Override
@ -78,15 +78,39 @@ public class ResolverSvc implements ResolverService {
return Optional.empty();
}
private static class Container {
private static class Container implements Comparable<Container> {
final String plugin;
final Predicate<String> matcher;
final Resolver resolver;
final String sortBy;
public Container(String plugin, Predicate<String> matcher, Resolver resolver) {
public Container(String plugin, Predicate<String> matcher, Resolver resolver, String sortBy) {
this.plugin = plugin;
this.matcher = matcher;
this.resolver = resolver;
this.sortBy = sortBy;
}
@Override
public int compareTo(Container o) {
// Longest first
return Integer.compare(o.sortBy.length(), this.sortBy.length());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Container)) return false;
Container container = (Container) o;
return Objects.equals(plugin, container.plugin) &&
Objects.equals(matcher, container.matcher) &&
Objects.equals(resolver, container.resolver) &&
Objects.equals(sortBy, container.sortBy);
}
@Override
public int hashCode() {
return Objects.hash(plugin, matcher, resolver, sortBy);
}
}
}

View File

@ -93,7 +93,7 @@ public class ResponseResolver extends CompositePageResolver {
public void registerPages() {
resolverService.registerResolver("Plan", "/debug", debugPageResolver);
resolverService.registerResolver("Plan", "/players", playersPageResolver);
registerPage("player", playerPageResolver);
resolverService.registerResolver("Plan", "/player", playerPageResolver);
registerPage("network", serverPageResolver);
registerPage("server", serverPageResolver);

View File

@ -16,21 +16,13 @@
*/
package com.djrapitops.plan.delivery.webserver.pages;
import com.djrapitops.plan.delivery.domain.WebUser_old;
import com.djrapitops.plan.delivery.webserver.Request;
import com.djrapitops.plan.delivery.webserver.RequestTarget;
import com.djrapitops.plan.delivery.webserver.auth.Authentication;
import com.djrapitops.plan.delivery.web.resolver.*;
import com.djrapitops.plan.delivery.webserver.response.ResponseFactory;
import com.djrapitops.plan.delivery.webserver.response.Response_old;
import com.djrapitops.plan.exceptions.WebUserAuthException;
import com.djrapitops.plan.exceptions.connection.ForbiddenException;
import com.djrapitops.plan.exceptions.connection.WebException;
import com.djrapitops.plan.identification.UUIDUtility;
import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.Database;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Optional;
import java.util.UUID;
/**
@ -39,50 +31,39 @@ import java.util.UUID;
* @author Rsl1122
*/
@Singleton
public class PlayerPageResolver implements PageResolver {
public class PlayerPageResolver implements Resolver {
private final ResponseFactory responseFactory;
private final DBSystem dbSystem;
private final UUIDUtility uuidUtility;
@Inject
public PlayerPageResolver(
ResponseFactory responseFactory,
DBSystem dbSystem,
UUIDUtility uuidUtility
) {
this.responseFactory = responseFactory;
this.dbSystem = dbSystem;
this.uuidUtility = uuidUtility;
}
@Override
public Response_old resolve(Request request, RequestTarget target) throws WebException {
if (target.isEmpty()) {
return responseFactory.pageNotFound404_old();
}
String playerName = target.get(0);
UUID playerUUID = uuidUtility.getUUIDOf(playerName);
boolean raw = target.size() >= 2 && target.get(1).equalsIgnoreCase("raw");
if (playerUUID == null) {
return responseFactory.uuidNotFound404_old();
}
Database.State dbState = dbSystem.getDatabase().getState();
if (dbState != Database.State.OPEN) {
throw new ForbiddenException("Database is " + dbState.name() + " - Please try again later. You can check database status with /plan info");
}
if (raw) {
return responseFactory.rawPlayerPageResponse_old(playerUUID);
}
return responseFactory.playerPageResponse_old(playerUUID);
public boolean canAccess(WebUser user, URIPath target, URIQuery query) {
boolean isOwnPage = target.getPart(1).map(user.getName()::equalsIgnoreCase).orElse(true);
return user.hasPermission("page.player.other") || (user.hasPermission("page.player.self") && isOwnPage);
}
@Override
public boolean isAuthorized(Authentication auth, RequestTarget target) throws WebUserAuthException {
WebUser_old webUser = auth.getWebUser();
return webUser.getPermLevel() <= 1 || webUser.getName().equalsIgnoreCase(target.get(target.size() - 1));
public Optional<Response> resolve(URIPath target, URIQuery query) {
Optional<String> part = target.getPart(1);
if (!part.isPresent()) return Optional.empty();
String playerName = part.get();
UUID playerUUID = uuidUtility.getUUIDOf(playerName);
if (playerUUID == null) return Optional.of(responseFactory.uuidNotFound404());
boolean raw = target.getPart(2).map("raw"::equalsIgnoreCase).orElse(false);
return Optional.of(
raw ? responseFactory.rawPlayerPageResponse(playerUUID)
: responseFactory.playerPageResponse(playerUUID)
);
}
}

View File

@ -16,6 +16,7 @@
*/
package com.djrapitops.plan.delivery.webserver.response;
import com.djrapitops.plan.delivery.domain.container.PlayerContainer;
import com.djrapitops.plan.delivery.rendering.pages.Page;
import com.djrapitops.plan.delivery.rendering.pages.PageFactory;
import com.djrapitops.plan.delivery.web.resolver.MimeType;
@ -77,15 +78,17 @@ public class ResponseFactory {
}
}
public Response forPage(Page page) throws IOException {
return Response.builder().setContent(page.toHtml())
private Response forPage(Page page) {
return Response.builder()
.setMimeType(MimeType.HTML)
.setContent(page.toHtml())
.build();
}
public Response forInternalError(String cause, Throwable error) {
return Response.builder().setContent(pageFactory.internalErrorPage(cause, error).toHtml())
private Response forInternalError(String cause, Throwable error) {
return Response.builder()
.setMimeType(MimeType.HTML)
.setContent(pageFactory.internalErrorPage(cause, error).toHtml())
.setStatus(500)
.build();
}
@ -103,16 +106,26 @@ public class ResponseFactory {
private Optional<Response> checkIfDBIsOpen() {
Database.State dbState = dbSystem.getDatabase().getState();
if (dbState != Database.State.OPEN) {
return Optional.of(Response.builder().setContent(pageFactory.errorPage(
"503 Resources Unavailable",
"Database is " + dbState.name() + " - Please try again later. You can check database status with /plan info"
).toHtml()).setMimeType(MimeType.HTML)
.setStatus(503)
.build());
try {
return Optional.of(buildDBNotOpenResponse(dbState));
} catch (IOException e) {
return Optional.of(forInternalError("Database was not open, additionally failed to generate error page for that", e));
}
}
return Optional.empty();
}
private Response buildDBNotOpenResponse(Database.State dbState) throws IOException {
return Response.builder()
.setMimeType(MimeType.HTML)
.setContent(pageFactory.errorPage(
"503 Resources Unavailable",
"Database is " + dbState.name() + " - Please try again later. You can check database status with /plan info"
).toHtml())
.setStatus(503)
.build();
}
@Deprecated
public ErrorResponse internalErrorResponse_old(Throwable e, String s) {
try {
@ -149,6 +162,14 @@ public class ResponseFactory {
return new RawPlayerDataResponse(dbSystem.getDatabase().query(ContainerFetchQueries.fetchPlayerContainer(uuid)));
}
public Response rawPlayerPageResponse(UUID playerUUID) {
PlayerContainer player = dbSystem.getDatabase().query(ContainerFetchQueries.fetchPlayerContainer(playerUUID));
return Response.builder()
.setMimeType(MimeType.JSON)
.setJSONContent(RawDataResponse.mapToNormalMap(player))
.build();
}
@Deprecated
public Response_old javaScriptResponse_old(String fileName) {
try {
@ -213,11 +234,19 @@ public class ResponseFactory {
return notFound404_old(locale.getString(ErrorPageLang.UUID_404));
}
public Response uuidNotFound404() {
return notFound404(locale.getString(ErrorPageLang.UUID_404));
}
@Deprecated
public ErrorResponse playerNotFound404_old() {
return notFound404_old(locale.getString(ErrorPageLang.NOT_PLAYED_404));
}
public Response playerNotFound404() {
return notFound404(locale.getString(ErrorPageLang.NOT_PLAYED_404));
}
@Deprecated
public ErrorResponse notFound404_old(String message) {
try {
@ -227,6 +256,19 @@ public class ResponseFactory {
}
}
public Response notFound404(String message) {
try {
return Response.builder()
.setMimeType(MimeType.HTML)
.setContent(pageFactory.errorPage("404 " + message, message).toHtml())
.setStatus(404)
.build();
} catch (IOException e) {
return forInternalError("Failed to generate 404 page with message '" + message + "'", e);
}
}
@Deprecated
public ErrorResponse basicAuthFail_old(WebUserAuthException e) {
try {
@ -265,6 +307,16 @@ public class ResponseFactory {
return new BadRequestResponse(errorMessage + " (when requesting '" + target + "')");
}
public Response playerPageResponse(UUID playerUUID) {
try {
return forPage(pageFactory.playerPage(playerUUID));
} catch (IllegalStateException e) {
return playerNotFound404();
} catch (IOException e) {
return forInternalError("Failed to generate player page", e);
}
}
@Deprecated
public Response_old playerPageResponse_old(UUID playerUUID) {
try {

View File

@ -38,7 +38,7 @@ public class RawDataResponse extends JSONResponse {
super(mapToNormalMap(dataContainer));
}
private static Map<String, Object> mapToNormalMap(DataContainer player) {
public static Map<String, Object> mapToNormalMap(DataContainer player) {
Map<String, Object> values = new HashMap<>();
player.getMap().forEach((key, value) ->
{

View File

@ -13,14 +13,14 @@
<title>Plan | ${playerName}</title>
<!-- Custom fonts for this template-->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet">
<link href="../vendor/fontawesome-free/css/all.min.css" rel="stylesheet">
<link crossorigin="anonymous"
href="https://fonts.googleapis.com/css?family=Nunito:400,700,800,900&display=swap&subset=latin-ext"
rel="stylesheet">
<!-- Custom styles for this template-->
<link href="css/sb-admin-2.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<link href="../css/sb-admin-2.css" rel="stylesheet">
<link href="../css/style.css" rel="stylesheet">
</head>
@ -41,7 +41,7 @@
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center">
<img class="w-22" src="img/Flaticon_circle.png">
<img class="w-22" src="../img/Flaticon_circle.png">
</a>
<!-- Divider -->
@ -699,36 +699,37 @@
</a>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="../vendor/jquery/jquery.min.js"></script>
<script src="../vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<script src="../vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Page level plugins -->
<script src="vendor/datatables/jquery.dataTables.min.js"></script>
<script src="vendor/datatables/dataTables.bootstrap4.min.js"></script>
<script src="vendor/highcharts/highstock.js"></script>
<script src="vendor/highcharts/drilldown.js"></script>
<script src="vendor/highcharts/highcharts-more.js"></script>
<script src="vendor/highcharts/no-data-to-display.js"></script>
<link href='vendor/fullcalendar/fullcalendar.min.css' rel='stylesheet'/>
<script src='vendor/momentjs/moment.js'></script>
<script src='vendor/fullcalendar/fullcalendar.min.js'></script>
<script src="../vendor/datatables/jquery.dataTables.min.js"></script>
<script src="../vendor/datatables/dataTables.bootstrap4.min.js"></script>
<script src="../vendor/highcharts/highstock.js"></script>
<script src="../vendor/highcharts/drilldown.js"></script>
<script src="../vendor/highcharts/highcharts-more.js"></script>
<script src="../vendor/highcharts/no-data-to-display.js"></script>
<link href='../vendor/fullcalendar/fullcalendar.min.css' rel='stylesheet'/>
<script src='../vendor/momentjs/moment.js'></script>
<script src='../vendor/fullcalendar/fullcalendar.min.js'></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.js"></script>
<script src="js/xmlhttprequests.js"></script>
<script src="js/color-selector.js"></script>
<script src="../js/sb-admin-2.js"></script>
<script src="../js/xmlhttprequests.js"></script>
<script src="../js/color-selector.js"></script>
<!-- Page level custom scripts -->
<script src="js/sessionAccordion.js"></script>
<script src="js/graphs.js"></script>
<script src="js/player-values.js"></script>
<script src="../js/sessionAccordion.js"></script>
<script src="../js/graphs.js"></script>
<script src="../js/player-values.js"></script>
<script>
try {
Highcharts.setOptions({lang: {noData: "No Data to Display"}, time: {timezoneOffset: ${timeZone} * 60}
Highcharts.setOptions({
lang: {noData: "No Data to Display"}, time: {timezoneOffset: ${timeZone} * 60}
});
setLoadingText('Loading player values..');
jsonRequest("../v1/player?player=${playerName}", function (json, error) {