Skip to content

Commit 09279cb

Browse files
authored
React html customization / public_html folder (#2862)
* Add public_html folder, configuration and access methods to it * Make Frontend BETA static resource resolution prefer public_html * Add resolver for getting any file in public_html from webserver * Test customized bundle loading from public_html * Update gradle wrapper to 7.6 * Wrote scripts to React build or run dev server through gradle * Disable cyclomatic-complexity check on PublicHtmlResolver * Throw bad request exception on IllegalPathException * Throw bad request exception on bad chars in URI query
1 parent 413e087 commit 09279cb

File tree

29 files changed

+682
-279
lines changed

29 files changed

+682
-279
lines changed

Plan/api/src/main/java/com/djrapitops/plan/delivery/web/resolver/MimeType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public final class MimeType {
2020
public static final String HTML = "text/html";
2121
public static final String CSS = "text/css";
2222
public static final String JSON = "application/json";
23-
public static final String JS = "application/javascript";
23+
public static final String JS = "text/javascript";
2424
public static final String IMAGE = "image/gif";
2525
public static final String FAVICON = "image/x-icon";
2626
public static final String FONT_TTF = "application/x-font-ttf";

Plan/api/src/main/java/com/djrapitops/plan/delivery/web/resolver/request/URIQuery.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717
package com.djrapitops.plan.delivery.web.resolver.request;
1818

19+
import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException;
1920
import org.apache.commons.lang3.StringUtils;
2021

2122
import java.io.UnsupportedEncodingException;
@@ -82,6 +83,8 @@ private void parseAndPutKeyEmptyValue(Map<String, String> parameters, String s)
8283
);
8384
} catch (UnsupportedEncodingException e) {
8485
// If UTF-8 is unsupported, we have bigger problems
86+
} catch (IllegalArgumentException badCharacter) {
87+
throw new BadRequestException("URI Query contained bad character");
8588
}
8689
}
8790

Plan/common/build.gradle

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,14 @@ task yarnBundle(type: YarnTask) {
105105
args = ['run', 'build']
106106
}
107107

