Compare commits
38 Commits
Author | SHA1 | Date |
---|---|---|
Taah | 2e40ddc6bc | |
Telesphoreo | ff9cf12acc | |
Telesphoreo | 94528860f2 | |
Telesphoreo | c83f8f1d8e | |
Focusvity | 31cd561b92 | |
Telesphoreo | f0582e03e6 | |
Telesphoreo | 4e593e1b5e | |
Telesphoreo | 026b29a98c | |
Telesphoreo | 266a8d6384 | |
Telesphoreo | 21ee54cf98 | |
Telesphoreo | 492c6bd8eb | |
Telesphoreo | a7c76e6089 | |
Telesphoreo | 7a996004f0 | |
Telesphoreo | 46ff09bf58 | |
Telesphoreo | 4426c4b4b7 | |
Telesphoreo | fc8811d453 | |
Telesphoreo | 459f62e0d3 | |
Telesphoreo | 4918cf55f3 | |
Telesphoreo | e9395e193a | |
Telesphoreo | a257fb2f9c | |
Telesphoreo | fc9924754a | |
Telesphoreo | 867e3ff79b | |
Telesphoreo | 8bef589b7a | |
Allink | 5a0ae8746c | |
Telesphoreo | 41a2475e3d | |
Telesphoreo | 0bcbc7e79c | |
Telesphoreo | 95043a33db | |
Telesphoreo | 93619dd05e | |
Taah | 244d027e5d | |
Telesphoreo | ceea975729 | |
Telesphoreo | 32f17a23f3 | |
Telesphoreo | 1148ff5da9 | |
Telesphoreo | a0ae4a9720 | |
Telesphoreo | 82238fa3ed | |
Telesphoreo | 6e152417b7 | |
Telesphoreo | 22bb27af24 | |
Telesphoreo | 2b24f0ee4c | |
Telesphoreo | 7769f34f74 |
|
@ -0,0 +1,18 @@
|
|||
name: Gradle
|
||||
|
||||
on: [ push ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 17
|
||||
cache: gradle
|
||||
- name: Build with Gradle
|
||||
run: chmod a+x gradlew && ./gradlew build --no-daemon
|
|
@ -0,0 +1,49 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Plexus Code Style" version="1">
|
||||
<JavaCodeStyleSettings>
|
||||
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="20" />
|
||||
<option name="IMPORT_LAYOUT_TABLE">
|
||||
<value>
|
||||
<package name="" withSubpackages="true" static="false" />
|
||||
<package name="" withSubpackages="true" static="true" />
|
||||
</value>
|
||||
</option>
|
||||
</JavaCodeStyleSettings>
|
||||
<JetCodeStyleSettings>
|
||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||
<value>
|
||||
<package name="java.util" alias="false" withSubpackages="false" />
|
||||
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
|
||||
<package name="io.ktor" alias="false" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="PACKAGES_IMPORT_LAYOUT">
|
||||
<value>
|
||||
<package name="" alias="false" withSubpackages="true" />
|
||||
<package name="java" alias="false" withSubpackages="true" />
|
||||
<package name="javax" alias="false" withSubpackages="true" />
|
||||
<package name="kotlin" alias="false" withSubpackages="true" />
|
||||
<package name="" alias="true" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
</JetCodeStyleSettings>
|
||||
<codeStyleSettings language="JAVA">
|
||||
<option name="BRACE_STYLE" value="2" />
|
||||
<option name="CLASS_BRACE_STYLE" value="2" />
|
||||
<option name="METHOD_BRACE_STYLE" value="2" />
|
||||
<option name="LAMBDA_BRACE_STYLE" value="2" />
|
||||
<option name="ELSE_ON_NEW_LINE" value="true" />
|
||||
<option name="WHILE_ON_NEW_LINE" value="true" />
|
||||
<option name="CATCH_ON_NEW_LINE" value="true" />
|
||||
<option name="FINALLY_ON_NEW_LINE" value="true" />
|
||||
<option name="SPACE_AFTER_TYPE_CAST" value="true" />
|
||||
<option name="IF_BRACE_FORCE" value="3" />
|
||||
<option name="DOWHILE_BRACE_FORCE" value="3" />
|
||||
<option name="WHILE_BRACE_FORCE" value="3" />
|
||||
<option name="FOR_BRACE_FORCE" value="3" />
|
||||
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="0" />
|
||||
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1" />
|
||||
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
|
@ -0,0 +1,5 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Plexus Code Style" />
|
||||
</state>
|
||||
</component>
|
|
@ -0,0 +1,24 @@
|
|||
For those who are wanting to contribute, we fully encourage doing so. There are a few rules we require following when contributing however.
|
||||
|
||||
## Steps
|
||||
1. Make an issue and get feedback. It's important to know if your idea will be accepted before writing any code.
|
||||
- If it is a feature request, describe the feature and be extremely specific.
|
||||
- If it is a bug report, ensure you include how to reproduce the bug and the expected outcome
|
||||
- If it is an enhancement, describe your proposed changes. Ensure you are extremely specific.
|
||||
2. Fork this project
|
||||
3. Create a new branch that describes the new feature, enhancement, or bug fix. For example, this is good: `feature/add-xyz`. This is bad: `fix-this-lol`.
|
||||
4. Write the code that addresses your change.
|
||||
- Keep in mind that it **must** be formatted correctly. If you are using IntelliJ, there is a `codeStyle.xml` file that tells IntelliJ how to format your code. Check this link for information on how to use the file: https://www.jetbrains.com/help/idea/configuring-code-style.html#import-export-schemes
|
||||
- If you are not using IntelliJ, that is fine. We use the Plexus Code Style (which is almost the same as Allman) so please format your code accordingly.
|
||||
6. Push your changes to your new branch and make a PR based off of that branch.
|
||||
|
||||
## Requirements for a PR
|
||||
- The issue must be marked as approved
|
||||
- It must only address each specific issue. Don't make one PR for multiple issues.
|
||||
- Your PR must compile and work. If it does not compile or work, your PR will most likely be rejected.
|
||||
|
||||
## Code requirements
|
||||
- Most importantly, your code must be efficient. Your pull request may be rejected if your code is deemed inefficient or sloppy.
|
||||
- Do not repeat yourself. Create functions as needed if you're using large blocks of code over and over again.
|
||||
- Do not use an excessive amount of commits when making your PR. It makes the master branch look messy.
|
||||
- Your code must be consistent with Plex's codebase. If a function already exists, use it.
|
|
@ -1,2 +1,2 @@
|
|||
# Module-HTTPD
|
||||
# Module-HTTPD [![Build Status](https://ci.plex.us.org/job/Module-HTTPD/badge/icon)](https://ci.plex.us.org/job/Module-HTTPD/)
|
||||
The HTTPD module for Plex
|
||||
|
|
|
@ -5,71 +5,75 @@ plugins {
|
|||
}
|
||||
|
||||
group = "dev.plex"
|
||||
version = "1.0.2"
|
||||
version = "1.4-SNAPSHOT"
|
||||
description = "Module-HTTPD"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
||||
maven {
|
||||
url = uri("https://papermc.io/repo/repository/maven-public/")
|
||||
url = uri("https://repo.papermc.io/repository/maven-public/")
|
||||
}
|
||||
|
||||
maven {
|
||||
url = uri("https://nexus.telesphoreo.me/repository/plex/")
|
||||
}
|
||||
|
||||
maven {
|
||||
url = uri("https://nexus.telesphoreo.me/repository/totalfreedom/")
|
||||
}
|
||||
maven {
|
||||
url = uri("https://jitpack.io")
|
||||
content {
|
||||
includeGroup("com.github.MilkBowl")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("org.projectlombok:lombok:1.18.22")
|
||||
annotationProcessor("org.projectlombok:lombok:1.18.22")
|
||||
implementation("io.papermc.paper:paper-api:1.18.2-R0.1-SNAPSHOT")
|
||||
implementation("dev.plex:Plex:1.0.2-SNAPSHOT")
|
||||
implementation("org.json:json:20220320")
|
||||
implementation("org.projectlombok:lombok:1.18.30")
|
||||
annotationProcessor("org.projectlombok:lombok:1.18.30")
|
||||
implementation("io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT")
|
||||
implementation("dev.plex:server:1.4-SNAPSHOT")
|
||||
implementation("org.json:json:20231013")
|
||||
implementation("org.reflections:reflections:0.10.2")
|
||||
implementation("org.eclipse.jetty:jetty-server:11.0.9")
|
||||
implementation("org.eclipse.jetty:jetty-servlet:11.0.9")
|
||||
implementation("org.eclipse.jetty:jetty-proxy:11.0.9")
|
||||
implementation("com.github.MilkBowl:VaultAPI:1.7")
|
||||
implementation("org.eclipse.jetty:jetty-server:11.0.19")
|
||||
implementation("org.eclipse.jetty:jetty-servlet:11.0.19")
|
||||
implementation("org.eclipse.jetty:jetty-proxy:11.0.19")
|
||||
implementation("com.github.MilkBowl:VaultAPI:1.7.1") {
|
||||
exclude("org.bukkit", "bukkit")
|
||||
}
|
||||
implementation(platform("com.intellectualsites.bom:bom-newest:1.40")) // Ref: https://github.com/IntellectualSites/bom
|
||||
compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Core")
|
||||
implementation("commons-io:commons-io:2.15.1")
|
||||
}
|
||||
|
||||
tasks.getByName<Jar>("jar") {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
archiveBaseName.set("Module-HTTPD")
|
||||
archiveVersion.set("")
|
||||
from("src/main/resources") {
|
||||
exclude("dev/**")
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
|
||||
}
|
||||
|
||||
tasks {
|
||||
compileJava {
|
||||
options.encoding = Charsets.UTF_8.name() // We want UTF-8 for everything
|
||||
|
||||
// Set the release flag. This configures what version bytecode the compiler will emit, as well as what JDK APIs are usable.
|
||||
// See https://openjdk.java.net/jeps/247 for more information.
|
||||
options.release.set(17)
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
}
|
||||
javadoc {
|
||||
options.encoding = Charsets.UTF_8.name() // We want UTF-8 for everything
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
}
|
||||
processResources {
|
||||
filteringCharset = Charsets.UTF_8.name() // We want UTF-8 for everything
|
||||
filteringCharset = Charsets.UTF_8.name()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create<MavenPublication>("maven") {
|
||||
from(components["java"])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.getByName<Jar>("jar") {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
archiveBaseName.set("Plex-HTTPD")
|
||||
archiveVersion.set("")
|
||||
from("src/main/resources") {
|
||||
exclude("dev/**")
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -1,5 +1,7 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
|
@ -80,13 +80,11 @@ do
|
|||
esac
|
||||
done
|
||||
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
APP_NAME="Gradle"
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
@ -133,22 +131,29 @@ location of your Java installation."
|
|||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
|
@ -193,6 +198,10 @@ if "$cygwin" || "$msys" ; then
|
|||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
|
@ -205,6 +214,12 @@ set -- \
|
|||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
|
@ -25,7 +25,8 @@
|
|||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
|
@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
|||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package dev.plex;
|
||||
|
||||
import dev.plex.authentication.AuthenticationManager;
|
||||
import dev.plex.cache.FileCache;
|
||||
import dev.plex.config.ModuleConfig;
|
||||
import dev.plex.module.PlexModule;
|
||||
|
@ -7,25 +8,19 @@ import dev.plex.request.AbstractServlet;
|
|||
import dev.plex.request.SchematicUploadServlet;
|
||||
import dev.plex.request.impl.*;
|
||||
import dev.plex.util.PlexLog;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import jakarta.servlet.MultipartConfigElement;
|
||||
import lombok.Getter;
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.server.*;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class HTTPDModule extends PlexModule
|
||||
{
|
||||
public static ServletContextHandler context;
|
||||
|
@ -41,6 +36,8 @@ public class HTTPDModule extends PlexModule
|
|||
|
||||
public static final String template = AbstractServlet.readFileReal(HTTPDModule.class.getResourceAsStream("/httpd/template.html"));
|
||||
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
||||
@Override
|
||||
public void load()
|
||||
{
|
||||
|
@ -53,10 +50,22 @@ public class HTTPDModule extends PlexModule
|
|||
{
|
||||
moduleConfig.load();
|
||||
PlexLog.debug("HTTPD Module Port: {0}", moduleConfig.getInt("server.port"));
|
||||
if (!setupPermissions() && getPlex().getSystem().equalsIgnoreCase("permissions") && !Bukkit.getPluginManager().isPluginEnabled("Vault"))
|
||||
if ((!Bukkit.getPluginManager().isPluginEnabled("Vault") || !setupPermissions()))
|
||||
{
|
||||
throw new RuntimeException("Plex-HTTPD requires the 'Vault' plugin as well as a Permissions plugin that hooks into 'Vault'. We recommend LuckPerms!");
|
||||
}
|
||||
|
||||
this.authenticationManager = new AuthenticationManager();
|
||||
if (this.authenticationManager.provider() != null)
|
||||
{
|
||||
PlexLog.debug(this.authenticationManager.provider().generateLogin());
|
||||
}
|
||||
else
|
||||
{
|
||||
PlexLog.debug("Provider was not found for Authentication so disabled");
|
||||
}
|
||||
|
||||
|
||||
serverThread = new Thread(() ->
|
||||
{
|
||||
Server server = new Server();
|
||||
|
@ -70,18 +79,21 @@ public class HTTPDModule extends PlexModule
|
|||
connector.setHost(moduleConfig.getString("server.bind-address"));
|
||||
connector.setPort(moduleConfig.getInt("server.port"));
|
||||
|
||||
new AdminsEndpoint();
|
||||
new IndefBansEndpoint();
|
||||
new IndexEndpoint();
|
||||
new ListEndpoint();
|
||||
new PunishmentsEndpoint();
|
||||
new CommandsEndpoint();
|
||||
new SchematicDownloadEndpoint();
|
||||
new SchematicUploadEndpoint();
|
||||
|
||||
ServletHolder uploadHolder = HTTPDModule.context.addServlet(SchematicUploadServlet.class, "/api/schematics/uploading");
|
||||
|
||||
File uploadLoc = new File(System.getProperty("java.io.tmpdir"), "schematic-temp-dir");
|
||||
if (!uploadLoc.exists()) uploadLoc.mkdirs();
|
||||
if (!uploadLoc.exists())
|
||||
{
|
||||
uploadLoc.mkdirs();
|
||||
}
|
||||
uploadHolder.getRegistration().setMultipartConfig(new MultipartConfigElement(uploadLoc.getAbsolutePath(), 1024 * 1024 * 5, 1024 * 1024 * 25, 1024 * 1024));
|
||||
|
||||
server.setConnectors(new Connector[]{connector});
|
||||
|
@ -140,7 +152,7 @@ public class HTTPDModule extends PlexModule
|
|||
}
|
||||
}
|
||||
|
||||
private static boolean isFileSystemCaseSensitive = !new File( "a" ).equals( new File( "A" ) );
|
||||
private static boolean isFileSystemCaseSensitive = !new File("a").equals(new File("A"));
|
||||
|
||||
public static boolean fileNameEquals(String filename1, String filename2)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package dev.plex.authentication;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Taah
|
||||
* @since 6:37 PM [03-05-2024]
|
||||
*/
|
||||
|
||||
@Data
|
||||
@Accessors(fluent = true)
|
||||
public class AuthenticatedUser
|
||||
{
|
||||
private final String ip;
|
||||
private final ZonedDateTime lastAuthenticated;
|
||||
private final LinkedList<String> roles = Lists.newLinkedList();
|
||||
private final UserType userType = UserType.UNKNOWN;
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package dev.plex.authentication;
|
||||
|
||||
import dev.plex.HTTPDModule;
|
||||
import dev.plex.authentication.impl.DiscordOAuth2Provider;
|
||||
import dev.plex.util.PlexLog;
|
||||
import org.apache.commons.lang3.NotImplementedException;
|
||||
|
||||
/**
|
||||
* @author Taah
|
||||
* @since 7:08 PM [03-05-2024]
|
||||
*/
|
||||
public class AuthenticationManager
|
||||
{
|
||||
private final OAuth2Provider provider;
|
||||
|
||||
public AuthenticationManager()
|
||||
{
|
||||
final boolean enabled = HTTPDModule.moduleConfig.getBoolean("authentication.enabled", false);
|
||||
if (!enabled)
|
||||
{
|
||||
provider = null;
|
||||
return;
|
||||
}
|
||||
|
||||
PlexLog.debug("[HTTPD] Auth is enabled");
|
||||
|
||||
final String providerName = HTTPDModule.moduleConfig.getString("authentication.provider.name", "");
|
||||
if (providerName.isEmpty())
|
||||
{
|
||||
PlexLog.error("OAuth2 Authentication is enabled but no provider was given!");
|
||||
provider = null;
|
||||
return;
|
||||
}
|
||||
|
||||
PlexLog.debug("[HTTPD] Provider name is {0}", providerName);
|
||||
|
||||
switch (providerName.toLowerCase())
|
||||
{
|
||||
case "discord" -> {
|
||||
provider = new DiscordOAuth2Provider();
|
||||
}
|
||||
case "xenforo" -> {
|
||||
throw new NotImplementedException("XenForo OAuth2 is not implemented yet!");
|
||||
}
|
||||
default -> {
|
||||
provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
PlexLog.log("Using {0} provider for authentication", providerName);
|
||||
}
|
||||
|
||||
public OAuth2Provider provider()
|
||||
{
|
||||
return this.provider;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package dev.plex.authentication;
|
||||
|
||||
import org.eclipse.jetty.server.Response;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @author Taah
|
||||
* @since 6:36 PM [03-05-2024]
|
||||
*/
|
||||
public interface OAuth2Provider
|
||||
{
|
||||
HashMap<String, AuthenticatedUser> sessions();
|
||||
|
||||
AuthenticatedUser login(Response response, UserType type);
|
||||
|
||||
String[] roles(AuthenticatedUser user);
|
||||
|
||||
String generateLogin();
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package dev.plex.authentication;
|
||||
|
||||
/**
|
||||
* @author Taah
|
||||
* @since 6:37 PM [03-05-2024]
|
||||
*/
|
||||
public enum UserType
|
||||
{
|
||||
DISCORD, UNKNOWN
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package dev.plex.authentication.impl;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import dev.plex.HTTPDModule;
|
||||
import dev.plex.authentication.AuthenticatedUser;
|
||||
import dev.plex.authentication.OAuth2Provider;
|
||||
import dev.plex.authentication.UserType;
|
||||
import dev.plex.util.PlexLog;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.server.Response;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @author Taah
|
||||
* @since 6:41 PM [03-05-2024]
|
||||
*/
|
||||
public class DiscordOAuth2Provider implements OAuth2Provider
|
||||
{
|
||||
private final HashMap<String, AuthenticatedUser> sessions = Maps.newHashMap();
|
||||
|
||||
private final String token;
|
||||
private final String clientId;
|
||||
private final String redirectUri;
|
||||
|
||||
public DiscordOAuth2Provider()
|
||||
{
|
||||
token = System.getenv("BOT_TOKEN").isEmpty() ? HTTPDModule.moduleConfig.getString("authentication.provider.discord.token", System.getProperty("BOT_TOKEN", "")) : System.getenv("BOT_TOKEN");
|
||||
clientId = HTTPDModule.moduleConfig.getString("authentication.provider.discord.clientId", "");
|
||||
redirectUri = URLEncoder.encode(HTTPDModule.moduleConfig.getString("authentication.provider.redirectUri", ""), StandardCharsets.UTF_8);
|
||||
|
||||
PlexLog.debug("[HTTPD] Client ID: {0}, Redirect URL: {1}", clientId, redirectUri);
|
||||
|
||||
if (redirectUri.isEmpty())
|
||||
{
|
||||
PlexLog.error("Provided authentication redirect url was empty for HTTPD!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (token.isEmpty())
|
||||
{
|
||||
PlexLog.error("Provided discord authentication token was empty for HTTPD!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (clientId.isEmpty())
|
||||
{
|
||||
PlexLog.error("Provided discord client ID was empty for HTTPD!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<String, AuthenticatedUser> sessions()
|
||||
{
|
||||
return sessions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthenticatedUser login(Response response, UserType type)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] roles(AuthenticatedUser user)
|
||||
{
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateLogin()
|
||||
{
|
||||
return String.format("https://discord.com/oauth2/authorize?client_id=%s&scope=%s&redirect_uri=%s",
|
||||
clientId,
|
||||
"identify%20guilds%20guilds.members.read",
|
||||
redirectUri);
|
||||
}
|
||||
}
|
|
@ -98,6 +98,7 @@ public class AbstractServlet extends HttpServlet
|
|||
base = base.replace("${ACTIVE_ADMINS}", "");
|
||||
base = base.replace("${ACTIVE_INDEFBANS}", "");
|
||||
base = base.replace("${ACTIVE_LIST}", "");
|
||||
base = base.replace("${ACTIVE_COMMANDS}", "");
|
||||
base = base.replace("${ACTIVE_PUNISHMENTS}", "");
|
||||
base = base.replace("${ACTIVE_SCHEMATICS}", "");
|
||||
base = base.replace("${CONTENT}", info[2]);
|
||||
|
|
|
@ -1,26 +1,27 @@
|
|||
package dev.plex.request;
|
||||
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
|
||||
import dev.plex.HTTPDModule;
|
||||
import dev.plex.Plex;
|
||||
import dev.plex.cache.DataUtils;
|
||||
import dev.plex.player.PlexPlayer;
|
||||
import dev.plex.rank.enums.Rank;
|
||||
import dev.plex.util.PlexLog;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.Part;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Arrays;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class SchematicUploadServlet extends HttpServlet
|
||||
{
|
||||
private static final Pattern schemNameMatcher = Pattern.compile("^[a-z0-9'!,_ -]{1,30}\\.schem(atic)?$", Pattern.CASE_INSENSITIVE);
|
||||
|
@ -39,24 +40,12 @@ public class SchematicUploadServlet extends HttpServlet
|
|||
response.getWriter().println(schematicUploadBadHTML("Couldn't load your IP Address: " + request.getRemoteAddr() + ". Have you joined the server before?"));
|
||||
return;
|
||||
}
|
||||
if (Plex.get().getSystem().equalsIgnoreCase("ranks"))
|
||||
PlexLog.debug("Plex-HTTPD using permissions check");
|
||||
final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(plexPlayer.getUuid());
|
||||
if (!HTTPDModule.getPermissions().playerHas(null, offlinePlayer, "plex.httpd.schematics.upload"))
|
||||
{
|
||||
PlexLog.debug("Plex-HTTPD using ranks check");
|
||||
if (!plexPlayer.getRankFromString().isAtLeast(Rank.ADMIN))
|
||||
{
|
||||
response.getWriter().println(schematicUploadBadHTML("You must be an admin or above to upload schematics."));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (Plex.get().getSystem().equalsIgnoreCase("permissions"))
|
||||
{
|
||||
PlexLog.debug("Plex-HTTPD using permissions check");
|
||||
final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(plexPlayer.getUuid());
|
||||
if (!HTTPDModule.getPermissions().playerHas(null, offlinePlayer, "plex.httpd.schematics.upload"))
|
||||
{
|
||||
response.getWriter().println(schematicUploadBadHTML("You do not have permission to upload schematics."));
|
||||
return;
|
||||
}
|
||||
response.getWriter().println(schematicUploadBadHTML("You do not have permission to upload schematics."));
|
||||
return;
|
||||
}
|
||||
File worldeditFolder = HTTPDModule.getWorldeditFolder();
|
||||
if (worldeditFolder == null)
|
||||
|
@ -88,9 +77,31 @@ public class SchematicUploadServlet extends HttpServlet
|
|||
return;
|
||||
}
|
||||
InputStream inputStream = uploadPart.getInputStream();
|
||||
Files.copy(inputStream, new File(worldeditFolder, filename).toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
File schematicFile = new File(worldeditFolder, filename);
|
||||
FileUtils.copyInputStreamToFile(inputStream, schematicFile);
|
||||
ClipboardFormat schematicFormat = ClipboardFormats.findByFile(schematicFile);
|
||||
if (schematicFormat == null)
|
||||
{
|
||||
PlexLog.log("IP Address: " + request.getRemoteAddr() + " FAILED to upload schematic with filename: " + filename);
|
||||
response.getWriter().println(schematicUploadBadHTML("Schematic is not a valid format."));
|
||||
FileUtils.deleteQuietly(schematicFile);
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
schematicFormat.getReader(new FileInputStream(schematicFile));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
PlexLog.log("IP Address: " + request.getRemoteAddr() + " FAILED to upload schematic with filename: " + filename);
|
||||
response.getWriter().println(schematicUploadBadHTML("Schematic is not a valid format."));
|
||||
FileUtils.deleteQuietly(schematicFile);
|
||||
return;
|
||||
}
|
||||
// Files.copy(inputStream, schematic.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
inputStream.close();
|
||||
response.getWriter().println(schematicUploadGoodHTML("Successfully uploaded <b>" + filename + "."));
|
||||
response.getWriter().println(schematicUploadGoodHTML("Successfully uploaded <b>" + filename + "</b>."));
|
||||
PlexLog.log("IP Address: " + request.getRemoteAddr() + " uploaded schematic with filename: " + filename);
|
||||
}
|
||||
|
||||
private String schematicUploadBadHTML(String message)
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
package dev.plex.request.impl;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import dev.plex.HTTPDModule;
|
||||
import dev.plex.Plex;
|
||||
import dev.plex.cache.DataUtils;
|
||||
import dev.plex.player.PlexPlayer;
|
||||
import dev.plex.rank.enums.Rank;
|
||||
import dev.plex.request.AbstractServlet;
|
||||
import dev.plex.request.GetMapping;
|
||||
import dev.plex.util.PlexLog;
|
||||
import dev.plex.util.adapter.ZonedDateTimeSerializer;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
public class AdminsEndpoint extends AbstractServlet
|
||||
{
|
||||
private static final String TITLE = "Admins - Plex HTTPD";
|
||||
|
||||
@GetMapping(endpoint = "/api/admins/")
|
||||
public String getAdmins(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
String ipAddress = request.getRemoteAddr();
|
||||
if (ipAddress == null)
|
||||
{
|
||||
return adminsHTML("An IP address could not be detected. Please ensure you are connecting using IPv4.");
|
||||
}
|
||||
final PlexPlayer player = DataUtils.getPlayerByIP(ipAddress);
|
||||
if (player == null)
|
||||
{
|
||||
// This likely means they've never joined the server before. That's okay. We can just not return IPs.
|
||||
return new GsonBuilder().registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeSerializer()).setPrettyPrinting().create().toJson(Plex.get().getAdminList().getAllAdminPlayers().stream().peek(plexPlayer -> plexPlayer.setIps(Lists.newArrayList())).peek(plexPlayer -> plexPlayer.setPunishments(Lists.newArrayList())).collect(Collectors.toList()));
|
||||
}
|
||||
if (Plex.get().getSystem().equalsIgnoreCase("ranks"))
|
||||
{
|
||||
PlexLog.debug("Plex-HTTPD using ranks check");
|
||||
if (!player.getRankFromString().isAtLeast(Rank.ADMIN))
|
||||
{
|
||||
// Don't return IPs either if the person is not an Admin or above.
|
||||
return new GsonBuilder().registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeSerializer()).setPrettyPrinting().create().toJson(Plex.get().getAdminList().getAllAdminPlayers().stream().peek(plexPlayer -> plexPlayer.setIps(Lists.newArrayList())).peek(plexPlayer -> plexPlayer.setPunishments(Lists.newArrayList())).collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
else if (Plex.get().getSystem().equalsIgnoreCase("permissions"))
|
||||
{
|
||||
PlexLog.debug("Plex-HTTPD using permissions check");
|
||||
final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(player.getUuid());
|
||||
if (!HTTPDModule.getPermissions().playerHas(null, offlinePlayer, "plex.httpd.admins.access"))
|
||||
{
|
||||
// If the person doesn't have permission, don't return IPs
|
||||
return new GsonBuilder().registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeSerializer()).setPrettyPrinting().create().toJson(Plex.get().getAdminList().getAllAdminPlayers().stream().peek(plexPlayer -> plexPlayer.setIps(Lists.newArrayList())).peek(plexPlayer -> plexPlayer.setPunishments(Lists.newArrayList())).collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
return new GsonBuilder().registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeSerializer()).setPrettyPrinting().create().toJson(Plex.get().getAdminList().getAllAdminPlayers());
|
||||
}
|
||||
|
||||
private String adminsHTML(String message)
|
||||
{
|
||||
String file = readFile(this.getClass().getResourceAsStream("/httpd/admins.html"));
|
||||
file = file.replace("${MESSAGE}", message);
|
||||
return file;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package dev.plex.request.impl;
|
||||
|
||||
import dev.plex.command.PlexCommand;
|
||||
import dev.plex.command.annotation.CommandPermissions;
|
||||
import dev.plex.request.AbstractServlet;
|
||||
import dev.plex.request.GetMapping;
|
||||
import dev.plex.util.PlexLog;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandMap;
|
||||
import org.bukkit.command.PluginIdentifiableCommand;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class AuthenticationEndpoint extends AbstractServlet
|
||||
{
|
||||
|
||||
|
||||
@GetMapping(endpoint = "/oauth2")
|
||||
public String login(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
// TODO: Nuh uh
|
||||
return "";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package dev.plex.request.impl;
|
||||
|
||||
import dev.plex.command.PlexCommand;
|
||||
import dev.plex.command.annotation.CommandPermissions;
|
||||
import dev.plex.request.AbstractServlet;
|
||||
import dev.plex.request.GetMapping;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandMap;
|
||||
import org.bukkit.command.PluginIdentifiableCommand;
|
||||
|
||||
public class CommandsEndpoint extends AbstractServlet
|
||||
{
|
||||
|
||||
private final StringBuilder list = new StringBuilder();
|
||||
private boolean loadedCommands = false;
|
||||
|
||||
@GetMapping(endpoint = "/api/commands/")
|
||||
public String getCommands(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
if (!loadedCommands)
|
||||
{
|
||||
final SortedMap<String, List<Command>> commandMap = new TreeMap<>();
|
||||
final CommandMap map = Bukkit.getCommandMap();
|
||||
for (Command command : map.getKnownCommands().values())
|
||||
{
|
||||
String plugin = "Bukkit";
|
||||
if (command instanceof PluginIdentifiableCommand)
|
||||
{
|
||||
plugin = ((PluginIdentifiableCommand) command).getPlugin().getName();
|
||||
}
|
||||
|
||||
List<Command> pluginCommands = commandMap.computeIfAbsent(plugin, k -> new ArrayList<>());
|
||||
if (!pluginCommands.contains(command))
|
||||
{
|
||||
pluginCommands.add(command);
|
||||
}
|
||||
}
|
||||
|
||||
for (String key : commandMap.keySet())
|
||||
{
|
||||
commandMap.get(key).sort(Comparator.comparing(Command::getName));
|
||||
StringBuilder rows = new StringBuilder();
|
||||
for (Command command : commandMap.get(key))
|
||||
{
|
||||
String permission = command.getPermission();
|
||||
if (command instanceof PlexCommand plexCmd)
|
||||
{
|
||||
CommandPermissions perms = plexCmd.getClass().getAnnotation(CommandPermissions.class);
|
||||
if (perms != null)
|
||||
{
|
||||
permission = (perms.permission().isBlank() ? "N/A" : perms.permission());
|
||||
}
|
||||
}
|
||||
|
||||
rows.append(createRow(command.getName(), command.getAliases(), command.getDescription(), command.getUsage(), permission));
|
||||
}
|
||||
|
||||
list.append(createTable(key, rows.toString())).append("\n");
|
||||
}
|
||||
|
||||
loadedCommands = true;
|
||||
}
|
||||
|
||||
return commandsHTML(list.toString());
|
||||
}
|
||||
|
||||
private String commandsHTML(String commandsList)
|
||||
{
|
||||
String file = readFile(this.getClass().getResourceAsStream("/httpd/commands.html"));
|
||||
file = file.replace("${commands}", commandsList);
|
||||
return file;
|
||||
}
|
||||
|
||||
private String createTable(String pluginName, String commandRows)
|
||||
{
|
||||
return "<details id=\"" + pluginName + "\"><summary>" + pluginName + "</summary>\n"
|
||||
+ "<table id=\"" + pluginName + "Table\" class=\"table table-striped table-bordered\">\n"
|
||||
+ " <thead>\n <tr>\n <th scope=\"col\">Name (Aliases)</th>\n "
|
||||
+ "<th scope=\"col\">Description</th>\n "
|
||||
+ "<th scope=\"col\">Usage</th>\n "
|
||||
+ "<th scope=\"col\">Permission</th>\n </tr>\n</thead>\n"
|
||||
+ "<tbody>\n " + commandRows + "\n</tbody>\n</table>\n</details>";
|
||||
}
|
||||
|
||||
private String createRow(String name, List<String> aliases, String description, String usage, String permission)
|
||||
{
|
||||
return " <tr>\n <th scope=\"row\">" + name
|
||||
+ (aliases.isEmpty() || aliases.toString().equals("[]") ? "" : " (" + String.join(", ", aliases) + ")") + "</th>\n"
|
||||
+ " <th scope=\"row\">" + description + "</th>\n"
|
||||
+ " <th scope=\"row\"><code>" + cleanUsage(usage) + "</code></th>\n"
|
||||
+ " <th scope=\"row\">" + (permission != null ? permission.replaceAll(";", "<br>") : "N/A") + "</th>\n </tr>";
|
||||
}
|
||||
|
||||
private String cleanUsage(String usage)
|
||||
{
|
||||
usage = usage.replaceAll("<", "<").replaceAll(">", ">");
|
||||
if (usage.isBlank())
|
||||
{
|
||||
usage = "Not Provided";
|
||||
}
|
||||
return usage.startsWith("/") || usage.equals("Not Provided") ? usage : "/" + usage;
|
||||
}
|
||||
}
|
|
@ -5,7 +5,6 @@ import dev.plex.HTTPDModule;
|
|||
import dev.plex.Plex;
|
||||
import dev.plex.cache.DataUtils;
|
||||
import dev.plex.player.PlexPlayer;
|
||||
import dev.plex.rank.enums.Rank;
|
||||
import dev.plex.request.AbstractServlet;
|
||||
import dev.plex.request.GetMapping;
|
||||
import dev.plex.util.PlexLog;
|
||||
|
@ -31,23 +30,14 @@ public class IndefBansEndpoint extends AbstractServlet
|
|||
{
|
||||
return indefbansHTML("Couldn't load your IP Address: " + ipAddress + ". Have you joined the server before?");
|
||||
}
|
||||
if (Plex.get().getSystem().equalsIgnoreCase("ranks"))
|
||||
PlexLog.debug("Plex-HTTPD using permissions check");
|
||||
final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(player.getUuid());
|
||||
if (!HTTPDModule.getPermissions().playerHas(null, offlinePlayer, "plex.httpd.indefbans.access"))
|
||||
{
|
||||
PlexLog.debug("Plex-HTTPD using ranks check");
|
||||
if (!player.getRankFromString().isAtLeast(Rank.ADMIN))
|
||||
{
|
||||
return indefbansHTML("Not a high enough rank to view this page.");
|
||||
}
|
||||
}
|
||||
else if (Plex.get().getSystem().equalsIgnoreCase("permissions"))
|
||||
{
|
||||
PlexLog.debug("Plex-HTTPD using permissions check");
|
||||
final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(player.getUuid());
|
||||
if (!HTTPDModule.getPermissions().playerHas(null, offlinePlayer, "plex.httpd.indefbans.access"))
|
||||
{
|
||||
return indefbansHTML("Not enough permissions to view this page.");
|
||||
}
|
||||
return indefbansHTML("Not enough permissions to view this page.");
|
||||
}
|
||||
|
||||
response.setHeader("content-type", "application/json");
|
||||
return new GsonBuilder().setPrettyPrinting().create().toJson(Plex.get().getPunishmentManager().getIndefiniteBans().stream().toList());
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package dev.plex.request.impl;
|
|||
import com.google.gson.GsonBuilder;
|
||||
import dev.plex.request.AbstractServlet;
|
||||
import dev.plex.request.GetMapping;
|
||||
import dev.plex.request.MappingHeaders;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -14,6 +15,7 @@ import org.bukkit.entity.Player;
|
|||
public class ListEndpoint extends AbstractServlet
|
||||
{
|
||||
@GetMapping(endpoint = "/api/list/")
|
||||
@MappingHeaders(headers = "content-type;application/json")
|
||||
public String getOnlinePlayers(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
List<String> players = new ArrayList<>();
|
||||
|
|
|
@ -2,20 +2,15 @@ package dev.plex.request.impl;
|
|||
|
||||
import com.google.gson.GsonBuilder;
|
||||
import dev.plex.HTTPDModule;
|
||||
import dev.plex.Plex;
|
||||
import dev.plex.cache.DataUtils;
|
||||
import dev.plex.player.PlexPlayer;
|
||||
import dev.plex.rank.enums.Rank;
|
||||
import dev.plex.request.AbstractServlet;
|
||||
import dev.plex.request.GetMapping;
|
||||
import dev.plex.util.PlexLog;
|
||||
import dev.plex.util.adapter.ZonedDateTimeSerializer;
|
||||
import dev.plex.util.adapter.ZonedDateTimeAdapter;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.time.LocalDateTime;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
|
@ -59,28 +54,17 @@ public class PunishmentsEndpoint extends AbstractServlet
|
|||
if (player == null)
|
||||
{
|
||||
// If the player is null, give it to them without the IPs
|
||||
return new GsonBuilder().registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeSerializer()).setPrettyPrinting().create().toJson(punishedPlayer.getPunishments().stream().peek(punishment -> punishment.setIp("")).toList());
|
||||
return new GsonBuilder().registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeAdapter()).setPrettyPrinting().create().toJson(punishedPlayer.getPunishments().stream().peek(punishment -> punishment.setIp("")).toList());
|
||||
}
|
||||
if (Plex.get().getSystem().equalsIgnoreCase("ranks"))
|
||||
final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(player.getUuid());
|
||||
if (!HTTPDModule.getPermissions().playerHas(null, offlinePlayer, "plex.httpd.punishments.access"))
|
||||
{
|
||||
PlexLog.debug("Plex-HTTPD using ranks check");
|
||||
if (!player.getRankFromString().isAtLeast(Rank.ADMIN))
|
||||
{
|
||||
// Don't return IPs either if the person is not an Admin or above.
|
||||
return new GsonBuilder().registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeSerializer()).setPrettyPrinting().create().toJson(punishedPlayer.getPunishments().stream().peek(punishment -> punishment.setIp("")).toList());
|
||||
}
|
||||
// If the person doesn't have permission, don't return IPs
|
||||
return new GsonBuilder().registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeAdapter()).setPrettyPrinting().create().toJson(punishedPlayer.getPunishments().stream().peek(punishment -> punishment.setIp("")).toList());
|
||||
}
|
||||
else if (Plex.get().getSystem().equalsIgnoreCase("permissions"))
|
||||
{
|
||||
PlexLog.debug("Plex-HTTPD using permissions check");
|
||||
final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(player.getUuid());
|
||||
if (!HTTPDModule.getPermissions().playerHas(null, offlinePlayer, "plex.httpd.punishments.access"))
|
||||
{
|
||||
// If the person doesn't have permission, don't return IPs
|
||||
return new GsonBuilder().registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeSerializer()).setPrettyPrinting().create().toJson(punishedPlayer.getPunishments().stream().peek(punishment -> punishment.setIp("")).toList());
|
||||
}
|
||||
}
|
||||
return new GsonBuilder().registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeSerializer()).setPrettyPrinting().create().toJson(punishedPlayer.getPunishments().stream().toList());
|
||||
|
||||
response.setHeader("content-type", "application/json");
|
||||
return new GsonBuilder().registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeAdapter()).setPrettyPrinting().create().toJson(punishedPlayer.getPunishments().stream().toList());
|
||||
}
|
||||
|
||||
private String punishmentsHTML(String message)
|
||||
|
|
|
@ -3,15 +3,21 @@ package dev.plex.request.impl;
|
|||
import dev.plex.HTTPDModule;
|
||||
import dev.plex.request.AbstractServlet;
|
||||
import dev.plex.request.GetMapping;
|
||||
import dev.plex.util.PlexLog;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class SchematicDownloadEndpoint extends AbstractServlet
|
||||
{
|
||||
List<File> files = new ArrayList<>();
|
||||
|
||||
@GetMapping(endpoint = "/api/schematics/download/")
|
||||
public String downloadSchematic(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
|
@ -72,20 +78,35 @@ public class SchematicDownloadEndpoint extends AbstractServlet
|
|||
return null;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
File[] alphabetical = worldeditFolder.listFiles();
|
||||
if (alphabetical != null)
|
||||
for (File worldeditFile : listFilesForFolder(worldeditFolder))
|
||||
{
|
||||
Arrays.sort(alphabetical);
|
||||
for (File worldeditFile : alphabetical)
|
||||
{
|
||||
String sanitizedName = worldeditFile.getName().replaceAll("<","<").replaceAll(">",">");
|
||||
sb.append("<tr>" +
|
||||
"<th scope=\"row\"><a href=\"" + worldeditFile.getName() + "\" download>" + sanitizedName + "</a></th>" +
|
||||
"<td>" + formattedSize(worldeditFile.length()) + "</td>" +
|
||||
"</tr>");
|
||||
}
|
||||
file = file.replace("${schematics}", sb.toString());
|
||||
String fixedPath = worldeditFile.getPath().replace("plugins/FastAsyncWorldEdit/schematics/", "");
|
||||
fixedPath = fixedPath.replace("plugins/WorldEdit/schematics/", "");
|
||||
String sanitizedName = fixedPath.replaceAll("<", "<").replaceAll(">", ">");
|
||||
sb.append(" <tr>\n" +
|
||||
" <th scope=\"row\">\n <a href=\"" + fixedPath + "\" download>" + sanitizedName + "</a>\n </th>\n" +
|
||||
" <td>\n " + formattedSize(worldeditFile.length()) + "\n </td>\n" +
|
||||
" </tr>\n");
|
||||
}
|
||||
file = file.replace("${schematics}", sb.toString());
|
||||
files.clear();
|
||||
return file;
|
||||
}
|
||||
|
||||
public List<File> listFilesForFolder(final File folder)
|
||||
{
|
||||
for (File fileEntry : folder.listFiles())
|
||||
{
|
||||
if (fileEntry.isDirectory())
|
||||
{
|
||||
PlexLog.debug("Found directory");
|
||||
listFilesForFolder(fileEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
files.add(fileEntry);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
package dev.plex.request.impl;
|
||||
|
||||
import dev.plex.HTTPDModule;
|
||||
import dev.plex.Plex;
|
||||
import dev.plex.cache.DataUtils;
|
||||
import dev.plex.player.PlexPlayer;
|
||||
import dev.plex.rank.enums.Rank;
|
||||
import dev.plex.request.AbstractServlet;
|
||||
import dev.plex.request.GetMapping;
|
||||
import dev.plex.util.PlexLog;
|
||||
|
@ -28,22 +26,11 @@ public class SchematicUploadEndpoint extends AbstractServlet
|
|||
{
|
||||
return schematicsHTML("Couldn't load your IP Address: " + ipAddress + ". Have you joined the server before?");
|
||||
}
|
||||
if (Plex.get().getSystem().equalsIgnoreCase("ranks"))
|
||||
PlexLog.debug("Plex-HTTPD using permissions check");
|
||||
final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(player.getUuid());
|
||||
if (!HTTPDModule.getPermissions().playerHas(null, offlinePlayer, "plex.httpd.schematics.upload"))
|
||||
{
|
||||
PlexLog.debug("Plex-HTTPD using ranks check");
|
||||
if (!player.getRankFromString().isAtLeast(Rank.ADMIN))
|
||||
{
|
||||
return schematicsHTML("You must be an admin or above to upload schematics.");
|
||||
}
|
||||
}
|
||||
else if (Plex.get().getSystem().equalsIgnoreCase("permissions"))
|
||||
{
|
||||
PlexLog.debug("Plex-HTTPD using permissions check");
|
||||
final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(player.getUuid());
|
||||
if (!HTTPDModule.getPermissions().playerHas(null, offlinePlayer, "plex.httpd.schematics.upload"))
|
||||
{
|
||||
return schematicsHTML("You do not have permission to upload schematics.");
|
||||
}
|
||||
return schematicsHTML("You do not have permission to upload schematics.");
|
||||
}
|
||||
return readFile(this.getClass().getResourceAsStream("/httpd/schematic_upload.html"));
|
||||
}
|
||||
|
|
|
@ -2,18 +2,21 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
||||
<script type="text/javascript"
|
||||
src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/gh/Telesphoreo/bootstrap-color-switcher@master/script.js"></script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@200;400&display=swap" rel="stylesheet">
|
||||
<title>${TITLE} - Plex HTTPD</title>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<body style="font-family: 'IBM Plex Sans', sans-serif;">
|
||||
<nav class="navbar navbar-expand-lg bg-body-tertiary">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/">Plex HTTPD</a>
|
||||
<a class="navbar-brand" href="/" style="font-weight:200;">Plex HTTPD</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
|
||||
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
|
@ -23,9 +26,6 @@
|
|||
<li class="nav-item">
|
||||
<a class="nav-link ${ACTIVE_HOME}" href="/">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link ${ACTIVE_ADMINS}" href="/api/admins/">Admins</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link ${ACTIVE_INDEFBANS}" href="/api/indefbans/">Indefinite Bans</a>
|
||||
</li>
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
Admins
|
||||
ADMINS
|
||||
<h2>Admins</h2>
|
||||
<h5 class="alert alert-danger mb-3 w-auto p-3" role="alert"><b>Error:</b> ${MESSAGE}</h5>
|
|
@ -0,0 +1,12 @@
|
|||
Commands
|
||||
COMMANDS
|
||||
<style>
|
||||
summary {
|
||||
font-size: 24px;
|
||||
padding: 16px;
|
||||
}
|
||||
</style>
|
||||
<h2>Commands List</h2>
|
||||
<h5>A list of commands is below.</h5>
|
||||
<br><br>
|
||||
${commands}
|
|
@ -1,4 +1,15 @@
|
|||
server:
|
||||
bind-address: 0.0.0.0
|
||||
port: 27192
|
||||
logging: false
|
||||
logging: false
|
||||
|
||||
authentication:
|
||||
enabled: false
|
||||
|
||||
# Providers: discord
|
||||
provider:
|
||||
name: discord
|
||||
redirectUri: ""
|
||||
discord: # Fill if using discord provider
|
||||
clientId: ""
|
||||
token: "" # Can also use environment variable or system property BOT_TOKEN
|
|
@ -15,7 +15,7 @@ SCHEMATICS
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${schematics}
|
||||
${schematics}
|
||||
</tbody>
|
||||
</table>
|
||||
<script>
|
||||
|
|
|
@ -2,18 +2,21 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
||||
<script type="text/javascript"
|
||||
src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/gh/Telesphoreo/bootstrap-color-switcher@master/script.js"></script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@200;400&display=swap" rel="stylesheet">
|
||||
<title>${TITLE} - Plex HTTPD</title>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<body style="font-family: 'IBM Plex Sans', sans-serif;">
|
||||
<nav class="navbar navbar-expand-lg bg-body-tertiary">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/">Plex HTTPD</a>
|
||||
<a class="navbar-brand" href="/" style="font-weight:200;">Plex HTTPD</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
|
||||
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
|
@ -23,9 +26,6 @@
|
|||
<li class="nav-item">
|
||||
<a class="nav-link ${ACTIVE_HOME}" href="/">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link ${ACTIVE_ADMINS}" href="/api/admins/">Admins</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link ${ACTIVE_INDEFBANS}" href="/api/indefbans/">Indefinite Bans</a>
|
||||
</li>
|
||||
|
@ -35,6 +35,9 @@
|
|||
<li class="nav-item">
|
||||
<a class="nav-link ${ACTIVE_PUNISHMENTS}" href="/api/punishments/">Punishments</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="nav-link ${ACTIVE_COMMANDS}" href="/api/commands/">Commands</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle ${ACTIVE_SCHEMATICS}" id="navbarDropdownMenuLink" role="button"
|
||||
data-bs-toggle="dropdown" aria-expanded="false">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
name: Plex-HTTPD
|
||||
version: 1.0.2
|
||||
name: Module-HTTPD
|
||||
version: 1.4-SNAPSHOT
|
||||
description: HTTPD server for Plex
|
||||
main: dev.plex.HTTPDModule
|
Loading…
Reference in New Issue