Export noauth.css to hide logout button

- Added test for exported pages that uses Selenium to check for js errors
This commit is contained in:
Aurora Lahtela 2022-02-27 15:40:35 +02:00
parent 8175e599ec
commit 22ebdab821
16 changed files with 530 additions and 68 deletions

View File

@ -86,6 +86,8 @@ subprojects {
bstatsVersion = "2.2.1"
placeholderapiVersion = "2.11.1"
nkPlaceholderapiVersion = "1.4-SNAPSHOT"
testContainersVersion = "1.16.3"
}
repositories {

View File

@ -50,6 +50,10 @@ dependencies {
testImplementation project(":api")
testImplementation "com.google.code.gson:gson:$gsonVersion"
testImplementation "org.testcontainers:testcontainers:$testContainersVersion"
testImplementation "org.testcontainers:junit-jupiter:$testContainersVersion"
testImplementation "org.testcontainers:nginx:$testContainersVersion"
}
import org.apache.tools.ant.filters.ReplaceTokens

View File

@ -30,14 +30,17 @@ import javax.inject.Singleton;
@Singleton
public class ExportSystem implements SubSystem {
private final Exporter exporter;
private final ExportScheduler exportScheduler;
private final RunnableFactory runnableFactory;
@Inject
public ExportSystem(
Exporter exporter,
ExportScheduler exportScheduler,
RunnableFactory runnableFactory
) {
this.exporter = exporter;
this.exportScheduler = exportScheduler;
this.runnableFactory = runnableFactory;
}
@ -51,4 +54,8 @@ public class ExportSystem implements SubSystem {
public void disable() {
// Nothing to disable
}
public Exporter getExporter() {
return exporter;
}
}

View File

@ -183,6 +183,7 @@ public class NetworkPageExporter extends FileExporter {
"./img/Flaticon_circle.png",
"./css/sb-admin-2.css",
"./css/style.css",
"./css/noauth.css",
"./vendor/datatables/datatables.min.js",
"./vendor/datatables/datatables.min.css",
"./vendor/highcharts/modules/map.js",

View File

@ -143,6 +143,7 @@ public class PlayerPageExporter extends FileExporter {
"../img/Flaticon_circle.png",
"../css/sb-admin-2.css",
"../css/style.css",
"../css/noauth.css",
"../vendor/datatables/datatables.min.js",
"../vendor/datatables/datatables.min.css",
"../vendor/highcharts/modules/map.js",

View File

@ -142,6 +142,7 @@ public class PlayersPageExporter extends FileExporter {
"img/Flaticon_circle.png",
"css/sb-admin-2.css",
"css/style.css",
"css/noauth.css",
"vendor/datatables/datatables.min.js",
"vendor/datatables/datatables.min.css",
"vendor/fontawesome-free/css/all.min.css",

View File

@ -0,0 +1,185 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.delivery.export;
import com.djrapitops.plan.PlanSystem;
import com.djrapitops.plan.gathering.domain.DataMap;
import com.djrapitops.plan.gathering.domain.FinishedSession;
import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.settings.config.PlanConfig;
import com.djrapitops.plan.settings.config.paths.ExportSettings;
import com.djrapitops.plan.settings.config.paths.ProxySettings;
import com.djrapitops.plan.settings.config.paths.WebserverSettings;
import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.Database;
import com.djrapitops.plan.storage.database.transactions.events.PlayerRegisterTransaction;
import com.djrapitops.plan.storage.database.transactions.events.SessionEndTransaction;
import com.djrapitops.plan.storage.database.transactions.events.WorldNameStoreTransaction;
import extension.SeleniumExtension;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.extension.ExtendWith;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.logging.LogEntry;
import org.openqa.selenium.logging.LogType;
import org.testcontainers.containers.NginxContainer;
import org.testcontainers.containers.wait.strategy.HttpWaitStrategy;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import utilities.RandomData;
import utilities.TestConstants;
import utilities.mocks.PluginMockComponent;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* This test class is for catching any JavaScript errors.
* <p>
* Errors may have been caused by:
* - Missing placeholders {@code ${placeholder}} inside {@code <script>} tags.
* - Automatic formatting of plugin javascript (See https://github.com/plan-player-analytics/Plan/issues/820)
* - Missing file definition in Mocker
*/
@Testcontainers(disabledWithoutDocker = true)
@ExtendWith(SeleniumExtension.class)
class ExportJSErrorRegressionTest {
public static PluginMockComponent component;
static Path tempDir;
static Path exportDirectory;
@Container
public static NginxContainer<?> nginx = new NginxContainer<>("nginx:latest")
.withCustomContent(exportDirectory.toFile().getAbsolutePath())
.waitingFor(new HttpWaitStrategy());
private static PlanSystem planSystem;
private static ServerUUID serverUUID;
static {
try {
tempDir = Files.createTempDirectory("export-test");
exportDirectory = tempDir.resolve("export");
Files.createDirectories(exportDirectory);
Files.write(exportDirectory.resolve("index.html"), new byte[1]);
} catch (IOException e) {
throw new AssertionError(e);
}
}
@BeforeAll
static void setUpClass() throws Exception {
component = new PluginMockComponent(tempDir);
planSystem = component.getPlanSystem();
PlanConfig config = planSystem.getConfigSystem().getConfig();
config.set(WebserverSettings.DISABLED, true);
config.set(ProxySettings.IP, "localhost");
config.set(ExportSettings.HTML_EXPORT_PATH, exportDirectory.toFile().getAbsolutePath());
config.set(ExportSettings.PLAYER_PAGES, true);
config.set(ExportSettings.SERVER_PAGE, true);
config.set(ExportSettings.PLAYERS_PAGE, true);
planSystem.enable();
serverUUID = planSystem.getServerInfo().getServerUUID();
savePlayerData();
Exporter exporter = planSystem.getExportSystem().getExporter();
exporter.exportServerPage(planSystem.getServerInfo().getServer());
exporter.exportPlayerPage(TestConstants.PLAYER_ONE_UUID, TestConstants.PLAYER_ONE_NAME);
exporter.exportPlayersPage();
System.out.println("Exported files: \n");
try (Stream<Path> walk = Files.walk(exportDirectory)) {
walk.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.map(File::getAbsolutePath)
.forEach(System.out::println);
}
System.out.println("Now running tests \n");
}
private static void savePlayerData() {
DBSystem dbSystem = planSystem.getDatabaseSystem();
Database database = dbSystem.getDatabase();
UUID uuid = TestConstants.PLAYER_ONE_UUID;
database.executeTransaction(new PlayerRegisterTransaction(uuid, RandomData::randomTime, TestConstants.PLAYER_ONE_NAME));
FinishedSession session = new FinishedSession(uuid, serverUUID, 1000L, 11000L, 500L, new DataMap());
database.executeTransaction(new WorldNameStoreTransaction(serverUUID, "world"));
database.executeTransaction(new SessionEndTransaction(session));
}
@AfterAll
static void tearDownClass() throws IOException {
if (planSystem != null) {
planSystem.disable();
}
try (Stream<Path> walk = Files.walk(tempDir)) {
walk.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.map(File::delete)
.forEach(Assertions::assertTrue);
}
Files.deleteIfExists(tempDir);
}
@AfterEach
void tearDownTest(WebDriver driver) {
SeleniumExtension.newTab(driver);
}
@TestFactory
Collection<DynamicTest> playerPageDoesNotHaveJavascriptErrors(ChromeDriver driver) {
String[] endpointsToTest = new String[]{
"/player/" + TestConstants.PLAYER_ONE_UUID_STRING + "/index.html",
// "/network/index.html",
"/server/index.html",
"/players/index.html"
};
return Arrays.stream(endpointsToTest).map(
endpoint -> DynamicTest.dynamicTest("Test exported endpoint " + endpoint, () -> {
String address = nginx.getBaseUrl("http", 80).toURI().resolve(endpoint).toString();
driver.get(address);
List<LogEntry> logs = new ArrayList<>();
logs.addAll(driver.manage().logs().get(LogType.CLIENT).getAll());
logs.addAll(driver.manage().logs().get(LogType.BROWSER).getAll());
assertNoLogs(logs);
})
).collect(Collectors.toList());
}
private void assertNoLogs(List<LogEntry> logs) {
List<String> loggedLines = logs.stream()
.map(log -> "\n" + log.getLevel().getName() + " " + log.getMessage())
.filter(line -> !line.contains("favicon.ico"))
.collect(Collectors.toList());
assertTrue(loggedLines.isEmpty(), () -> "Browser console included " + loggedLines.size() + " logs: " + loggedLines);
}
}

View File

@ -21,6 +21,7 @@ import com.djrapitops.plan.gathering.domain.DataMap;
import com.djrapitops.plan.gathering.domain.FinishedSession;
import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.settings.config.PlanConfig;
import com.djrapitops.plan.settings.config.paths.ProxySettings;
import com.djrapitops.plan.settings.config.paths.WebserverSettings;
import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.Database;
@ -31,18 +32,25 @@ import extension.SeleniumExtension;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.logging.LogEntry;
import org.openqa.selenium.logging.LogType;
import utilities.RandomData;
import utilities.TestConstants;
import utilities.mocks.PluginMockComponent;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* This test class is for catching any JavaScript errors.
@ -55,31 +63,32 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
@ExtendWith(SeleniumExtension.class)
class JSErrorRegressionTest {
private static final int TEST_PORT_NUMBER = RandomData.randomInt(9005, 9500);
private static final int TEST_PORT_NUMBER = 9091;
public static PluginMockComponent component;
private static PlanSystem bukkitSystem;
private static PlanSystem planSystem;
private static ServerUUID serverUUID;
@BeforeAll
static void setUpClass(@TempDir Path tempDir) throws Exception {
component = new PluginMockComponent(tempDir);
bukkitSystem = component.getPlanSystem();
planSystem = component.getPlanSystem();
PlanConfig config = bukkitSystem.getConfigSystem().getConfig();
PlanConfig config = planSystem.getConfigSystem().getConfig();
config.set(WebserverSettings.PORT, TEST_PORT_NUMBER);
config.set(ProxySettings.IP, "localhost:" + TEST_PORT_NUMBER);
bukkitSystem.enable();
serverUUID = bukkitSystem.getServerInfo().getServerUUID();
planSystem.enable();
serverUUID = planSystem.getServerInfo().getServerUUID();
savePlayerData();
}
private static void savePlayerData() {
DBSystem dbSystem = bukkitSystem.getDatabaseSystem();
DBSystem dbSystem = planSystem.getDatabaseSystem();
Database database = dbSystem.getDatabase();
UUID uuid = TestConstants.PLAYER_ONE_UUID;
database.executeTransaction(new PlayerRegisterTransaction(uuid, RandomData::randomTime, "name"));
database.executeTransaction(new PlayerRegisterTransaction(uuid, RandomData::randomTime, TestConstants.PLAYER_ONE_NAME));
FinishedSession session = new FinishedSession(uuid, serverUUID, 1000L, 11000L, 500L, new DataMap());
database.executeTransaction(new WorldNameStoreTransaction(serverUUID, "world"));
database.executeTransaction(new SessionEndTransaction(session));
@ -87,8 +96,8 @@ class JSErrorRegressionTest {
@AfterAll
static void tearDownClass() {
if (bukkitSystem != null) {
bukkitSystem.disable();
if (planSystem != null) {
planSystem.disable();
}
}
@ -97,42 +106,27 @@ class JSErrorRegressionTest {
SeleniumExtension.newTab(driver);
}
@Test
void playerPageDoesNotHaveJavascriptErrors(WebDriver driver) {
System.out.println("Testing Player Page");
driver.get("http://localhost:" + TEST_PORT_NUMBER + "/player/TestPlayer");
assertNo500Error(driver);
@ParameterizedTest
@CsvSource({
"http://localhost:" + TEST_PORT_NUMBER + "/player/" + TestConstants.PLAYER_ONE_NAME,
"http://localhost:" + TEST_PORT_NUMBER + "/player/" + TestConstants.PLAYER_ONE_UUID_STRING,
"http://localhost:" + TEST_PORT_NUMBER + "/network",
"http://localhost:" + TEST_PORT_NUMBER + "/server/Server 1",
"http://localhost:" + TEST_PORT_NUMBER + "/players"
})
void playerPageDoesNotHaveJavascriptErrors(String address, ChromeDriver driver) {
driver.get(address);
List<LogEntry> logs = new ArrayList<>();
logs.addAll(driver.manage().logs().get(LogType.CLIENT).getAll());
logs.addAll(driver.manage().logs().get(LogType.BROWSER).getAll());
assertNoLogs(logs);
}
private void assertNo500Error(WebDriver driver) {
assertFalse(driver.getPageSource().contains("<span class=\"loader-text\">Error occurred"), driver.getPageSource());
}
@Test
void playerPageAccessibleViaUUID(WebDriver driver) {
System.out.println("Testing Player Page via UUID");
driver.get("http://localhost:" + TEST_PORT_NUMBER + "/player/" + TestConstants.PLAYER_ONE_UUID);
assertNo500Error(driver);
}
@Test
void serverPageDoesNotHaveJavascriptErrors(WebDriver driver) {
System.out.println("Testing Server Page");
driver.get("http://localhost:" + TEST_PORT_NUMBER + "/server");
assertNo500Error(driver);
}
@Test
void playersPageDoesNotHaveJavascriptErrors(WebDriver driver) {
System.out.println("Testing Players Page");
driver.get("http://localhost:" + TEST_PORT_NUMBER + "/players");
assertNo500Error(driver);
}
@Test
void debugPageDoesNotHaveJavascriptErrors(WebDriver driver) {
System.out.println("Testing Debug Page");
driver.get("http://localhost:" + TEST_PORT_NUMBER + "/debug");
assertNo500Error(driver);
private void assertNoLogs(List<LogEntry> logs) {
assertTrue(logs.isEmpty(), () -> "Browser console included " + logs.size() + " logs: " + logs.stream()
.map(log -> "\n" + log.getLevel().getName() + " " + log.getMessage())
.collect(Collectors.toList()));
}
}

View File

@ -46,6 +46,7 @@ import java.nio.file.Path;
DatabaseTestComponent.DBTestModule.class,
PlanPluginModule.class,
PlanServerPluginModule.class,
PluginServerPropertiesModule.class,
PluginSuperClassBindingModule.class
})

View File

@ -25,10 +25,15 @@ import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.logging.LogType;
import org.openqa.selenium.logging.LoggingPreferences;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import utilities.CIProperties;
import java.io.File;
import java.util.ArrayList;
import java.util.logging.Level;
import static org.openqa.selenium.remote.CapabilityType.SUPPORTS_JAVASCRIPT;
@ -39,7 +44,7 @@ import static org.openqa.selenium.remote.CapabilityType.SUPPORTS_JAVASCRIPT;
*/
public class SeleniumExtension implements ParameterResolver, BeforeAllCallback, AfterAllCallback {
private WebDriver driver;
private ChromeDriver driver;
public static void newTab(WebDriver driver) {
WebElement body = driver.findElement(By.tagName("body"));
@ -48,12 +53,13 @@ public class SeleniumExtension implements ParameterResolver, BeforeAllCallback,
}
@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
return parameterContext.getParameter().getType().equals(WebDriver.class);
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
final Class<?> type = parameterContext.getParameter().getType();
return WebDriver.class.equals(type) || ChromeDriver.class.equals(type);
}
@Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return driver;
}
@ -67,17 +73,30 @@ public class SeleniumExtension implements ParameterResolver, BeforeAllCallback,
driver = getChromeWebDriver();
}
private WebDriver getChromeWebDriver() {
private ChromeDriver getChromeWebDriver() {
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setCapability(ChromeOptions.CAPABILITY, getDesiredCapabilities());
chromeOptions.setCapability(SUPPORTS_JAVASCRIPT, true);
// Using environment variable assumes linux
if (System.getenv(CIProperties.CHROME_DRIVER) != null) {
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setBinary("/usr/bin/google-chrome-stable");
chromeOptions.setHeadless(true);
chromeOptions.setCapability(SUPPORTS_JAVASCRIPT, true);
return new ChromeDriver(chromeOptions);
} else {
return new ChromeDriver();
}
return new ChromeDriver(chromeOptions);
}
private DesiredCapabilities getDesiredCapabilities() {
DesiredCapabilities caps = new DesiredCapabilities();
LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(LogType.PERFORMANCE, Level.INFO);
logPrefs.enable(LogType.PROFILER, Level.INFO);
logPrefs.enable(LogType.BROWSER, Level.INFO);
logPrefs.enable(LogType.CLIENT, Level.INFO);
logPrefs.enable(LogType.DRIVER, Level.INFO);
caps.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);
return caps;
}
private String getChromeDriverLocation() {

View File

@ -39,6 +39,7 @@ import java.nio.file.Path;
@Singleton
@Component(modules = {
PlanPluginModule.class,
PlanServerPluginModule.class,
TestSystemObjectProvidingModule.class,
PlatformAbstractionLayerModule.class,
FiltersModule.class,

View File

@ -18,10 +18,6 @@ package utilities.dagger;
import com.djrapitops.plan.delivery.webserver.cache.JSONFileStorage;
import com.djrapitops.plan.delivery.webserver.cache.JSONStorage;
import com.djrapitops.plan.identification.ServerInfo;
import com.djrapitops.plan.identification.ServerServerInfo;
import com.djrapitops.plan.settings.BukkitConfigSystem;
import com.djrapitops.plan.settings.ConfigSystem;
import dagger.Binds;
import dagger.Module;
@ -33,12 +29,6 @@ import dagger.Module;
@Module
public interface PlanPluginModule {
@Binds
ConfigSystem bindBukkitConfigSystem(BukkitConfigSystem bukkitConfigSystem);
@Binds
ServerInfo bindServerInfo(ServerServerInfo serverServerInfo);
@Binds
JSONStorage bindJSONStorage(JSONFileStorage jsonFileStorage);

View File

@ -0,0 +1,72 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package utilities.dagger;
import com.djrapitops.plan.PlanPlugin;
import com.djrapitops.plan.PlanSystem;
import com.djrapitops.plan.commands.PlanCommand;
import com.djrapitops.plan.modules.FiltersModule;
import com.djrapitops.plan.modules.PlaceholderModule;
import com.djrapitops.plan.modules.PlatformAbstractionLayerModule;
import com.djrapitops.plan.utilities.logging.PluginErrorLogger;
import dagger.BindsInstance;
import dagger.Component;
import net.playeranalytics.plugin.PlatformAbstractionLayer;
import javax.inject.Named;
import javax.inject.Singleton;
import java.nio.file.Path;
/**
* Dagger component for {@link PlanPlugin} based Plan system.
*
* @author AuroraLS3
*/
@Singleton
@Component(modules = {
PlanPluginModule.class,
PlanProxyPluginModule.class,
TestSystemObjectProvidingModule.class,
PlatformAbstractionLayerModule.class,
FiltersModule.class,
PlaceholderModule.class,
PluginServerPropertiesModule.class,
PluginSuperClassBindingModule.class,
DBSystemModule.class
})
public interface PlanProxyPluginComponent {
PlanCommand planCommand();
PlanSystem system();
PluginErrorLogger pluginErrorLogger();
@Component.Builder
interface Builder {
@BindsInstance
Builder bindTemporaryDirectory(@Named("tempDir") Path tempDir);
@BindsInstance
Builder plan(PlanPlugin plan);
@BindsInstance
Builder abstractionLayer(PlatformAbstractionLayer plan);
PlanProxyPluginComponent build();
}
}

View File

@ -0,0 +1,32 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package utilities.dagger;
import com.djrapitops.plan.identification.ServerInfo;
import com.djrapitops.plan.settings.BukkitConfigSystem;
import com.djrapitops.plan.settings.ConfigSystem;
import dagger.Binds;
import dagger.Module;
@Module
public interface PlanProxyPluginModule {
@Binds
ConfigSystem bindBukkitConfigSystem(BukkitConfigSystem bukkitConfigSystem);
@Binds
ServerInfo bindServerInfo(ProxyServerInfo proxyServerInfo);
}

View File

@ -0,0 +1,33 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package utilities.dagger;
import com.djrapitops.plan.identification.ServerInfo;
import com.djrapitops.plan.identification.ServerServerInfo;
import com.djrapitops.plan.settings.BukkitConfigSystem;
import com.djrapitops.plan.settings.ConfigSystem;
import dagger.Binds;
import dagger.Module;
@Module
public interface PlanServerPluginModule {
@Binds
ConfigSystem bindBukkitConfigSystem(BukkitConfigSystem bukkitConfigSystem);
@Binds
ServerInfo bindServerInfo(ServerServerInfo serverServerInfo);
}

View File

@ -0,0 +1,119 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package utilities.dagger;
import com.djrapitops.plan.delivery.webserver.Addresses;
import com.djrapitops.plan.exceptions.EnableException;
import com.djrapitops.plan.identification.Server;
import com.djrapitops.plan.identification.ServerInfo;
import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.identification.properties.ServerProperties;
import com.djrapitops.plan.identification.storage.ServerDBLoader;
import com.djrapitops.plan.identification.storage.ServerFileLoader;
import com.djrapitops.plan.identification.storage.ServerLoader;
import com.djrapitops.plan.processing.Processing;
import com.djrapitops.plan.settings.locale.Locale;
import com.djrapitops.plan.settings.locale.lang.PluginLang;
import net.playeranalytics.plugin.server.PluginLogger;
import javax.inject.Inject;
import javax.inject.Singleton;
/**
* Manages Server information on the Bungee instance.
*
* @author AuroraLS3
*/
@Singleton
public class ProxyServerInfo extends ServerInfo {
private final ServerLoader fromFile;
private final ServerLoader fromDatabase;
private final Processing processing;
private final Addresses addresses;
private final Locale locale;
private final PluginLogger logger;
@Inject
public ProxyServerInfo(
ServerProperties serverProperties,
ServerFileLoader fromFile,
ServerDBLoader fromDatabase,
Processing processing,
Addresses addresses,
Locale locale,
PluginLogger logger
) {
super(serverProperties);
this.fromFile = fromFile;
this.fromDatabase = fromDatabase;
this.processing = processing;
this.addresses = addresses;
this.locale = locale;
this.logger = logger;
}
@Override
public void loadServerInfo() {
logger.info(locale.getString(PluginLang.LOADING_SERVER_INFO));
checkIfDefaultIP();
this.server = fromFile.load(null).orElseGet(() -> fromDatabase.load(null)
.orElseGet(this::registerServer));
this.server.setProxy(true); // Ensure isProxy if loaded from file
processing.submitNonCritical(this::updateStorage);
}
private void updateStorage() {
String address = addresses.getAccessAddress().orElseGet(addresses::getFallbackLocalhostAddress);
server.setWebAddress(address);
fromDatabase.save(server);
server = fromDatabase.load(server.getUuid()).orElse(server);
fromFile.save(server);
}
private void checkIfDefaultIP() {
String ip = serverProperties.getIp();
if ("0.0.0.0".equals(ip)) {
logger.error("IP setting still 0.0.0.0 - Configure Alternative_IP/IP that connects to the Proxy server.");
logger.info("Player Analytics partially enabled (Use /planproxy reload to reload config)");
throw new EnableException("IP setting still 0.0.0.0 - Configure Alternative_IP/IP that connects to the Proxy server.");
}
}
private Server registerServer() {
Server proxy = createServerObject();
fromDatabase.save(proxy);
Server stored = fromDatabase.load(null)
.orElseThrow(() -> new EnableException("BungeeCord registration failed (DB)"));
fromFile.save(stored);
return stored;
}
private Server createServerObject() {
ServerUUID serverUUID = generateNewUUID();
String accessAddress = addresses.getAccessAddress().orElseThrow(() -> new EnableException("Velocity can not have '0.0.0.0' or '' as an address. Set up 'Server.IP' setting."));
return new Server(-1, serverUUID, "BungeeCord", accessAddress, true);
}
}