mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-03-09 13:19:07 +01:00
Add Swagger & Swagger UI (#2470)
* Adds swagger dependencies and annotations for json endpoints for documentation * Add swagger ui to react project * Access control to swagger endpoints * Include swagger.json in jars using custom configuration Also: * Reworked project shadow configurations to avoid shadowing shadow versions of modules Why: Extra dependencies were being included when using shadow scope What: - modules no longer depend on shadow configurations, which speeds up IDEA indexing after build considerably (No need to index *-all.jars) - 'shadow' scope is now used for artifacts that need to be included - 'shadow' scope is also 'api' so that modules that depend on common can import the libraries. This may cause issues in projects depending on Plan so this may need to be reconsidered - Relocations and exclusions were moved to plugin module org.slf4j is now included in 2 locations which may cause issues. Needs testing with servers - Found out that all Extension dependencies include junit as compile scope which caused it to be included. Affects issues: - Close #1890
This commit is contained in:
parent
547cf67021
commit
8f239b010c
@ -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 'com.djrapitops:Extension-AAC:4.4.2-R0.1'
|
||||
implementation 'com.djrapitops:Extension-AdvancedAchievements:6.4.0-R0.1'
|
||||
implementation 'com.djrapitops:Extension-AdvancedBan:2.1.5-R1.0'
|
||||
implementation 'com.djrapitops:Extension-ASkyBlock:3.0.9.4-R0.5'
|
||||
implementation 'com.djrapitops:Extension-AuthMe:5.6.0-R0.2'
|
||||
implementation 'com.djrapitops:Extension-BanManager:7.3.1-R0.2'
|
||||
implementation 'com.djrapitops:Extension-BentoBox:1.15.5-R1.0'
|
||||
implementation 'com.djrapitops:Extension-CoreProtect:2.16.0-R0.4'
|
||||
implementation 'com.djrapitops:Extension-DiscordSRV:1.18.0-R0.4'
|
||||
implementation 'com.djrapitops:Extension-DKBans:2.1.2-R0.3'
|
||||
implementation 'com.djrapitops:Extension-DKCoins:3.0.5-R0.1'
|
||||
implementation 'com.djrapitops:Extension-EssentialsX:2.15.0-R1.0'
|
||||
implementation 'com.djrapitops:Extension-Factions:2.14.0-R0.1'
|
||||
implementation 'com.djrapitops:Extension-FactionsUUID:1.6.9.5-U0.5.25-R0.1'
|
||||
implementation 'com.djrapitops:Extension-FastLogin:R0.1'
|
||||
implementation 'com.djrapitops:Extension-Floodgate:2.0-R0.2'
|
||||
implementation 'com.djrapitops:Extension-GriefDefender:2.1.0-R0.1'
|
||||
implementation 'com.djrapitops:Extension-GriefPrevention:16.11.6-R0.2'
|
||||
implementation 'com.djrapitops:Extension-GriefPrevention-Sponge:4.0.1-R0.2'
|
||||
implementation 'com.djrapitops:Extension-Heroes:R0.2'
|
||||
implementation 'com.djrapitops:Extension-Jobs:4.16.3-R0.1'
|
||||
implementation 'com.djrapitops:Extension-KingdomsX:1.12.6.3.1-R0.4'
|
||||
implementation 'com.djrapitops:Extension-Lands:5.4.12-R0.1'
|
||||
implementation 'net.playeranalytics:Extension-LibertyBans:0.8.0-R0.2'
|
||||
implementation 'com.djrapitops:Extension-Litebans:0.3.4-R0.3'
|
||||
implementation 'com.djrapitops:Extension-LogBlock:1.16.1.2-R0.9'
|
||||
implementation 'com.djrapitops:Extension-LuckPerms:5.0-R0.5'
|
||||
implementation 'com.djrapitops:Extension-MarriageMaster:2.3-R0.3'
|
||||
implementation 'com.djrapitops:Extension-McMMO:2.1.149-R1.5'
|
||||
implementation 'com.djrapitops:Extension-MinigamesLib:1.14.17-R0.2'
|
||||
implementation 'com.djrapitops:Extension-MyPet:3.10-R0.2'
|
||||
implementation 'com.djrapitops:Extension-Nucleus:2.3.0-R0.1'
|
||||
implementation 'com.djrapitops:Extension-nuVotifier:2.3.4-R0.3'
|
||||
implementation 'com.djrapitops:Extension-PlaceholderAPI:2.10.9-R0.5'
|
||||
implementation 'com.djrapitops:Extension-PlotSquared:5.13.11-R0.2'
|
||||
implementation 'com.djrapitops:Extension-ProtectionStones:2.8.2-R0.2'
|
||||
implementation 'com.djrapitops:Extension-ProtocolSupport:1.16.4-R0.3'
|
||||
implementation 'com.djrapitops:Extension-Quests:4.0.5-R0.1'
|
||||
implementation 'com.djrapitops:Extension-React:6.651-R0.1'
|
||||
implementation 'com.djrapitops:Extension-RedProtect:7.7.3-R0.1'
|
||||
implementation 'com.djrapitops:Extension-Sponge-Economy:8.0.0-R0.3'
|
||||
implementation 'com.djrapitops:Extension-SuperbVote:0.5.4-R0.1'
|
||||
implementation 'com.djrapitops:Extension-Tebex:R1.3'
|
||||
implementation 'com.djrapitops:Extension-Towny:0.96.7.4-R0.2'
|
||||
implementation 'com.djrapitops:Extension-Vault:1.7-R0.3'
|
||||
implementation 'com.djrapitops:Extension-ViaVersion:4.0.1-R0.3'
|
||||
shadow 'com.djrapitops:Extension-AAC:4.4.2-R0.1'
|
||||
shadow 'com.djrapitops:Extension-AdvancedAchievements:6.4.0-R0.1'
|
||||
shadow 'com.djrapitops:Extension-AdvancedBan:2.1.5-R1.0'
|
||||
shadow 'com.djrapitops:Extension-ASkyBlock:3.0.9.4-R0.5'
|
||||
shadow 'com.djrapitops:Extension-AuthMe:5.6.0-R0.2'
|
||||
shadow 'com.djrapitops:Extension-BanManager:7.3.1-R0.2'
|
||||
shadow 'com.djrapitops:Extension-BentoBox:1.15.5-R1.0'
|
||||
shadow 'com.djrapitops:Extension-CoreProtect:2.16.0-R0.4'
|
||||
shadow 'com.djrapitops:Extension-DiscordSRV:1.18.0-R0.4'
|
||||
shadow 'com.djrapitops:Extension-DKBans:2.1.2-R0.3'
|
||||
shadow 'com.djrapitops:Extension-DKCoins:3.0.5-R0.1'
|
||||
shadow 'com.djrapitops:Extension-EssentialsX:2.15.0-R1.0'
|
||||
shadow 'com.djrapitops:Extension-Factions:2.14.0-R0.1'
|
||||
shadow 'com.djrapitops:Extension-FactionsUUID:1.6.9.5-U0.5.25-R0.1'
|
||||
shadow 'com.djrapitops:Extension-FastLogin:R0.1'
|
||||
shadow 'com.djrapitops:Extension-Floodgate:2.0-R0.2'
|
||||
shadow 'com.djrapitops:Extension-GriefDefender:2.1.0-R0.1'
|
||||
shadow 'com.djrapitops:Extension-GriefPrevention:16.11.6-R0.2'
|
||||
shadow 'com.djrapitops:Extension-GriefPrevention-Sponge:4.0.1-R0.2'
|
||||
shadow 'com.djrapitops:Extension-Heroes:R0.2'
|
||||
shadow 'com.djrapitops:Extension-Jobs:4.16.3-R0.1'
|
||||
shadow 'com.djrapitops:Extension-KingdomsX:1.12.6.3.1-R0.4'
|
||||
shadow 'com.djrapitops:Extension-Lands:5.4.12-R0.1'
|
||||
shadow 'net.playeranalytics:Extension-LibertyBans:0.8.0-R0.2'
|
||||
shadow 'com.djrapitops:Extension-Litebans:0.3.4-R0.4'
|
||||
shadow 'com.djrapitops:Extension-LogBlock:1.16.1.2-R0.9'
|
||||
shadow 'com.djrapitops:Extension-LuckPerms:5.0-R0.5'
|
||||
shadow 'com.djrapitops:Extension-MarriageMaster:2.3-R0.3'
|
||||
shadow 'com.djrapitops:Extension-McMMO:2.1.149-R1.5'
|
||||
shadow 'com.djrapitops:Extension-MinigamesLib:1.14.17-R0.2'
|
||||
shadow 'com.djrapitops:Extension-MyPet:3.10-R0.2'
|
||||
shadow 'com.djrapitops:Extension-Nucleus:2.3.0-R0.1'
|
||||
shadow 'com.djrapitops:Extension-nuVotifier:2.3.4-R0.3'
|
||||
shadow 'com.djrapitops:Extension-PlaceholderAPI:2.10.9-R0.5'
|
||||
shadow 'com.djrapitops:Extension-PlotSquared:5.13.11-R0.2'
|
||||
shadow 'com.djrapitops:Extension-ProtectionStones:2.8.2-R0.2'
|
||||
shadow 'com.djrapitops:Extension-ProtocolSupport:1.16.4-R0.3'
|
||||
shadow 'com.djrapitops:Extension-Quests:4.0.5-R0.1'
|
||||
shadow 'com.djrapitops:Extension-React:6.651-R0.1'
|
||||
shadow 'com.djrapitops:Extension-RedProtect:7.7.3-R0.1'
|
||||
shadow 'com.djrapitops:Extension-Sponge-Economy:8.0.0-R0.3'
|
||||
shadow 'com.djrapitops:Extension-SuperbVote:0.5.4-R0.1'
|
||||
shadow 'com.djrapitops:Extension-Tebex:R1.3'
|
||||
shadow 'com.djrapitops:Extension-Towny:0.96.7.4-R0.2'
|
||||
shadow 'com.djrapitops:Extension-Vault:1.7-R0.3'
|
||||
shadow 'com.djrapitops:Extension-ViaVersion:4.0.1-R0.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
|
||||
|
@ -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