108+
task yarnStart(type: YarnTask) {
109+
logging.captureStandardOutput LogLevel.INFO
110+
inputs.file("$rootDir/react/dashboard/package.json")
111+
112+
dependsOn yarn_install
113+
args = ['run', 'start']
114+
}
115+
108116
task copyYarnBuildResults {
109117
inputs.files(fileTree("$rootDir/react/dashboard/build"))
110118
outputs.dir("$rootDir/common/build/resources/main/assets/plan/web")

Plan/common/src/main/java/com/djrapitops/plan/delivery/DeliveryUtilities.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import com.djrapitops.plan.delivery.formatting.Formatters;
2020
import com.djrapitops.plan.delivery.rendering.json.graphs.Graphs;
21+
import com.djrapitops.plan.storage.file.PublicHtmlFiles;
2122
import dagger.Lazy;
2223

2324
import javax.inject.Inject;
@@ -28,14 +29,16 @@ public class DeliveryUtilities {
2829

2930
private final Lazy<Formatters> formatters;
3031
private final Lazy<Graphs> graphs;
32+
private final Lazy<PublicHtmlFiles> publicHtmlFiles;
3133

3234
@Inject
3335
public DeliveryUtilities(
3436
Lazy<Formatters> formatters,
35-
Lazy<Graphs> graphs
36-
) {
37+
Lazy<Graphs> graphs,
38+
Lazy<PublicHtmlFiles> publicHtmlFiles) {
3739
this.formatters = formatters;
3840
this.graphs = graphs;
41+
this.publicHtmlFiles = publicHtmlFiles;
3942
}
4043

4144
public Formatters getFormatters() {
@@ -46,4 +49,7 @@ public Graphs getGraphs() {
4649
return graphs.get();
4750
}
4851

52+
public PublicHtmlFiles getPublicHtmlFiles() {
53+
return publicHtmlFiles.get();
54+
}
4955
}

Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/pages/PageFactory.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import com.djrapitops.plan.storage.database.queries.containers.ContainerFetchQueries;
4040
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
4141
import com.djrapitops.plan.storage.file.PlanFiles;
42+
import com.djrapitops.plan.storage.file.PublicHtmlFiles;
4243
import com.djrapitops.plan.utilities.dev.Untrusted;
4344
import com.djrapitops.plan.version.VersionChecker;
4445
import dagger.Lazy;
@@ -59,6 +60,7 @@ public class PageFactory {
5960

6061
private final Lazy<VersionChecker> versionChecker;
6162
private final Lazy<PlanFiles> files;
63+
private final Lazy<PublicHtmlFiles> publicHtmlFiles;
6264
private final Lazy<PlanConfig> config;
6365
private final Lazy<Theme> theme;
6466
private final Lazy<DBSystem> dbSystem;
@@ -73,7 +75,7 @@ public class PageFactory {
7375
public PageFactory(
7476
Lazy<VersionChecker> versionChecker,
7577
Lazy<PlanFiles> files,
76-
Lazy<PlanConfig> config,
78+
Lazy<PublicHtmlFiles> publicHtmlFiles, Lazy<PlanConfig> config,
7779
Lazy<Theme> theme,
7880
Lazy<DBSystem> dbSystem,
7981
Lazy<ServerInfo> serverInfo,
@@ -85,6 +87,7 @@ public PageFactory(
8587
) {
8688
this.versionChecker = versionChecker;
8789
this.files = files;
90+
this.publicHtmlFiles = publicHtmlFiles;
8891
this.config = config;
8992
this.theme = theme;
9093
this.dbSystem = dbSystem;
@@ -106,7 +109,8 @@ public Page playersPage() throws IOException {
106109
}
107110

108111
public Page reactPage() throws IOException {
109-
return new ReactPage(getBasePath(), getResource("index.html"));
112+
// TODO use ResourceService to apply snippets to the React index.html
113+
return new ReactPage(getBasePath(), getPublicHtmlOrJarResource("index.html"));
110114
}
111115

112116
private String getBasePath() {
@@ -244,16 +248,26 @@ public String getResourceAsString(String name) throws IOException {
244248
return getResource(name).asString();
245249
}
246250

247-
public WebResource getResource(String name) throws IOException {
251+
public WebResource getResource(String resourceName) throws IOException {
248252
try {
249-
return ResourceService.getInstance().getResource("Plan", name,
250-
() -> files.get().getResourceFromJar("web/" + name).asWebResource()
253+
return ResourceService.getInstance().getResource("Plan", resourceName,
254+
() -> files.get().getResourceFromJar("web/" + resourceName).asWebResource()
251255
);
252256
} catch (UncheckedIOException readFail) {
253257
throw readFail.getCause();
254258
}
255259
}
256260

261+
public WebResource getPublicHtmlOrJarResource(String resourceName) throws IOException {
262+
try {
263+
return publicHtmlFiles.get().findPublicHtmlResource(resourceName)
264+
.orElseGet(() -> files.get().getResourceFromJar("web/" + resourceName))
265+
.asWebResource();
266+
} catch (UncheckedIOException readFail) {
267+
throw readFail.getCause();
268+
}
269+
}
270+
257271
public Page loginPage() throws IOException {
258272
if (config.get().isTrue(PluginSettings.FRONTEND_BETA)) {
259273
return reactPage();

Plan/common/src/main/java/com/djrapitops/plan/delivery/web/ResolverSvc.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,17 @@
1717
package com.djrapitops.plan.delivery.web;
1818

1919
import com.djrapitops.plan.delivery.web.resolver.Resolver;
20+
import com.djrapitops.plan.settings.config.PlanConfig;
21+
import com.djrapitops.plan.settings.config.paths.PluginSettings;
2022
import com.djrapitops.plan.utilities.dev.Untrusted;
23+
import net.playeranalytics.plugin.server.PluginLogger;
2124

2225
import javax.inject.Inject;
2326
import javax.inject.Singleton;
2427
import java.util.*;
2528
import java.util.function.Predicate;
2629
import java.util.regex.Pattern;
30+
import java.util.stream.Collectors;
2731

2832
/**
2933
* ResolverService Implementation.
@@ -33,11 +37,16 @@
3337
@Singleton
3438
public class ResolverSvc implements ResolverService {
3539

40+
private final PlanConfig config;
41+
private final PluginLogger logger;
42+
3643
private final List<Container> basicResolvers;
3744
private final List<Container> regexResolvers;
3845

3946
@Inject
40-
public ResolverSvc() {
47+
public ResolverSvc(PlanConfig config, PluginLogger logger) {
48+
this.config = config;
49+
this.logger = logger;
4150
basicResolvers = new ArrayList<>();
4251
regexResolvers = new ArrayList<>();
4352
}
@@ -78,6 +87,12 @@ public List<Resolver> getResolvers(@Untrusted String target) {
7887
for (Container container : regexResolvers) {
7988
if (container.matcher.test(target)) resolvers.add(container.resolver);
8089
}
90+
if (config.isTrue(PluginSettings.DEV_MODE)) {
91+
logger.info("Match Resolvers " + target + " - " + resolvers.stream()
92+
.map(Object::getClass)
93+
.map(Class::getSimpleName)
94+
.collect(Collectors.toList()));
95+
}
8196
return resolvers;
8297
}
8398

Plan/common/src/main/java/com/djrapitops/plan/delivery/web/ResourceSvc.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import com.djrapitops.plan.settings.config.ResourceSettings;
2222
import com.djrapitops.plan.settings.locale.Locale;
2323
import com.djrapitops.plan.settings.locale.lang.PluginLang;
24-
import com.djrapitops.plan.storage.file.PlanFiles;
24+
import com.djrapitops.plan.storage.file.PublicHtmlFiles;
2525
import com.djrapitops.plan.storage.file.Resource;
2626
import com.djrapitops.plan.utilities.dev.Untrusted;
2727
import com.djrapitops.plan.utilities.logging.ErrorContext;
@@ -50,21 +50,21 @@
5050
public class ResourceSvc implements ResourceService {
5151

5252
public final Set<Snippet> snippets;
53-
private final PlanFiles files;
53+
private final PublicHtmlFiles publicHtmlFiles;
5454
private final ResourceSettings resourceSettings;
5555
private final Locale locale;
5656
private final PluginLogger logger;
5757
private final ErrorLogger errorLogger;
5858

5959
@Inject
6060
public ResourceSvc(
61-
PlanFiles files,
61+
PublicHtmlFiles publicHtmlFiles,
6262
PlanConfig config,
6363
Locale locale,
6464
PluginLogger logger,
6565
ErrorLogger errorLogger
6666
) {
67-
this.files = files;
67+
this.publicHtmlFiles = publicHtmlFiles;
6868
this.resourceSettings = config.getResourceSettings();
6969
this.locale = locale;
7070
this.logger = logger;
@@ -155,7 +155,7 @@ public WebResource getTheResource(String pluginName, @Untrusted String fileName,
155155
}
156156

157157
public WebResource getOrWriteCustomized(@Untrusted String fileName, Supplier<WebResource> source) throws IOException {
158-
Optional<Resource> customizedResource = files.getCustomizableResource(fileName);
158+
Optional<Resource> customizedResource = publicHtmlFiles.findCustomizedResource(fileName);
159159
if (customizedResource.isPresent()) {
160160
return readCustomized(customizedResource.get());
161161
} else {

Plan/common/src/main/java/com/djrapitops/plan/delivery/web/WebAssetVersionCheckTask.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,19 @@
2828
import javax.inject.Singleton;
2929
import java.io.File;
3030
import java.io.IOException;
31+
import java.nio.file.Path;
3132
import java.util.ArrayList;
3233
import java.util.List;
3334
import java.util.Optional;
3435
import java.util.concurrent.TimeUnit;
3536

3637
/**
3738
* Task in charge of checking html customized files on enable to see if they are outdated.
39+
*
40+
* @deprecated Html customization system will be overhauled for React version of frontend.
3841
*/
3942
@Singleton
43+
@Deprecated(forRemoval = true, since = "#2260") // TODO Remove after Frontend BETA
4044
public class WebAssetVersionCheckTask extends TaskSystem.Task {
4145

4246
private final PlanConfig config;
@@ -110,7 +114,8 @@ private void runTask() {
110114
}
111115

112116
private Optional<AssetInfo> findOutdatedResource(String resource) {
113-
Optional<File> resourceFile = files.attemptToFind(resource);
117+
Path dir = config.getResourceSettings().getCustomizationDirectory();
118+
Optional<File> resourceFile = files.attemptToFind(dir, resource);
114119
Optional<Long> webAssetVersion = assetVersions.getAssetVersion(resource);
115120
if (resourceFile.isPresent() && webAssetVersion.isPresent() && webAssetVersion.get() > resourceFile.get().lastModified()) {
116121
return Optional.of(new AssetInfo(

0 commit comments

Comments
 (0)