mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-01-06 15:44:49 +08:00
Merge branch 'master' into update-extensions
# Conflicts: # Plan/extensions/build.gradle
This commit is contained in:
commit
f64290c019
@ -13,6 +13,7 @@ buildscript {
|
||||
plugins {
|
||||
id "com.github.johnrengelman.shadow" version "7.1.2" apply false
|
||||
id "java"
|
||||
id 'java-library'
|
||||
id "jacoco"
|
||||
id "checkstyle"
|
||||
id "org.sonarqube" version "3.4.0.2513"
|
||||
@ -54,6 +55,7 @@ subprojects {
|
||||
// Build plugins
|
||||
apply plugin: "com.github.johnrengelman.shadow"
|
||||
apply plugin: "java"
|
||||
apply plugin: "java-library"
|
||||
apply plugin: "maven-publish"
|
||||
|
||||
// Report plugins
|
||||
@ -100,6 +102,7 @@ subprojects {
|
||||
junitVersion = "5.8.2"
|
||||
mockitoVersion = "4.6.1"
|
||||
testContainersVersion = "1.17.3"
|
||||
swaggerVersion = "2.2.1"
|
||||
}
|
||||
|
||||
repositories {
|
||||
@ -116,8 +119,9 @@ subprojects {
|
||||
|
||||
dependencies {
|
||||
// Dependency Injection used across the project
|
||||
implementation "com.google.dagger:dagger:$daggerVersion"
|
||||
shadow "com.google.dagger:dagger:$daggerVersion"
|
||||
annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
|
||||
testImplementation "com.google.dagger:dagger:$daggerVersion"
|
||||
testAnnotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
|
||||
|
||||
// Test Tooling Dependencies
|
||||
@ -133,7 +137,11 @@ subprojects {
|
||||
}
|
||||
|
||||
configurations {
|
||||
testArtifacts.extendsFrom testRuntimeOnly
|
||||
// Include shadowed dependencies in compile classpath of dependent modules
|
||||
api.extendsFrom shadow
|
||||
|
||||
testArtifacts.extendsFrom testRuntimeOnly // Test classes available to other modules
|
||||
testImplementation.extendsFrom shadow // Include shadowed dependencies in test classpath
|
||||
}
|
||||
// Test classes available to other modules
|
||||
task testJar(type: Jar) {
|
||||
|
@ -5,21 +5,23 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly project(":common")
|
||||
implementation project(path: ":common", configuration: 'shadow')
|
||||
compileOnly project(":api")
|
||||
implementation project(":api")
|
||||
implementation project(":common")
|
||||
|
||||
implementation "net.playeranalytics:platform-abstraction-layer-bukkit:$palVersion"
|
||||
implementation "org.bstats:bstats-bukkit:$bstatsVersion"
|
||||
shadow "net.playeranalytics:platform-abstraction-layer-api:$palVersion"
|
||||
shadow "net.playeranalytics:platform-abstraction-layer-bukkit:$palVersion"
|
||||
shadow "org.bstats:bstats-bukkit:$bstatsVersion"
|
||||
compileOnly "me.clip:placeholderapi:$placeholderapiVersion"
|
||||
|
||||
compileOnly "com.destroystokyo.paper:paper-api:$paperVersion"
|
||||
testImplementation "com.destroystokyo.paper:paper-api:$paperVersion"
|
||||
|
||||
testImplementation "com.destroystokyo.paper:paper-api:$paperVersion"
|
||||
testImplementation project(path: ":common", configuration: 'testArtifacts')
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
configurations = [project.configurations.shadow]
|
||||
|
||||
relocate 'org.bstats', 'net.playeranalytics.bstats.utilities.metrics'
|
||||
relocate 'org.slf4j', 'plan.org.slf4j'
|
||||
}
|
@ -1,20 +1,21 @@
|
||||
dependencies {
|
||||
compileOnly project(":common")
|
||||
implementation project(path: ":common", configuration: 'shadow')
|
||||
compileOnly project(":api")
|
||||
implementation project(":api")
|
||||
implementation project(":common")
|
||||
|
||||
implementation "net.playeranalytics:platform-abstraction-layer-bungeecord:$palVersion"
|
||||
implementation "org.bstats:bstats-bungeecord:$bstatsVersion"
|
||||
shadow "net.playeranalytics:platform-abstraction-layer-api:$palVersion"
|
||||
shadow "net.playeranalytics:platform-abstraction-layer-bungeecord:$palVersion"
|
||||
shadow "org.bstats:bstats-bungeecord:$bstatsVersion"
|
||||
|
||||
compileOnly "net.md-5:bungeecord-api:$bungeeVersion"
|
||||
compileOnly "com.imaginarycode.minecraft:RedisBungee:$redisBungeeVersion"
|
||||
|
||||
testImplementation "net.md-5:bungeecord-api:$bungeeVersion"
|
||||
testImplementation "com.imaginarycode.minecraft:RedisBungee:$redisBungeeVersion"
|
||||
|
||||
testImplementation project(path: ":common", configuration: 'testArtifacts')
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
configurations = [project.configurations.shadow]
|
||||
relocate 'org.bstats', 'net.playeranalytics.bstats.utilities.metrics'
|
||||
relocate 'org.slf4j', 'plan.org.slf4j'
|
||||
}
|
@ -4,13 +4,17 @@ import org.apache.tools.ant.filters.ReplaceTokens
|
||||
plugins {
|
||||
id "dev.vankka.dependencydownload.plugin" version "$dependencyDownloadVersion"
|
||||
id "com.github.node-gradle.node" version "3.4.0"
|
||||
id "io.swagger.core.v3.swagger-gradle-plugin" version "2.2.1"
|
||||
}
|
||||
|
||||
configurations {
|
||||
// Runtime downloading scopes
|
||||
mysqlDriver
|
||||
sqliteDriver
|
||||
testImplementation.extendsFrom mysqlDriver, sqliteDriver
|
||||
compileOnly.extendsFrom mysqlDriver, sqliteDriver
|
||||
compileOnly.extendsFrom mysqlDriver, sqliteDriver,
|
||||
|
||||
swaggerJson // swagger.json configuration
|
||||
}
|
||||
|
||||
task generateResourceForMySQLDriver(type: GenerateDependencyDownloadResourceTask) {
|
||||
@ -30,30 +34,35 @@ task generateResourceForSQLiteDriver(type: GenerateDependencyDownloadResourceTas
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "net.playeranalytics:platform-abstraction-layer-api:$palVersion"
|
||||
implementation project(":api")
|
||||
compileOnly project(":extensions")
|
||||
implementation project(path: ":extensions", configuration: 'shadow')
|
||||
implementation "org.apache.commons:commons-text:$commonsTextVersion"
|
||||
implementation "org.apache.commons:commons-compress:$commonsCompressVersion"
|
||||
implementation "commons-codec:commons-codec:$commonsCodecVersion"
|
||||
implementation "com.github.ben-manes.caffeine:caffeine:$caffeineVersion"
|
||||
implementation "com.zaxxer:HikariCP:$hikariVersion"
|
||||
implementation "org.slf4j:slf4j-nop:$slf4jVersion"
|
||||
implementation "org.slf4j:slf4j-api:$slf4jVersion"
|
||||
implementation "com.maxmind.geoip2:geoip2:$geoIpVersion"
|
||||
implementation "com.google.code.gson:gson:$gsonVersion"
|
||||
compileOnly "net.kyori:adventure-api:4.9.3"
|
||||
shadow project(":extensions")
|
||||
|
||||
implementation("dev.vankka:dependencydownload-runtime:$dependencyDownloadVersion") {
|
||||
shadow "net.playeranalytics:platform-abstraction-layer-api:$palVersion"
|
||||
compileOnly "net.kyori:adventure-api:4.9.3"
|
||||
shadow("dev.vankka:dependencydownload-runtime:$dependencyDownloadVersion") {
|
||||
// Effectively disables relocating
|
||||
exclude module: "jar-relocator"
|
||||
}
|
||||
mysqlDriver "mysql:mysql-connector-java:$mysqlVersion"
|
||||
sqliteDriver "org.xerial:sqlite-jdbc:$sqliteVersion"
|
||||
implementation "org.eclipse.jetty:jetty-server:$jettyVersion"
|
||||
implementation "org.eclipse.jetty:jetty-alpn-java-server:$jettyVersion"
|
||||
implementation "org.eclipse.jetty.http2:http2-server:$jettyVersion"
|
||||
|
||||
shadow "org.apache.commons:commons-text:$commonsTextVersion"
|
||||
shadow "org.apache.commons:commons-compress:$commonsCompressVersion"
|
||||
shadow "commons-codec:commons-codec:$commonsCodecVersion"
|
||||
shadow "com.github.ben-manes.caffeine:caffeine:$caffeineVersion"
|
||||
shadow "com.zaxxer:HikariCP:$hikariVersion"
|
||||
shadow "org.slf4j:slf4j-nop:$slf4jVersion"
|
||||
shadow "org.slf4j:slf4j-api:$slf4jVersion"
|
||||
shadow "com.maxmind.geoip2:geoip2:$geoIpVersion"
|
||||
shadow "com.google.code.gson:gson:$gsonVersion"
|
||||
shadow "org.eclipse.jetty:jetty-server:$jettyVersion"
|
||||
shadow "org.eclipse.jetty:jetty-alpn-java-server:$jettyVersion"
|
||||
shadow "org.eclipse.jetty.http2:http2-server:$jettyVersion"
|
||||
|
||||
// Swagger annotations
|
||||
implementation "jakarta.ws.rs:jakarta.ws.rs-api:3.1.0"
|
||||
implementation "io.swagger.core.v3:swagger-core-jakarta:$swaggerVersion"
|
||||
implementation "io.swagger.core.v3:swagger-jaxrs2-jakarta:$swaggerVersion"
|
||||
|
||||
testImplementation project(":api")
|
||||
testImplementation "com.google.code.gson:gson:$gsonVersion"
|
||||
@ -127,49 +136,40 @@ task determineWebAssetModifications {
|
||||
}
|
||||
}
|
||||
|
||||
resolve { // Swagger json generation task
|
||||
outputFileName = 'swagger'
|
||||
outputFormat = 'JSON'
|
||||
prettyPrint = 'TRUE'
|
||||
classpath = sourceSets.main.runtimeClasspath
|
||||
buildClasspath = classpath
|
||||
resourcePackages = [
|
||||
'com.djrapitops.plan.delivery.webserver',
|
||||
'com.djrapitops.plan.delivery.webserver.resolver.auth',
|
||||
'com.djrapitops.plan.delivery.webserver.resolver.json',
|
||||
]
|
||||
outputDir = file('build/generated-resources/swagger/assets/plan/web/')
|
||||
}
|
||||
task swaggerJsonJar(type: Jar) {
|
||||
dependsOn resolve
|
||||
archiveClassifier.set("resolve")
|
||||
from 'build/generated-resources/swagger'
|
||||
}
|
||||
artifacts {
|
||||
swaggerJson swaggerJsonJar
|
||||
}
|
||||
|
||||
processResources {
|
||||
dependsOn copyYarnBuildResults, determineWebAssetModifications, generateResourceForMySQLDriver, generateResourceForSQLiteDriver
|
||||
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
||||
dependsOn copyYarnBuildResults
|
||||
dependsOn determineWebAssetModifications
|
||||
dependsOn generateResourceForMySQLDriver
|
||||
dependsOn generateResourceForSQLiteDriver
|
||||
dependsOn updateVersion
|
||||
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
||||
from 'build/sources/resources'
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
dependsOn processResources
|
||||
configurations = [project.configurations.shadow]
|
||||
|
||||
// Exclude these files
|
||||
exclude "**/*.svg"
|
||||
exclude "**/*.psd"
|
||||
exclude "**/*.map"
|
||||
|
||||
exclude "**/module-info.class"
|
||||
exclude "module-info.class"
|
||||
exclude 'META-INF/versions/' // Causes Sponge to crash
|
||||
exclude 'org/apache/http/**/*' // Unnecessary http client depended on by geolite2 implementation
|
||||
exclude 'mozilla/**/*'
|
||||
|
||||
// Exclude unnecessary SQLite drivers
|
||||
exclude '**/Linux/android-arm/libsqlitejdbc.so'
|
||||
exclude '**/DragonFlyBSD/**/libsqlitejdbc.so'
|
||||
|
||||
relocate 'com.maxmind', 'plan.com.maxmind'
|
||||
relocate 'com.fasterxml', 'plan.com.fasterxml'
|
||||
relocate 'com.zaxxer', 'plan.com.zaxxer'
|
||||
relocate 'com.google.gson', 'plan.com.google.gson'
|
||||
relocate 'com.google.errorprone', 'plan.com.google.errorprone'
|
||||
relocate 'org.bstats', 'plan.org.bstats'
|
||||
relocate 'org.slf4j', 'plan.org.slf4j'
|
||||
|
||||
// Exclude test dependencies
|
||||
exclude "org/junit/**/*"
|
||||
exclude "org/opentest4j/**/*"
|
||||
exclude "org/checkerframework/**/*"
|
||||
exclude "org/apiguardian/**/*"
|
||||
exclude "org/mockito/**/*"
|
||||
exclude "org/selenium/**/*"
|
||||
exclude "org/jayway/**/*"
|
||||
exclude "google/protobuf/**/*"
|
||||
exclude "jargs/gnu/**/*"
|
||||
|
||||
mergeServiceFiles()
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ public class JSONFactory {
|
||||
}
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> serverPlayerKillsAsJSONMap(ServerUUID serverUUID) {
|
||||
public List<Map<String, Object>> serverPlayerKillsAsJSONMaps(ServerUUID serverUUID) {
|
||||
Database db = dbSystem.getDatabase();
|
||||
List<PlayerKill> kills = db.query(KillQueries.fetchPlayerKillsOnServer(serverUUID, 100));
|
||||
return new PlayerKillMutator(kills).toJSONAsMap(formatters);
|
||||
|
@ -185,7 +185,7 @@ public class ResponseFactory {
|
||||
.setStatus(200)
|
||||
.build();
|
||||
} catch (UncheckedIOException e) {
|
||||
return notFound404("JS File not found from jar: " + fileName + ", " + e.toString());
|
||||
return notFound404("JS File not found from jar: " + fileName + ", " + e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,7 +204,7 @@ public class ResponseFactory {
|
||||
.setStatus(200)
|
||||
.build();
|
||||
} catch (UncheckedIOException e) {
|
||||
return notFound404("CSS File not found from jar: " + fileName + ", " + e.toString());
|
||||
return notFound404("CSS File not found from jar: " + fileName + ", " + e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,7 +216,7 @@ public class ResponseFactory {
|
||||
.setStatus(200)
|
||||
.build();
|
||||
} catch (UncheckedIOException e) {
|
||||
return notFound404("Image File not found from jar: " + fileName + ", " + e.toString());
|
||||
return notFound404("Image File not found from jar: " + fileName + ", " + e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,7 +239,7 @@ public class ResponseFactory {
|
||||
.setContent(getResource(fileName))
|
||||
.build();
|
||||
} catch (UncheckedIOException e) {
|
||||
return notFound404("Font File not found from jar: " + fileName + ", " + e.toString());
|
||||
return notFound404("Font File not found from jar: " + fileName + ", " + e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -454,4 +454,15 @@ public class ResponseFactory {
|
||||
return forInternalError(e, "Could not read " + file);
|
||||
}
|
||||
}
|
||||
|
||||
public Response reactPageResponse() {
|
||||
try {
|
||||
return Response.builder()
|
||||
.setMimeType(MimeType.HTML)
|
||||
.setContent(getResource("index.html"))
|
||||
.build();
|
||||
} catch (UncheckedIOException e) {
|
||||
return forInternalError(e, "Could not read index.html");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,11 +30,17 @@ import com.djrapitops.plan.delivery.webserver.http.WebServer;
|
||||
import com.djrapitops.plan.delivery.webserver.resolver.*;
|
||||
import com.djrapitops.plan.delivery.webserver.resolver.auth.*;
|
||||
import com.djrapitops.plan.delivery.webserver.resolver.json.RootJSONResolver;
|
||||
import com.djrapitops.plan.delivery.webserver.resolver.swagger.SwaggerJsonResolver;
|
||||
import com.djrapitops.plan.delivery.webserver.resolver.swagger.SwaggerPageResolver;
|
||||
import com.djrapitops.plan.exceptions.WebUserAuthException;
|
||||
import com.djrapitops.plan.exceptions.connection.ForbiddenException;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorContext;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorLogger;
|
||||
import dagger.Lazy;
|
||||
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
|
||||
import io.swagger.v3.oas.annotations.info.Contact;
|
||||
import io.swagger.v3.oas.annotations.info.Info;
|
||||
import io.swagger.v3.oas.annotations.info.License;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -52,6 +58,12 @@ import java.util.regex.Pattern;
|
||||
* @author AuroraLS3
|
||||
*/
|
||||
@Singleton
|
||||
@OpenAPIDefinition(info = @Info(
|
||||
title = "Plan API endpoints",
|
||||
description = "If authentication is enabled (see response of /v1/whoami) logging in is required for endpoints (/auth/login). Pass 'Cookie' header in the requests after login.",
|
||||
contact = @Contact(name = "Github Discussions", url = "https://github.com/plan-player-analytics/Plan/discussions/categories/apis-and-development"),
|
||||
license = @License(name = "GNU Lesser General Public License v3.0 (LGPLv3.0)", url = "https://github.com/plan-player-analytics/Plan/blob/master/LICENSE")
|
||||
))
|
||||
public class ResponseResolver {
|
||||
|
||||
private final QueryPageResolver queryPageResolver;
|
||||
@ -67,6 +79,8 @@ public class ResponseResolver {
|
||||
private final LogoutResolver logoutResolver;
|
||||
private final RegisterResolver registerResolver;
|
||||
private final ErrorsPageResolver errorsPageResolver;
|
||||
private final SwaggerJsonResolver swaggerJsonResolver;
|
||||
private final SwaggerPageResolver swaggerPageResolver;
|
||||
private final ErrorLogger errorLogger;
|
||||
|
||||
private final ResolverService resolverService;
|
||||
@ -94,6 +108,9 @@ public class ResponseResolver {
|
||||
RegisterResolver registerResolver,
|
||||
ErrorsPageResolver errorsPageResolver,
|
||||
|
||||
SwaggerJsonResolver swaggerJsonResolver,
|
||||
SwaggerPageResolver swaggerPageResolver,
|
||||
|
||||
ErrorLogger errorLogger
|
||||
) {
|
||||
this.resolverService = resolverService;
|
||||
@ -112,6 +129,8 @@ public class ResponseResolver {
|
||||
this.logoutResolver = logoutResolver;
|
||||
this.registerResolver = registerResolver;
|
||||
this.errorsPageResolver = errorsPageResolver;
|
||||
this.swaggerJsonResolver = swaggerJsonResolver;
|
||||
this.swaggerPageResolver = swaggerPageResolver;
|
||||
this.errorLogger = errorLogger;
|
||||
}
|
||||
|
||||
@ -140,6 +159,8 @@ public class ResponseResolver {
|
||||
resolverService.registerResolverForMatches(plugin, Pattern.compile(StaticResourceResolver.PATH_REGEX), staticResourceResolver);
|
||||
|
||||
resolverService.registerResolver(plugin, "/v1", rootJSONResolver.getResolver());
|
||||
resolverService.registerResolver(plugin, "/docs/swagger.json", swaggerJsonResolver);
|
||||
resolverService.registerResolver(plugin, "/docs", swaggerPageResolver);
|
||||
}
|
||||
|
||||
private NoAuthResolver fileResolver(Supplier<Response> response) {
|
||||
|
@ -30,6 +30,13 @@ import com.djrapitops.plan.exceptions.WebUserAuthException;
|
||||
import com.djrapitops.plan.exceptions.database.DBOpException;
|
||||
import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.WebUserQueries;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -37,6 +44,7 @@ import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
@Singleton
|
||||
@Path("/auth/login")
|
||||
public class LoginResolver implements NoAuthResolver {
|
||||
|
||||
private final DBSystem dbSystem;
|
||||
@ -51,6 +59,21 @@ public class LoginResolver implements NoAuthResolver {
|
||||
this.activeCookieStore = activeCookieStore;
|
||||
}
|
||||
|
||||
@POST
|
||||
@Operation(
|
||||
description = "Log in as user. Pass user=username&password=password in response body.",
|
||||
requestBody = @RequestBody(
|
||||
required = true,
|
||||
content = @Content(
|
||||
examples = {@ExampleObject("user=username&password=password")}
|
||||
)
|
||||
),
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", description = "Login success, read Set-Cookie header for cookie"),
|
||||
@ApiResponse(responseCode = "400", description = "Bad input user details"),
|
||||
@ApiResponse(responseCode = "403", description = "Too many attempts, wait"),
|
||||
}
|
||||
)
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
try {
|
||||
|
@ -22,12 +22,20 @@ import com.djrapitops.plan.delivery.web.resolver.request.Request;
|
||||
import com.djrapitops.plan.delivery.webserver.auth.ActiveCookieStore;
|
||||
import com.djrapitops.plan.delivery.webserver.auth.FailReason;
|
||||
import com.djrapitops.plan.exceptions.WebUserAuthException;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Optional;
|
||||
|
||||
@Singleton
|
||||
@Path("/auth/logout")
|
||||
public class LogoutResolver implements NoAuthResolver {
|
||||
|
||||
private final ActiveCookieStore activeCookieStore;
|
||||
@ -39,6 +47,15 @@ public class LogoutResolver implements NoAuthResolver {
|
||||
this.activeCookieStore = activeCookieStore;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Operation(
|
||||
description = "Logout the user by removing cookie",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "302 (success)", description = "Logout successful, redirects to /login"),
|
||||
@ApiResponse(responseCode = "302 (failure)", description = "Cookie had already expired, redirects to /login"),
|
||||
},
|
||||
requestBody = @RequestBody(content = @Content(examples = @ExampleObject()))
|
||||
)
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
String cookies = request.getHeader("Cookie").orElse("");
|
||||
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.djrapitops.plan.delivery.webserver.resolver.auth;
|
||||
|
||||
import com.djrapitops.plan.delivery.web.resolver.MimeType;
|
||||
import com.djrapitops.plan.delivery.web.resolver.NoAuthResolver;
|
||||
import com.djrapitops.plan.delivery.web.resolver.Response;
|
||||
import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException;
|
||||
@ -27,6 +28,15 @@ import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.WebUserQueries;
|
||||
import com.djrapitops.plan.utilities.PassEncryptUtil;
|
||||
import com.djrapitops.plan.utilities.java.Maps;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -34,13 +44,35 @@ import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
@Singleton
|
||||
@Path("/auth/register")
|
||||
public class RegisterResolver implements NoAuthResolver {
|
||||
|
||||
private final DBSystem dbSystem;
|
||||
|
||||
@Inject
|
||||
public RegisterResolver(DBSystem dbSystem) {this.dbSystem = dbSystem;}
|
||||
public RegisterResolver(DBSystem dbSystem) {
|
||||
this.dbSystem = dbSystem;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Operation(
|
||||
description = "Start new registration and check if registration is complete. POST user=username&password=password to start new registration.",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200 (new)", description = "New registration started (when given request body details)", content = @Content(mediaType = MimeType.JSON, examples = @ExampleObject("{\"success\": true, \"code\": \"474AF76D5362\"}"))),
|
||||
@ApiResponse(responseCode = "200 (unfinished)", description = "Registration not yet completed (when given code as parameter)", content = @Content(mediaType = MimeType.JSON, examples = @ExampleObject("{\"success\": false}"))),
|
||||
@ApiResponse(responseCode = "200 (completed)", description = "Registration completed (when given code as parameter)", content = @Content(mediaType = MimeType.JSON, examples = @ExampleObject("{\"success\": true}"))),
|
||||
@ApiResponse(responseCode = "400", description = "Given username has already been registered", content = @Content(mediaType = MimeType.JSON, examples = @ExampleObject("{\"status\": 400, \"error\": \"User already exists!\"}"))),
|
||||
},
|
||||
parameters = {
|
||||
@Parameter(in = ParameterIn.QUERY, name = "code", description = "Registration code for finishing registration, Check if registration is complete - success: true if yes.")
|
||||
},
|
||||
requestBody = @RequestBody(
|
||||
description = "Register a new user",
|
||||
content = @Content(
|
||||
examples = @ExampleObject("user=username&password=password")
|
||||
)
|
||||
)
|
||||
)
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
return Optional.of(getResponse(request));
|
||||
|
@ -22,6 +22,15 @@ 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.WebUser;
|
||||
import com.djrapitops.plan.storage.file.PlanFiles;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.ArraySchema;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -36,6 +45,7 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Singleton
|
||||
@Path("/v1/errors")
|
||||
public class ErrorsJSONResolver implements Resolver {
|
||||
|
||||
private final PlanFiles files;
|
||||
@ -50,6 +60,14 @@ public class ErrorsJSONResolver implements Resolver {
|
||||
return request.getUser().orElse(new WebUser("")).hasPermission("page.server");
|
||||
}
|
||||
|
||||
@GET
|
||||
@Operation(
|
||||
description = "Get list of Plan error logs",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", description = "List of error files and their contents", content = @Content(array = @ArraySchema(schema = @Schema(implementation = ErrorFile.class))))
|
||||
},
|
||||
requestBody = @RequestBody(content = @Content(examples = @ExampleObject()))
|
||||
)
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
return Optional.of(getResponse());
|
||||
@ -79,7 +97,7 @@ public class ErrorsJSONResolver implements Resolver {
|
||||
try (Stream<String> lines = Files.lines(file.toPath())) {
|
||||
return lines.collect(Collectors.toList());
|
||||
} catch (IOException e) {
|
||||
return Collections.singletonList("Failed to read " + file.getAbsolutePath() + ": " + e.toString());
|
||||
return Collections.singletonList("Failed to read " + file.getAbsolutePath() + ": " + e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,14 @@ import com.djrapitops.plan.storage.database.queries.objects.TPSQueries;
|
||||
import com.djrapitops.plan.utilities.java.Lists;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorContext;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorLogger;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -46,6 +54,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Singleton
|
||||
@Path("/v1/filters")
|
||||
public class FiltersJSONResolver implements Resolver {
|
||||
|
||||
private final ServerInfo serverInfo;
|
||||
@ -81,6 +90,14 @@ public class FiltersJSONResolver implements Resolver {
|
||||
return user.hasPermission("page.players");
|
||||
}
|
||||
|
||||
@GET
|
||||
@Operation(
|
||||
description = "Get list of available filters, view and graph points for visualizing the view",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", content = @Content(mediaType = MimeType.JSON, schema = @Schema(implementation = FilterResponseDto.class)))
|
||||
},
|
||||
requestBody = @RequestBody(content = @Content(examples = @ExampleObject()))
|
||||
)
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
return Optional.of(getResponse());
|
||||
|
@ -29,6 +29,15 @@ import com.djrapitops.plan.delivery.webserver.cache.DataID;
|
||||
import com.djrapitops.plan.delivery.webserver.cache.JSONStorage;
|
||||
import com.djrapitops.plan.identification.Identifiers;
|
||||
import com.djrapitops.plan.identification.ServerUUID;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -41,6 +50,7 @@ import java.util.Optional;
|
||||
* @author AuroraLS3
|
||||
*/
|
||||
@Singleton
|
||||
@Path("/v1/graph")
|
||||
public class GraphsJSONResolver implements Resolver {
|
||||
|
||||
private final Identifiers identifiers;
|
||||
@ -70,6 +80,40 @@ public class GraphsJSONResolver implements Resolver {
|
||||
* @throws BadRequestException If 'type' parameter is not defined or supported.
|
||||
* @throws BadRequestException If 'server' parameter is not defined or server is not found in database.
|
||||
*/
|
||||
@GET
|
||||
@Operation(
|
||||
description = "Get graph data",
|
||||
parameters = {
|
||||
@Parameter(in = ParameterIn.QUERY, name = "type", description = "Type of the graph, see https://github.com/plan-player-analytics/Plan/blob/master/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/resolver/json/GraphsJSONResolver.java", required = true, examples = {
|
||||
@ExampleObject(value = "performance", description = "Deprecated, use optimizedPerformance"),
|
||||
@ExampleObject("optimizedPerformance"),
|
||||
@ExampleObject("playersOnline"),
|
||||
@ExampleObject("uniqueAndNew"),
|
||||
@ExampleObject("hourlyUniqueAndNew"),
|
||||
@ExampleObject("serverCalendar"),
|
||||
@ExampleObject("worldPie"),
|
||||
@ExampleObject("activity"),
|
||||
@ExampleObject("geolocation"),
|
||||
@ExampleObject("aggregatedPing"),
|
||||
@ExampleObject("punchCard"),
|
||||
@ExampleObject("serverPie"),
|
||||
@ExampleObject("joinAddressPie"),
|
||||
}),
|
||||
@Parameter(in = ParameterIn.QUERY, name = "server", description = "Server identifier to get data for", examples = {
|
||||
@ExampleObject("Server 1"),
|
||||
@ExampleObject("1"),
|
||||
@ExampleObject("1fb39d2a-eb82-4868-b245-1fad17d823b3"),
|
||||
}),
|
||||
@Parameter(in = ParameterIn.QUERY, name = "timestamp", description = "Epoch millisecond for the request, newer value is wanted")
|
||||
},
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", description = "Graph data json", content = @Content()),
|
||||
@ApiResponse(responseCode = "400", description = "'type' parameter not given", content = @Content(examples = {
|
||||
@ExampleObject("{\"status\": 400, \"error\": \"'type' parameter was not defined.\"}")
|
||||
})),
|
||||
},
|
||||
requestBody = @RequestBody(content = @Content(examples = @ExampleObject()))
|
||||
)
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
return Optional.of(getResponse(request));
|
||||
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.djrapitops.plan.delivery.webserver.resolver.json;
|
||||
|
||||
import com.djrapitops.plan.delivery.web.resolver.MimeType;
|
||||
import com.djrapitops.plan.delivery.web.resolver.NoAuthResolver;
|
||||
import com.djrapitops.plan.delivery.web.resolver.Response;
|
||||
import com.djrapitops.plan.delivery.web.resolver.ResponseBuilder;
|
||||
@ -29,6 +30,15 @@ import com.djrapitops.plan.settings.locale.Locale;
|
||||
import com.djrapitops.plan.settings.locale.LocaleSystem;
|
||||
import com.djrapitops.plan.storage.file.PlanFiles;
|
||||
import com.djrapitops.plan.storage.file.Resource;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -42,6 +52,7 @@ import java.util.*;
|
||||
* @author Kopo942
|
||||
*/
|
||||
@Singleton
|
||||
@Path("/v1/locale/{langCode}")
|
||||
public class LocaleJSONResolver implements NoAuthResolver {
|
||||
|
||||
private final LocaleSystem localeSystem;
|
||||
@ -62,6 +73,20 @@ public class LocaleJSONResolver implements NoAuthResolver {
|
||||
this.addresses = addresses;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Operation(
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200 (/locale)", description = "List of available locales", content = @Content(mediaType = MimeType.JSON, examples = {
|
||||
@ExampleObject("{\"defaultLanguage\": \"EN\", \"languages\": {\"EN\": \"English\", \"FI\": \"Finnish\"}, \"languageVersions\": {\"EN\": 1657189514266, \"FI\": 1657189514266}}")
|
||||
})),
|
||||
@ApiResponse(responseCode = "200 (/locale/{langCode})", description = "Contents of the locale.json file matching given langCode"),
|
||||
@ApiResponse(responseCode = "404", description = "Language by langCode was not found")
|
||||
},
|
||||
parameters = {
|
||||
@Parameter(in = ParameterIn.PATH, name = "langCode", description = "Language code. NOT REQUIRED. /v1/locale lists available language codes.", allowEmptyValue = true, example = "/v1/locale/EN")
|
||||
},
|
||||
requestBody = @RequestBody(content = @Content(examples = @ExampleObject()))
|
||||
)
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
return Optional.of(getResponse(request));
|
||||
|
@ -27,12 +27,19 @@ import com.djrapitops.plan.settings.config.paths.ProxySettings;
|
||||
import com.djrapitops.plan.settings.theme.Theme;
|
||||
import com.djrapitops.plan.settings.theme.ThemeVal;
|
||||
import com.djrapitops.plan.utilities.java.Maps;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Optional;
|
||||
|
||||
@Singleton
|
||||
@Path("/v1/metadata")
|
||||
public class MetadataJSONResolver implements NoAuthResolver {
|
||||
|
||||
private final PlanConfig config;
|
||||
@ -47,6 +54,11 @@ public class MetadataJSONResolver implements NoAuthResolver {
|
||||
this.serverInfo = serverInfo;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Operation(
|
||||
description = "Get metadata required for displaying Plan React frontend",
|
||||
requestBody = @RequestBody(content = @Content(examples = @ExampleObject()))
|
||||
)
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
return Optional.of(getResponse());
|
||||
|
@ -19,6 +19,7 @@ package com.djrapitops.plan.delivery.webserver.resolver.json;
|
||||
import com.djrapitops.plan.delivery.domain.mutators.TPSMutator;
|
||||
import com.djrapitops.plan.delivery.formatting.Formatter;
|
||||
import com.djrapitops.plan.delivery.formatting.Formatters;
|
||||
import com.djrapitops.plan.delivery.web.resolver.MimeType;
|
||||
import com.djrapitops.plan.delivery.web.resolver.Resolver;
|
||||
import com.djrapitops.plan.delivery.web.resolver.Response;
|
||||
import com.djrapitops.plan.delivery.web.resolver.request.Request;
|
||||
@ -34,6 +35,15 @@ import com.djrapitops.plan.storage.database.Database;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.TPSQueries;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -47,6 +57,7 @@ import java.util.stream.Collectors;
|
||||
* @author AuroraLS3
|
||||
*/
|
||||
@Singleton
|
||||
@Path("/v1/network/performanceOverview")
|
||||
public class NetworkPerformanceJSONResolver implements Resolver {
|
||||
|
||||
private final PlanConfig config;
|
||||
@ -83,6 +94,19 @@ public class NetworkPerformanceJSONResolver implements Resolver {
|
||||
return request.getUser().orElse(new WebUser("")).hasPermission("page.network");
|
||||
}
|
||||
|
||||
@GET
|
||||
@Operation(
|
||||
description = "Get performance overview information for multiple servers",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", content = @Content(mediaType = MimeType.JSON, examples = {
|
||||
@ExampleObject("{\"numbers\": {}}")
|
||||
}))
|
||||
},
|
||||
parameters = {
|
||||
@Parameter(in = ParameterIn.QUERY, name = "servers", required = true, description = "JSON list of server uuids (URI encoded)", example = "%5B%22a779e107-0474-4d9f-8f4d-f1efb068d32e%22%5D (is [\"a779e107-0474-4d9f-8f4d-f1efb068d32e\"])")
|
||||
},
|
||||
requestBody = @RequestBody(content = @Content(examples = @ExampleObject()))
|
||||
)
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
List<ServerUUID> serverUUIDs = request.getQuery().get("servers")
|
||||
|
@ -24,6 +24,15 @@ import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException;
|
||||
import com.djrapitops.plan.delivery.web.resolver.request.Request;
|
||||
import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
|
||||
import com.djrapitops.plan.identification.Identifiers;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -31,6 +40,7 @@ import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Singleton
|
||||
@Path("/v1/player")
|
||||
public class PlayerJSONResolver implements Resolver {
|
||||
|
||||
private final Identifiers identifiers;
|
||||
@ -58,6 +68,19 @@ public class PlayerJSONResolver implements Resolver {
|
||||
return false;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Operation(
|
||||
description = "Get player data for visualizing a single player",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", content = @Content(mediaType = MimeType.JSON)),
|
||||
@ApiResponse(responseCode = "400", description = "If 'player' parameter is not given")
|
||||
},
|
||||
parameters = @Parameter(in = ParameterIn.QUERY, name = "player", description = "Identifier for the player", examples = {
|
||||
@ExampleObject("dade56b7-366a-495a-a087-5bf0178536d4"),
|
||||
@ExampleObject("AuroraLS3"),
|
||||
}),
|
||||
requestBody = @RequestBody(content = @Content(examples = @ExampleObject()))
|
||||
)
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
return Optional.of(getResponse(request));
|
||||
|
@ -27,6 +27,15 @@ import com.djrapitops.plan.delivery.webserver.cache.DataID;
|
||||
import com.djrapitops.plan.delivery.webserver.cache.JSONStorage;
|
||||
import com.djrapitops.plan.identification.Identifiers;
|
||||
import com.djrapitops.plan.identification.ServerUUID;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -39,6 +48,7 @@ import java.util.Optional;
|
||||
* @author AuroraLS3
|
||||
*/
|
||||
@Singleton
|
||||
@Path("/v1/kills")
|
||||
public class PlayerKillsJSONResolver implements Resolver {
|
||||
|
||||
private final Identifiers identifiers;
|
||||
@ -61,6 +71,23 @@ public class PlayerKillsJSONResolver implements Resolver {
|
||||
return request.getUser().orElse(new WebUser("")).hasPermission("page.server");
|
||||
}
|
||||
|
||||
@GET
|
||||
@Operation(
|
||||
description = "Get player kill data for a server",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", content = @Content(mediaType = MimeType.JSON, examples = {
|
||||
@ExampleObject("{\"player_kills\": []}")
|
||||
})),
|
||||
@ApiResponse(responseCode = "400 (no parameter)", description = "If 'server' parameter is not given"),
|
||||
@ApiResponse(responseCode = "400 (no match)", description = "If 'server' parameter does not match an existing server")
|
||||
},
|
||||
parameters = @Parameter(in = ParameterIn.QUERY, name = "server", description = "Identifier for the server", examples = {
|
||||
@ExampleObject("dade56b7-366a-495a-a087-5bf0178536d4"),
|
||||
@ExampleObject("Server 1"),
|
||||
@ExampleObject("1"),
|
||||
}),
|
||||
requestBody = @RequestBody(content = @Content(examples = @ExampleObject()))
|
||||
)
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
return Optional.of(getResponse(request));
|
||||
@ -70,7 +97,7 @@ public class PlayerKillsJSONResolver implements Resolver {
|
||||
ServerUUID serverUUID = identifiers.getServerUUID(request);
|
||||
Optional<Long> timestamp = Identifiers.getTimestamp(request);
|
||||
JSONStorage.StoredJSON storedJSON = jsonResolverService.resolve(timestamp, DataID.KILLS, serverUUID,
|
||||
theUUID -> Collections.singletonMap("player_kills", jsonFactory.serverPlayerKillsAsJSONMap(theUUID))
|
||||
theUUID -> Collections.singletonMap("player_kills", jsonFactory.serverPlayerKillsAsJSONMaps(theUUID))
|
||||
);
|
||||
return Response.builder()
|
||||
.setMimeType(MimeType.JSON)
|
||||
|
@ -27,6 +27,15 @@ import com.djrapitops.plan.delivery.webserver.cache.DataID;
|
||||
import com.djrapitops.plan.delivery.webserver.cache.JSONStorage;
|
||||
import com.djrapitops.plan.identification.Identifiers;
|
||||
import com.djrapitops.plan.identification.ServerUUID;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -38,6 +47,7 @@ import java.util.Optional;
|
||||
* @author AuroraLS3
|
||||
*/
|
||||
@Singleton
|
||||
@Path("/v1/players")
|
||||
public class PlayersTableJSONResolver implements Resolver {
|
||||
|
||||
private final Identifiers identifiers;
|
||||
@ -65,6 +75,19 @@ public class PlayersTableJSONResolver implements Resolver {
|
||||
return user.hasPermission("page.players");
|
||||
}
|
||||
|
||||
@GET
|
||||
@Operation(
|
||||
description = "Get player table data for /players page or a server",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", content = @Content(mediaType = MimeType.JSON)),
|
||||
},
|
||||
parameters = @Parameter(in = ParameterIn.QUERY, name = "server", description = "Server identifier to get data for (optional)", examples = {
|
||||
@ExampleObject("Server 1"),
|
||||
@ExampleObject("1"),
|
||||
@ExampleObject("1fb39d2a-eb82-4868-b245-1fad17d823b3"),
|
||||
}),
|
||||
requestBody = @RequestBody(content = @Content(examples = @ExampleObject()))
|
||||
)
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
return Optional.of(getResponse(request));
|
||||
|
@ -49,6 +49,15 @@ import com.djrapitops.plan.storage.database.queries.objects.SessionQueries;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.playertable.QueryTablePlayersQuery;
|
||||
import com.djrapitops.plan.utilities.java.Maps;
|
||||
import com.google.gson.Gson;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import net.playeranalytics.plugin.scheduling.TimeAmount;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@ -60,6 +69,7 @@ import java.text.ParseException;
|
||||
import java.util.*;
|
||||
|
||||
@Singleton
|
||||
@Path("/v1/query")
|
||||
public class QueryJSONResolver implements Resolver {
|
||||
|
||||
private final QueryFilters filters;
|
||||
@ -101,6 +111,21 @@ public class QueryJSONResolver implements Resolver {
|
||||
return user.hasPermission("page.players");
|
||||
}
|
||||
|
||||
@GET
|
||||
@Operation(
|
||||
description = "Perform a query or get cached results. Use q to do new query, timestamp to see cached query.",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", content = @Content(mediaType = MimeType.JSON)),
|
||||
@ApiResponse(responseCode = "400 (invalid view)", description = "If 'view' date formats does not match afterDate dd/mm/yyyy, afterTime hh:mm, beforeDate dd/mm/yyyy, beforeTime hh:mm"),
|
||||
@ApiResponse(responseCode = "400 (no query)", description = "If request body is empty and 'q' request parameter is not given"),
|
||||
@ApiResponse(responseCode = "400 (invalid query)", description = "If request body is empty and 'q' json request parameter doesn't contain 'view' property"),
|
||||
},
|
||||
parameters = {
|
||||
@Parameter(in = ParameterIn.QUERY, name = "timestamp", description = "Epoch millisecond for cached query"),
|
||||
@Parameter(in = ParameterIn.QUERY, name = "q", description = "URI encoded json, alternative is to POST in request body", schema = @Schema(implementation = InputQueryDto.class))
|
||||
},
|
||||
requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = InputQueryDto.class)))
|
||||
)
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
return Optional.of(getResponse(request));
|
||||
|
@ -27,6 +27,15 @@ import com.djrapitops.plan.delivery.webserver.cache.DataID;
|
||||
import com.djrapitops.plan.delivery.webserver.cache.JSONStorage;
|
||||
import com.djrapitops.plan.identification.Identifiers;
|
||||
import com.djrapitops.plan.identification.ServerUUID;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -39,6 +48,7 @@ import java.util.Optional;
|
||||
* @author AuroraLS3
|
||||
*/
|
||||
@Singleton
|
||||
@Path("/v1/sessions")
|
||||
public class SessionsJSONResolver implements Resolver {
|
||||
|
||||
private final Identifiers identifiers;
|
||||
@ -61,6 +71,20 @@ public class SessionsJSONResolver implements Resolver {
|
||||
return request.getUser().orElse(new WebUser("")).hasPermission("page.server");
|
||||
}
|
||||
|
||||
@GET
|
||||
@Operation(
|
||||
description = "Get sessions for a server or whole network",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", content = @Content(mediaType = MimeType.JSON)),
|
||||
@ApiResponse(responseCode = "400", description = "If 'server' parameter is not an existing server")
|
||||
},
|
||||
parameters = @Parameter(in = ParameterIn.QUERY, name = "server", description = "Server identifier to get data for (optional)", examples = {
|
||||
@ExampleObject("Server 1"),
|
||||
@ExampleObject("1"),
|
||||
@ExampleObject("1fb39d2a-eb82-4868-b245-1fad17d823b3"),
|
||||
}),
|
||||
requestBody = @RequestBody(content = @Content(examples = @ExampleObject()))
|
||||
)
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
return Optional.of(getResponse(request));
|
||||
|
@ -16,11 +16,19 @@
|
||||
*/
|
||||
package com.djrapitops.plan.delivery.webserver.resolver.json;
|
||||
|
||||
import com.djrapitops.plan.delivery.web.resolver.MimeType;
|
||||
import com.djrapitops.plan.delivery.web.resolver.Resolver;
|
||||
import com.djrapitops.plan.delivery.web.resolver.Response;
|
||||
import com.djrapitops.plan.delivery.web.resolver.request.Request;
|
||||
import com.djrapitops.plan.version.VersionChecker;
|
||||
import com.djrapitops.plan.version.VersionInfo;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
@ -33,6 +41,7 @@ import java.util.Optional;
|
||||
*
|
||||
* @author Kopo942
|
||||
*/
|
||||
@Path("/v1/version")
|
||||
public class VersionJSONResolver implements Resolver {
|
||||
|
||||
private final VersionChecker versionChecker;
|
||||
@ -52,6 +61,14 @@ public class VersionJSONResolver implements Resolver {
|
||||
return true;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Operation(
|
||||
description = "Get Plan version and update information",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", content = @Content(mediaType = MimeType.JSON)),
|
||||
},
|
||||
requestBody = @RequestBody(content = @Content(examples = @ExampleObject()))
|
||||
)
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
return Optional.of(getResponse());
|
||||
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.djrapitops.plan.delivery.webserver.resolver.json;
|
||||
|
||||
import com.djrapitops.plan.delivery.web.resolver.MimeType;
|
||||
import com.djrapitops.plan.delivery.web.resolver.NoAuthResolver;
|
||||
import com.djrapitops.plan.delivery.web.resolver.Response;
|
||||
import com.djrapitops.plan.delivery.web.resolver.request.Request;
|
||||
@ -23,12 +24,20 @@ import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
|
||||
import com.djrapitops.plan.delivery.webserver.http.WebServer;
|
||||
import com.djrapitops.plan.utilities.java.Maps;
|
||||
import dagger.Lazy;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Optional;
|
||||
|
||||
@Singleton
|
||||
@Path("/v1/whoami")
|
||||
public class WhoAmIJSONResolver implements NoAuthResolver {
|
||||
|
||||
private final Lazy<WebServer> webServer;
|
||||
@ -38,6 +47,18 @@ public class WhoAmIJSONResolver implements NoAuthResolver {
|
||||
this.webServer = webServer;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Operation(
|
||||
description = "Get information about the currently logged in user",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", content = @Content(mediaType = MimeType.JSON, examples = {
|
||||
@ExampleObject(value = "{\"authRequired\": false, \"loggedIn\": false}", description = "Authentication is disabled"),
|
||||
@ExampleObject(value = "{\"authRequired\": true, \"loggedIn\": false}", description = "Not logged in"),
|
||||
@ExampleObject(value = "{\"authRequired\": true, \"loggedIn\": true, \"user\": {}}", description = "Logged in as user"),
|
||||
})),
|
||||
},
|
||||
requestBody = @RequestBody(content = @Content(examples = @ExampleObject()))
|
||||
)
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
return Optional.of(getResponse(request));
|
||||
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.webserver.resolver.swagger;
|
||||
|
||||
import com.djrapitops.plan.delivery.web.resolver.Resolver;
|
||||
import com.djrapitops.plan.delivery.web.resolver.Response;
|
||||
import com.djrapitops.plan.delivery.web.resolver.request.Request;
|
||||
import com.djrapitops.plan.delivery.webserver.ResponseFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Optional;
|
||||
|
||||
@Singleton
|
||||
public class SwaggerJsonResolver implements Resolver {
|
||||
|
||||
private final ResponseFactory responseFactory;
|
||||
|
||||
@Inject
|
||||
public SwaggerJsonResolver(ResponseFactory responseFactory) {
|
||||
this.responseFactory = responseFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccess(Request request) {
|
||||
return request.getUser()
|
||||
.filter(user -> user.hasPermission("page.server"))
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
return Optional.of(responseFactory.jsonFileResponse("swagger.json"));
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.webserver.resolver.swagger;
|
||||
|
||||
import com.djrapitops.plan.delivery.web.resolver.Resolver;
|
||||
import com.djrapitops.plan.delivery.web.resolver.Response;
|
||||
import com.djrapitops.plan.delivery.web.resolver.request.Request;
|
||||
import com.djrapitops.plan.delivery.webserver.ResponseFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Optional;
|
||||
|
||||
@Singleton
|
||||
public class SwaggerPageResolver implements Resolver {
|
||||
|
||||
private final ResponseFactory responseFactory;
|
||||
|
||||
@Inject
|
||||
public SwaggerPageResolver(ResponseFactory responseFactory) {
|
||||
this.responseFactory = responseFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccess(Request request) {
|
||||
return request.getUser()
|
||||
.filter(user -> user.hasPermission("page.server"))
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Response> resolve(Request request) {
|
||||
return Optional.of(responseFactory.reactPageResponse());
|
||||
}
|
||||
}
|
@ -215,6 +215,8 @@ class AccessControlTest {
|
||||
"/v1/locale,200",
|
||||
"/v1/locale/EN,200",
|
||||
"/v1/locale/NonexistingLanguage,404",
|
||||
"/docs/swagger.json,500", // swagger.json not available during tests
|
||||
"/docs,200",
|
||||
})
|
||||
void levelZeroCanAccess(String resource, String expectedResponseCode) throws NoSuchAlgorithmException, IOException, KeyManagementException {
|
||||
int responseCode = access(resource, cookieLevel0);
|
||||
@ -285,6 +287,8 @@ class AccessControlTest {
|
||||
"/v1/locale,200",
|
||||
"/v1/locale/EN,200",
|
||||
"/v1/locale/NonexistingLanguage,404",
|
||||
"/docs/swagger.json,403",
|
||||
"/docs,403",
|
||||
})
|
||||
void levelOneCanAccess(String resource, String expectedResponseCode) throws NoSuchAlgorithmException, IOException, KeyManagementException {
|
||||
int responseCode = access(resource, cookieLevel1);
|
||||
@ -355,6 +359,8 @@ class AccessControlTest {
|
||||
"/v1/locale,200",
|
||||
"/v1/locale/EN,200",
|
||||
"/v1/locale/NonexistingLanguage,404",
|
||||
"/docs/swagger.json,403",
|
||||
"/docs,403",
|
||||
})
|
||||
void levelTwoCanAccess(String resource, String expectedResponseCode) throws NoSuchAlgorithmException, IOException, KeyManagementException {
|
||||
int responseCode = access(resource, cookieLevel2);
|
||||
@ -423,6 +429,8 @@ class AccessControlTest {
|
||||
"/v1/locale,200",
|
||||
"/v1/locale/EN,200",
|
||||
"/v1/locale/NonexistingLanguage,404",
|
||||
"/docs/swagger.json,403",
|
||||
"/docs,403",
|
||||
})
|
||||
void levelHundredCanNotAccess(String resource, String expectedResponseCode) throws NoSuchAlgorithmException, IOException, KeyManagementException {
|
||||
int responseCode = access(resource, cookieLevel100);
|
||||
|
@ -76,8 +76,8 @@
|
||||
|
||||
<!-- Metrics -->
|
||||
<module name="ClassFanOutComplexity">
|
||||
<!-- This value is ok with manual exceptions. -->
|
||||
<property name="max" value="35"/>
|
||||
<!-- This value is a bit high. -->
|
||||
<property name="max" value="40"/>
|
||||
</module>
|
||||
<module name="CyclomaticComplexity">
|
||||
<!-- This value is high. Notable: ThemeConfig: 16 -->
|
||||
|
@ -1,55 +1,57 @@
|
||||
dependencies {
|
||||
implementation project(path: ":api")
|
||||
implementation 'net.playeranalytics:Extension-AAC:4.4.2-R1.1'
|
||||
implementation 'net.playeranalytics:Extension-AdvancedAchievements:6.4.0-R1.1'
|
||||
implementation 'net.playeranalytics:Extension-AdvancedBan:2.1.5-R2.0'
|
||||
implementation 'net.playeranalytics:Extension-ASkyBlock:3.0.9.4-R1.5'
|
||||
implementation 'net.playeranalytics:Extension-AuthMe:5.6.0-R1.2'
|
||||
implementation 'net.playeranalytics:Extension-BanManager:7.3.1-R1.2'
|
||||
implementation 'net.playeranalytics:Extension-BentoBox:1.15.5-R2.0'
|
||||
// implementation 'net.playeranalytics:Extension-CoreProtect:2.16.0-R1.4' // unable to compile new version
|
||||
implementation 'net.playeranalytics:Extension-DiscordSRV:1.25.1-R1.4'
|
||||
implementation 'net.playeranalytics:Extension-DKBans:2.1.2-R1.3'
|
||||
implementation 'net.playeranalytics:Extension-DKCoins:3.0.5-R1.1'
|
||||
implementation 'net.playeranalytics:Extension-EssentialsX:2.15.0-R2.0'
|
||||
implementation 'net.playeranalytics:Extension-Factions:2.14.0-R1.1'
|
||||
implementation 'net.playeranalytics:Extension-FactionsUUID:1.6.9.5-U0.5.25-R1.1'
|
||||
implementation 'net.playeranalytics:Extension-FastLogin:R1.1'
|
||||
implementation 'net.playeranalytics:Extension-Floodgate:2.0-R1.2'
|
||||
implementation 'net.playeranalytics:Extension-GriefDefender:2.1.0-R1.1'
|
||||
implementation 'net.playeranalytics:Extension-GriefPrevention:16.11.6-R1.2'
|
||||
implementation 'net.playeranalytics:Extension-GriefPrevention-Sponge:4.0.1-R1.2'
|
||||
implementation 'net.playeranalytics:Extension-Heroes:R1.2'
|
||||
implementation 'net.playeranalytics:Extension-Jobs:4.16.3-R1.1'
|
||||
implementation 'net.playeranalytics:Extension-KingdomsX:1.12.6.3.1-R1.4'
|
||||
implementation 'net.playeranalytics:Extension-Lands:5.4.12-R1.1'
|
||||
implementation 'net.playeranalytics:Extension-LibertyBans:0.8.0-R1.2'
|
||||
implementation 'net.playeranalytics:Extension-Litebans:0.3.4-R1.4'
|
||||
implementation 'net.playeranalytics:Extension-LogBlock:1.16.1.2-R1.9'
|
||||
implementation 'net.playeranalytics:Extension-LuckPerms:5.0-R1.5'
|
||||
implementation 'net.playeranalytics:Extension-MarriageMaster:2.3-R1.3'
|
||||
implementation 'net.playeranalytics:Extension-McMMO:2.1.149-R2.5'
|
||||
implementation 'net.playeranalytics:Extension-MinigamesLib:1.14.17-R1.2'
|
||||
implementation 'net.playeranalytics:Extension-MyPet:3.10-R1.2'
|
||||
// implementation 'net.playeranalytics:Extension-Nucleus:2.3.0-R1.1' // TODO Update to sponge 8
|
||||
implementation 'net.playeranalytics:Extension-nuVotifier:2.3.4-R1.3'
|
||||
implementation 'net.playeranalytics:Extension-PlaceholderAPI:2.10.9-R1.5'
|
||||
implementation 'net.playeranalytics:Extension-PlotSquared:5.13.11-R1.2'
|
||||
implementation 'net.playeranalytics:Extension-ProtectionStones:2.8.2-R1.2'
|
||||
implementation 'net.playeranalytics:Extension-ProtocolSupport:1.16.4-R1.3'
|
||||
implementation 'net.playeranalytics:Extension-Quests:4.0.5-R1.1'
|
||||
implementation 'net.playeranalytics:Extension-React:6.651-R1.1'
|
||||
// implementation 'net.playeranalytics:Extension-RedProtect:7.7.3-R1.1' // TODO Update to sponge 8
|
||||
implementation 'net.playeranalytics:Extension-Sponge-Economy:8.0.0-R1.3'
|
||||
implementation 'net.playeranalytics:Extension-SuperbVote:0.5.4-R1.1'
|
||||
implementation 'net.playeranalytics:Extension-Tebex:R2.3'
|
||||
implementation 'net.playeranalytics:Extension-Towny:0.96.7.4-R1.2'
|
||||
implementation 'net.playeranalytics:Extension-Vault:1.7-R1.3'
|
||||
implementation 'net.playeranalytics:Extension-ViaVersion:4.0.1-R1.3'
|
||||
shadow 'net.playeranalytics:Extension-AAC:4.4.2-R1.1'
|
||||
shadow 'net.playeranalytics:Extension-AdvancedAchievements:6.4.0-R1.1'
|
||||
shadow 'net.playeranalytics:Extension-AdvancedBan:2.1.5-R2.0'
|
||||
shadow 'net.playeranalytics:Extension-ASkyBlock:3.0.9.4-R1.5'
|
||||
shadow 'net.playeranalytics:Extension-AuthMe:5.6.0-R1.2'
|
||||
shadow 'net.playeranalytics:Extension-BanManager:7.3.1-R1.2'
|
||||
shadow 'net.playeranalytics:Extension-BentoBox:1.15.5-R2.0'
|
||||
// shadow 'net.playeranalytics:Extension-CoreProtect:2.16.0-R1.4' // unable to compile new version
|
||||
shadow 'net.playeranalytics:Extension-DiscordSRV:1.25.1-R1.4'
|
||||
shadow 'net.playeranalytics:Extension-DKBans:2.1.2-R1.3'
|
||||
shadow 'net.playeranalytics:Extension-DKCoins:3.0.5-R1.1'
|
||||
shadow 'net.playeranalytics:Extension-EssentialsX:2.15.0-R2.0'
|
||||
shadow 'net.playeranalytics:Extension-Factions:2.14.0-R1.1'
|
||||
shadow 'net.playeranalytics:Extension-FactionsUUID:1.6.9.5-U0.5.25-R1.1'
|
||||
shadow 'net.playeranalytics:Extension-FastLogin:R1.1'
|
||||
shadow 'net.playeranalytics:Extension-Floodgate:2.0-R1.2'
|
||||
shadow 'net.playeranalytics:Extension-GriefDefender:2.1.0-R1.1'
|
||||
shadow 'net.playeranalytics:Extension-GriefPrevention:16.11.6-R1.2'
|
||||
shadow 'net.playeranalytics:Extension-GriefPrevention-Sponge:4.0.1-R1.2'
|
||||
shadow 'net.playeranalytics:Extension-Heroes:R1.2'
|
||||
shadow 'net.playeranalytics:Extension-Jobs:4.16.3-R1.1'
|
||||
shadow 'net.playeranalytics:Extension-KingdomsX:1.12.6.3.1-R1.4'
|
||||
shadow 'net.playeranalytics:Extension-Lands:5.4.12-R1.1'
|
||||
shadow 'net.playeranalytics:Extension-LibertyBans:0.8.0-R1.2'
|
||||
shadow 'net.playeranalytics:Extension-Litebans:0.3.4-R1.4'
|
||||
shadow 'net.playeranalytics:Extension-LogBlock:1.16.1.2-R1.9'
|
||||
shadow 'net.playeranalytics:Extension-LuckPerms:5.0-R1.5'
|
||||
shadow 'net.playeranalytics:Extension-MarriageMaster:2.3-R1.3'
|
||||
shadow 'net.playeranalytics:Extension-McMMO:2.1.149-R2.5'
|
||||
shadow 'net.playeranalytics:Extension-MinigamesLib:1.14.17-R1.2'
|
||||
shadow 'net.playeranalytics:Extension-MyPet:3.10-R1.2'
|
||||
// shadow 'net.playeranalytics:Extension-Nucleus:2.3.0-R1.1' // TODO Update to sponge 8
|
||||
shadow 'net.playeranalytics:Extension-nuVotifier:2.3.4-R1.3'
|
||||
shadow 'net.playeranalytics:Extension-PlaceholderAPI:2.10.9-R1.5'
|
||||
shadow 'net.playeranalytics:Extension-PlotSquared:5.13.11-R1.2'
|
||||
shadow 'net.playeranalytics:Extension-ProtectionStones:2.8.2-R1.2'
|
||||
shadow 'net.playeranalytics:Extension-ProtocolSupport:1.16.4-R1.3'
|
||||
shadow 'net.playeranalytics:Extension-Quests:4.0.5-R1.1'
|
||||
shadow 'net.playeranalytics:Extension-React:6.651-R1.1'
|
||||
// shadow 'net.playeranalytics:Extension-RedProtect:7.7.3-R1.1' // TODO Update to sponge 8
|
||||
shadow 'net.playeranalytics:Extension-Sponge-Economy:8.0.0-R1.3'
|
||||
shadow 'net.playeranalytics:Extension-SuperbVote:0.5.4-R1.1'
|
||||
shadow 'net.playeranalytics:Extension-Tebex:R2.3'
|
||||
shadow 'net.playeranalytics:Extension-Towny:0.96.7.4-R1.2'
|
||||
shadow 'net.playeranalytics:Extension-Vault:1.7-R1.3'
|
||||
shadow 'net.playeranalytics:Extension-ViaVersion:4.0.1-R1.3'
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
dependencies {
|
||||
exclude(project(':api'))
|
||||
}
|
||||
configurations = [project.configurations.shadow]
|
||||
|
||||
// TODO Missing test scope in every Extension pom.xml causes junit to be shadowed.
|
||||
exclude 'org/junit/**/*'
|
||||
exclude 'org/opentest4j/**/*'
|
||||
}
|
||||
|
@ -1,15 +1,17 @@
|
||||
apply plugin: 'fabric-loom'
|
||||
|
||||
dependencies {
|
||||
shadow project(path: ":api")
|
||||
shadow project(path: ":extensions")
|
||||
shadow project(path: ":common")
|
||||
shadow project(path: ":common", configuration: "swaggerJson")
|
||||
|
||||
shadow "net.playeranalytics:platform-abstraction-layer-api:$palVersion"
|
||||
implementation project(path: ":common", configuration: 'shadow')
|
||||
shadow project(path: ":common", configuration: 'shadow')
|
||||
compileOnly project(":api")
|
||||
modImplementation('me.lucko:fabric-permissions-api:0.1-SNAPSHOT')
|
||||
|
||||
minecraft "com.mojang:minecraft:1.19"
|
||||
mappings "net.fabricmc:yarn:1.19+build.1:v2"
|
||||
modImplementation "net.fabricmc:fabric-loader:0.14.7"
|
||||
modImplementation('me.lucko:fabric-permissions-api:0.1-SNAPSHOT')
|
||||
|
||||
// Fabric API
|
||||
Set<String> apiModules = [
|
||||
@ -44,6 +46,22 @@ shadowJar {
|
||||
exclude('net.fabricmc:*')
|
||||
exclude('/mappings/')
|
||||
|
||||
// Exclude these files
|
||||
exclude "**/*.svg"
|
||||
exclude "**/*.psd"
|
||||
exclude "**/*.map"
|
||||
|
||||
exclude "**/module-info.class"
|
||||
exclude "module-info.class"
|
||||
exclude 'META-INF/versions/' // Causes Sponge to crash
|
||||
exclude 'mozilla/**/*'
|
||||
|
||||
// Exclude extra dependencies
|
||||
exclude 'org/apache/http/**/*' // Unnecessary http client depended on by geolite2 implementation
|
||||
exclude "org/junit/**/*" // see extensions/build.gradle
|
||||
exclude "org/opentest4j/**/*" // see extensions/build.gradle
|
||||
exclude "org/checkerframework/**/*" // Dagger compiler
|
||||
|
||||
relocate('org.apache', 'plan.org.apache') {
|
||||
exclude 'org/apache/logging/**'
|
||||
}
|
||||
@ -56,11 +74,22 @@ shadowJar {
|
||||
relocate 'com.github.benmanes', 'plan.com.github.benmanes'
|
||||
relocate 'dev.vankka.dependencydownload', 'plan.dev.vankka.dependencydownload'
|
||||
|
||||
relocate 'com.maxmind', 'plan.com.maxmind'
|
||||
relocate 'com.fasterxml', 'plan.com.fasterxml'
|
||||
relocate 'com.zaxxer', 'plan.com.zaxxer'
|
||||
relocate 'com.google.gson', 'plan.com.google.gson'
|
||||
relocate 'com.google.errorprone', 'plan.com.google.errorprone'
|
||||
relocate 'org.bstats', 'plan.org.bstats'
|
||||
|
||||
relocate 'org.eclipse.jetty', 'plan.org.eclipse.jetty'
|
||||
relocate 'jakarta.servlet', 'plan.jakarta.servlet'
|
||||
relocate 'javax.servlet', 'plan.javax.servlet'
|
||||
}
|
||||
|
||||
prepareRemapJar {
|
||||
dependsOn tasks.shadowJar
|
||||
}
|
||||
|
||||
remapJar {
|
||||
dependsOn tasks.shadowJar
|
||||
mustRunAfter tasks.shadowJar
|
||||
|
@ -1 +1 @@
|
||||
org.gradle.jvmargs=-Xmx1024m
|
||||
org.gradle.jvmargs=-Xmx2048m
|
||||
|
@ -4,18 +4,20 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly project(":common")
|
||||
implementation project(path: ":common", configuration: 'shadow')
|
||||
compileOnly project(":api")
|
||||
implementation project(":api")
|
||||
implementation project(":common")
|
||||
|
||||
shadow "net.playeranalytics:platform-abstraction-layer-api:$palVersion"
|
||||
shadow "net.playeranalytics:platform-abstraction-layer-nukkit:$palVersion"
|
||||
|
||||
implementation "net.playeranalytics:platform-abstraction-layer-nukkit:$palVersion"
|
||||
compileOnly "cn.nukkit:nukkit:$nukkitVersion"
|
||||
compileOnly "com.creeperface.nukkit.placeholderapi:PlaceholderAPI:$nkPlaceholderapiVersion"
|
||||
testImplementation "cn.nukkit:nukkit:$nukkitVersion"
|
||||
|
||||
testImplementation "cn.nukkit:nukkit:$nukkitVersion"
|
||||
testImplementation project(path: ":common", configuration: 'testArtifacts')
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
configurations = [project.configurations.shadow]
|
||||
relocate 'org.slf4j', 'plan.org.slf4j'
|
||||
}
|
@ -1,10 +1,13 @@
|
||||
dependencies {
|
||||
implementation project(path: ":common", configuration: 'shadow')
|
||||
implementation project(path: ":bukkit", configuration: 'shadow')
|
||||
implementation project(path: ":nukkit", configuration: 'shadow')
|
||||
implementation project(path: ":sponge", configuration: 'shadow')
|
||||
implementation project(path: ":bungeecord", configuration: 'shadow')
|
||||
implementation project(path: ":velocity", configuration: 'shadow')
|
||||
shadow project(path: ":api")
|
||||
shadow project(path: ":extensions")
|
||||
shadow project(path: ":common")
|
||||
shadow project(path: ":common", configuration: "swaggerJson")
|
||||
shadow project(path: ":bukkit")
|
||||
shadow project(path: ":nukkit")
|
||||
shadow project(path: ":sponge")
|
||||
shadow project(path: ":bungeecord")
|
||||
shadow project(path: ":velocity")
|
||||
testImplementation project(path: ":common", configuration: 'testArtifacts')
|
||||
testImplementation project(path: ":bukkit", configuration: 'testArtifacts')
|
||||
testImplementation project(path: ":nukkit", configuration: 'testArtifacts')
|
||||
@ -21,6 +24,38 @@ jar {
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
dependsOn processResources
|
||||
configurations = [project.configurations.shadow]
|
||||
|
||||
// Exclude these files
|
||||
exclude "**/*.svg"
|
||||
exclude "**/*.psd"
|
||||
exclude "**/*.map"
|
||||
|
||||
exclude "**/module-info.class"
|
||||
exclude "module-info.class"
|
||||
exclude 'META-INF/versions/' // Causes Sponge to crash
|
||||
exclude 'mozilla/**/*'
|
||||
|
||||
// Exclude extra dependencies
|
||||
exclude 'org/apache/http/**/*' // Unnecessary http client depended on by geolite2 implementation
|
||||
exclude "org/junit/**/*" // see extensions/build.gradle
|
||||
exclude "org/opentest4j/**/*" // see extensions/build.gradle
|
||||
exclude "org/checkerframework/**/*" // Dagger compiler
|
||||
exclude "com/google/common/**/*"
|
||||
exclude "com/google/thirdparty/**/*"
|
||||
// Exclude swagger
|
||||
exclude "org/yaml/**/*"
|
||||
exclude "nonapi/**/*"
|
||||
exclude "io/github/classgraph/**/*"
|
||||
exclude "io/swagger/**/*"
|
||||
exclude "com/sun/activation/**/*"
|
||||
exclude "jakarta/activation/**/*"
|
||||
exclude "jakarta/validation/**/*"
|
||||
exclude "jakarta/ws/**/*"
|
||||
exclude "jakarta/xml/**/*"
|
||||
exclude "javassist/**/*"
|
||||
|
||||
relocate('org.apache', 'plan.org.apache') {
|
||||
exclude 'org/apache/logging/**'
|
||||
exclude 'org/apache/maven/**' // This needs to be unrelocated for Sponge
|
||||
@ -34,6 +69,13 @@ shadowJar {
|
||||
relocate 'com.github.benmanes', 'plan.com.github.benmanes'
|
||||
relocate 'dev.vankka.dependencydownload', 'plan.dev.vankka.dependencydownload'
|
||||
|
||||
relocate 'com.maxmind', 'plan.com.maxmind'
|
||||
relocate 'com.fasterxml', 'plan.com.fasterxml'
|
||||
relocate 'com.zaxxer', 'plan.com.zaxxer'
|
||||
relocate 'com.google.gson', 'plan.com.google.gson'
|
||||
relocate 'com.google.errorprone', 'plan.com.google.errorprone'
|
||||
relocate 'org.bstats', 'plan.org.bstats'
|
||||
|
||||
relocate 'org.eclipse.jetty', 'plan.org.eclipse.jetty'
|
||||
relocate 'jakarta.servlet', 'plan.jakarta.servlet'
|
||||
relocate 'javax.servlet', 'plan.javax.servlet'
|
||||
@ -42,6 +84,8 @@ shadowJar {
|
||||
archiveBaseName.set('Plan')
|
||||
archiveClassifier.set('')
|
||||
|
||||
mergeServiceFiles()
|
||||
|
||||
build {
|
||||
dependsOn tasks.named("shadowJar")
|
||||
}
|
||||
|
@ -36,6 +36,7 @@
|
||||
"react-scripts": "5.0.1",
|
||||
"sass": "^1.53.0",
|
||||
"source-map-explorer": "^2.5.2",
|
||||
"swagger-ui": "^4.12.0",
|
||||
"web-vitals": "^2.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
|
@ -29,6 +29,8 @@ import PlayersPage from "./views/layout/PlayersPage";
|
||||
import AllPlayers from "./views/players/AllPlayers";
|
||||
import ServerGeolocations from "./views/server/ServerGeolocations";
|
||||
|
||||
const SwaggerView = React.lazy(() => import("./views/SwaggerView"));
|
||||
|
||||
const OverviewRedirect = () => {
|
||||
return (<Navigate to={"overview"} replace={true}/>)
|
||||
}
|
||||
@ -85,6 +87,9 @@ function App() {
|
||||
<Route path="performance" element={<></>}/>
|
||||
<Route path="plugins-overview" element={<></>}/>
|
||||
</Route>
|
||||
<Route path="docs" element={<React.Suspense fallback={<></>}>
|
||||
<SwaggerView/>
|
||||
</React.Suspense>}/>
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
</div>
|
||||
|
21
Plan/react/dashboard/src/views/SwaggerView.js
Normal file
21
Plan/react/dashboard/src/views/SwaggerView.js
Normal file
@ -0,0 +1,21 @@
|
||||
import React, {useEffect} from "react";
|
||||
import SwaggerUI from "swagger-ui"
|
||||
import "swagger-ui/dist/swagger-ui.css"
|
||||
|
||||
import {baseAddress} from "../service/backendConfiguration"
|
||||
|
||||
const SwaggerView = () => {
|
||||
|
||||
useEffect(() => {
|
||||
SwaggerUI({
|
||||
dom_id: "#swagger-ui",
|
||||
url: baseAddress + "/docs/swagger.json"
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<main id="swagger-ui" className="col-12"></main>
|
||||
)
|
||||
}
|
||||
|
||||
export default SwaggerView;
|
File diff suppressed because it is too large
Load Diff
@ -7,17 +7,17 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly project(":common")
|
||||
implementation project(path: ":common", configuration: 'shadow')
|
||||
compileOnly project(":api")
|
||||
implementation project(":api")
|
||||
implementation project(":common")
|
||||
|
||||
shadow "net.playeranalytics:platform-abstraction-layer-api:$palVersion"
|
||||
shadow "net.playeranalytics:platform-abstraction-layer-sponge:$palVersion"
|
||||
shadow "org.bstats:bstats-sponge:$bstatsVersion"
|
||||
|
||||
testImplementation "org.spongepowered:spongeapi:$spongeVersion"
|
||||
annotationProcessor "org.spongepowered:spongeapi:$spongeVersion"
|
||||
shadow "org.spongepowered:mixin:0.7.11-SNAPSHOT"
|
||||
|
||||
testImplementation "org.spongepowered:spongeapi:$spongeVersion"
|
||||
testImplementation project(path: ":common", configuration: 'testArtifacts')
|
||||
}
|
||||
|
||||
|
@ -8,21 +8,21 @@ blossom {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly project(":common")
|
||||
implementation project(path: ":common", configuration: 'shadow')
|
||||
compileOnly project(":api")
|
||||
implementation project(":api")
|
||||
implementation project(":common")
|
||||
|
||||
implementation "net.playeranalytics:platform-abstraction-layer-velocity:$palVersion"
|
||||
implementation "org.bstats:bstats-velocity:$bstatsVersion"
|
||||
shadow "net.playeranalytics:platform-abstraction-layer-api:$palVersion"
|
||||
shadow "net.playeranalytics:platform-abstraction-layer-velocity:$palVersion"
|
||||
shadow "org.bstats:bstats-velocity:$bstatsVersion"
|
||||
|
||||
compileOnly "com.velocitypowered:velocity-api:$velocityVersion"
|
||||
testImplementation "com.velocitypowered:velocity-api:$velocityVersion"
|
||||
|
||||
annotationProcessor "com.velocitypowered:velocity-api:$velocityVersion"
|
||||
|
||||
testImplementation "com.velocitypowered:velocity-api:$velocityVersion"
|
||||
testImplementation project(path: ":common", configuration: 'testArtifacts')
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
configurations = [project.configurations.shadow]
|
||||
relocate 'org.bstats', 'net.playeranalytics.bstats.utilities.metrics'
|
||||
}
|
Loading…
Reference in New Issue
Block a user