mirror of
https://github.com/plexusorg/Module-HTTPD.git
synced 2026-06-04 00:56:54 +00:00
Refactor
This commit is contained in:
@@ -3,7 +3,6 @@ package dev.plex;
|
||||
import dev.plex.assets.MinecraftAssetsManager;
|
||||
import dev.plex.authentication.AuthenticationManager;
|
||||
import dev.plex.cache.FileCache;
|
||||
import dev.plex.api.PlexApi;
|
||||
import dev.plex.config.ModuleConfig;
|
||||
import dev.plex.logging.Log;
|
||||
import dev.plex.module.PlexModule;
|
||||
@@ -33,35 +32,41 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class HTTPDModule extends PlexModule
|
||||
{
|
||||
public static ServletContextHandler context;
|
||||
@Getter
|
||||
private ServletContextHandler context;
|
||||
private Thread serverThread;
|
||||
private AtomicReference<Server> atomicServer = new AtomicReference<>();
|
||||
|
||||
public static ModuleConfig moduleConfig;
|
||||
private static PlexApi plexApi;
|
||||
|
||||
public static PlexApi plexApi()
|
||||
{
|
||||
return plexApi;
|
||||
}
|
||||
|
||||
public static final FileCache fileCache = new FileCache();
|
||||
|
||||
public static final String template = AbstractServlet.readFileReal(HTTPDModule.class.getResourceAsStream("/httpd/template.html"));
|
||||
private final AtomicReference<Server> atomicServer = new AtomicReference<>();
|
||||
|
||||
@Getter
|
||||
private static AuthenticationManager authenticationManager;
|
||||
private ModuleConfig moduleConfig;
|
||||
|
||||
@Getter
|
||||
private static File accessLogFile;
|
||||
private final FileCache fileCache = new FileCache();
|
||||
|
||||
@Getter
|
||||
private static MinecraftAssetsManager minecraftAssetsManager;
|
||||
private final String template = AbstractServlet.readFileReal(HTTPDModule.class.getResourceAsStream("/httpd/template.html"));
|
||||
|
||||
@Getter
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
||||
@Getter
|
||||
private File accessLogFile;
|
||||
|
||||
@Getter
|
||||
private MinecraftAssetsManager minecraftAssetsManager;
|
||||
|
||||
@Getter
|
||||
private StatsBroadcaster statsBroadcaster;
|
||||
|
||||
@Getter
|
||||
private PlayersBroadcaster playersBroadcaster;
|
||||
|
||||
@Getter
|
||||
private PlayerInventoryBroadcaster playerInventoryBroadcaster;
|
||||
|
||||
@Override
|
||||
public void load()
|
||||
{
|
||||
plexApi = api();
|
||||
// Move it from /httpd/config.yml to /plugins/Plex/modules/Plex-HTTPD/config.yml
|
||||
moduleConfig = new ModuleConfig(this, "httpd/config.yml", "config.yml");
|
||||
}
|
||||
@@ -70,17 +75,18 @@ public class HTTPDModule extends PlexModule
|
||||
public void enable()
|
||||
{
|
||||
moduleConfig.load();
|
||||
HTTPDModule.plexApi().logging().debug("HTTPD Module Port: {0}", moduleConfig.getInt("server.port"));
|
||||
api().logging().debug("HTTPD Module Port: {0}", moduleConfig.getInt("server.port"));
|
||||
|
||||
accessLogFile = new File(getDataFolder(), moduleConfig.getString("server.logging.file-path", "httpd.log"));
|
||||
Log.configure(moduleConfig, accessLogFile);
|
||||
|
||||
minecraftAssetsManager = new MinecraftAssetsManager(getDataFolder().toPath());
|
||||
minecraftAssetsManager = new MinecraftAssetsManager(getDataFolder().toPath(), api());
|
||||
minecraftAssetsManager.refreshAsync();
|
||||
|
||||
authenticationManager = new AuthenticationManager();
|
||||
authenticationManager = new AuthenticationManager(this);
|
||||
if (authenticationManager.provider() == null)
|
||||
{
|
||||
HTTPDModule.plexApi().logging().debug("Authentication is disabled or misconfigured");
|
||||
api().logging().debug("Authentication is disabled or misconfigured");
|
||||
}
|
||||
|
||||
|
||||
@@ -110,33 +116,37 @@ public class HTTPDModule extends PlexModule
|
||||
connector.setIdleTimeout(moduleConfig.getLong("server.limits.idle-timeout-ms", 15_000L));
|
||||
connector.setAcceptQueueSize(moduleConfig.getInt("server.limits.accept-queue", 32));
|
||||
|
||||
context.addFilter(new FilterHolder(new RateLimitFilter()), "/*", EnumSet.of(DispatcherType.REQUEST));
|
||||
context.addFilter(new FilterHolder(new RateLimitFilter(moduleConfig)), "/*", EnumSet.of(DispatcherType.REQUEST));
|
||||
|
||||
StatsBroadcaster.get().start();
|
||||
PlayersBroadcaster.get().start();
|
||||
PlayerInventoryBroadcaster.get().start();
|
||||
statsBroadcaster = new StatsBroadcaster(this);
|
||||
playersBroadcaster = new PlayersBroadcaster(this);
|
||||
playerInventoryBroadcaster = new PlayerInventoryBroadcaster(this);
|
||||
statsBroadcaster.start();
|
||||
playersBroadcaster.start();
|
||||
playerInventoryBroadcaster.start();
|
||||
|
||||
new IndefBansEndpoint();
|
||||
new IndexEndpoint();
|
||||
new ListEndpoint();
|
||||
new PunishmentsEndpoint();
|
||||
new CommandsEndpoint();
|
||||
new SchematicDownloadEndpoint();
|
||||
new SchematicUploadEndpoint();
|
||||
new PlayersEndpoint();
|
||||
new PlayerAdminEndpoint();
|
||||
new AssetsEndpoint();
|
||||
new PunishmentsUIEndpoint();
|
||||
new IndefBansUIEndpoint();
|
||||
new AuthenticationEndpoint();
|
||||
new IndefBansEndpoint(this);
|
||||
new IndexEndpoint(this);
|
||||
new ListEndpoint(this);
|
||||
new PunishmentsEndpoint(this);
|
||||
new CommandsEndpoint(this);
|
||||
new SchematicDownloadEndpoint(this);
|
||||
new SchematicUploadEndpoint(this);
|
||||
new PlayersEndpoint(this);
|
||||
new PlayerAdminEndpoint(this);
|
||||
new AssetsEndpoint(this);
|
||||
new PunishmentsUIEndpoint(this);
|
||||
new IndefBansUIEndpoint(this);
|
||||
new AuthenticationEndpoint(this);
|
||||
|
||||
HTTPDModule.context.addServlet(StatsStreamServlet.class, "/api/stats/stream");
|
||||
HTTPDModule.context.addServlet(PlayersStreamServlet.class, "/api/players/stream");
|
||||
HTTPDModule.context.addServlet(StaffPlayersStreamServlet.class, "/api/players/stream/staff");
|
||||
HTTPDModule.context.addServlet(PlayerActionServlet.class, "/api/admin/action");
|
||||
HTTPDModule.context.addServlet(PlayerInventoryStreamServlet.class, "/api/player/inventory/stream");
|
||||
context.addServlet(new ServletHolder(new StatsStreamServlet(statsBroadcaster)), "/api/stats/stream");
|
||||
context.addServlet(new ServletHolder(new PlayersStreamServlet(playersBroadcaster)), "/api/players/stream");
|
||||
context.addServlet(new ServletHolder(new StaffPlayersStreamServlet(this, playersBroadcaster)), "/api/players/stream/staff");
|
||||
context.addServlet(new ServletHolder(new PlayerActionServlet(this)), "/api/admin/action");
|
||||
context.addServlet(new ServletHolder(new PlayerInventoryStreamServlet(this, playerInventoryBroadcaster)), "/api/player/inventory/stream");
|
||||
|
||||
ServletHolder uploadHolder = HTTPDModule.context.addServlet(SchematicUploadServlet.class, "/api/schematics/uploading");
|
||||
ServletHolder uploadHolder = new ServletHolder(new SchematicUploadServlet(this));
|
||||
context.addServlet(uploadHolder, "/api/schematics/uploading");
|
||||
|
||||
File uploadLoc = new File(System.getProperty("java.io.tmpdir"), "schematic-temp-dir");
|
||||
if (!uploadLoc.exists())
|
||||
@@ -160,16 +170,19 @@ public class HTTPDModule extends PlexModule
|
||||
}
|
||||
}, "Jetty-Server");
|
||||
serverThread.start();
|
||||
HTTPDModule.plexApi().logging().info("Starting Jetty server on port " + moduleConfig.getInt("server.port"));
|
||||
api().logging().info("Starting Jetty server on port " + moduleConfig.getInt("server.port"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable()
|
||||
{
|
||||
HTTPDModule.plexApi().logging().debug("Stopping Jetty server");
|
||||
api().logging().debug("Stopping Jetty server");
|
||||
try
|
||||
{
|
||||
StatsBroadcaster.get().shutdown();
|
||||
if (statsBroadcaster != null)
|
||||
{
|
||||
statsBroadcaster.shutdown();
|
||||
}
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
@@ -177,7 +190,10 @@ public class HTTPDModule extends PlexModule
|
||||
}
|
||||
try
|
||||
{
|
||||
PlayersBroadcaster.get().shutdown();
|
||||
if (playersBroadcaster != null)
|
||||
{
|
||||
playersBroadcaster.shutdown();
|
||||
}
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
@@ -185,7 +201,10 @@ public class HTTPDModule extends PlexModule
|
||||
}
|
||||
try
|
||||
{
|
||||
PlayerInventoryBroadcaster.get().shutdown();
|
||||
if (playerInventoryBroadcaster != null)
|
||||
{
|
||||
playerInventoryBroadcaster.shutdown();
|
||||
}
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
@@ -193,8 +212,12 @@ public class HTTPDModule extends PlexModule
|
||||
}
|
||||
try
|
||||
{
|
||||
atomicServer.get().stop();
|
||||
atomicServer.get().destroy();
|
||||
Server server = atomicServer.get();
|
||||
if (server != null)
|
||||
{
|
||||
server.stop();
|
||||
server.destroy();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package dev.plex.assets;
|
||||
|
||||
import dev.plex.HTTPDModule;
|
||||
import dev.plex.api.PlexApi;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
@@ -35,12 +35,14 @@ public class MinecraftAssetsManager
|
||||
private final AtomicBoolean ready = new AtomicBoolean(false);
|
||||
private final AtomicBoolean refreshStarted = new AtomicBoolean(false);
|
||||
private final String minecraftVersion;
|
||||
private final PlexApi api;
|
||||
|
||||
public MinecraftAssetsManager(Path dataFolder)
|
||||
public MinecraftAssetsManager(Path dataFolder, PlexApi api)
|
||||
{
|
||||
this.root = dataFolder.resolve("minecraft-assets");
|
||||
this.versionFile = root.resolve("version.txt");
|
||||
this.minecraftVersion = detectMinecraftVersion();
|
||||
this.api = api;
|
||||
this.client = HttpClient.newBuilder()
|
||||
.followRedirects(HttpClient.Redirect.NORMAL)
|
||||
.connectTimeout(Duration.ofSeconds(20))
|
||||
@@ -63,7 +65,7 @@ public class MinecraftAssetsManager
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
HTTPDModule.plexApi().logging().info("Unable to download Minecraft assets for HTTPD inventory view: " + e.getMessage());
|
||||
api.logging().info("Unable to download Minecraft assets for HTTPD inventory view: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
@@ -90,13 +92,13 @@ public class MinecraftAssetsManager
|
||||
String cachedVersion = Files.exists(versionFile) ? Files.readString(versionFile).trim() : "";
|
||||
if (minecraftVersion.equals(cachedVersion) && hasAssets())
|
||||
{
|
||||
HTTPDModule.plexApi().logging().debug("HTTPD Minecraft assets are already cached for {0}", minecraftVersion);
|
||||
api.logging().debug("HTTPD Minecraft assets are already cached for {0}", minecraftVersion);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cachedVersion.isEmpty() && !minecraftVersion.equals(cachedVersion))
|
||||
{
|
||||
HTTPDModule.plexApi().logging().info("Minecraft version changed from " + cachedVersion + " to " + minecraftVersion + "; recreating HTTPD asset cache");
|
||||
api.logging().info("Minecraft version changed from " + cachedVersion + " to " + minecraftVersion + "; recreating HTTPD asset cache");
|
||||
}
|
||||
recreateCache();
|
||||
}
|
||||
@@ -114,7 +116,7 @@ public class MinecraftAssetsManager
|
||||
deleteDirectory(root);
|
||||
Files.createDirectories(root);
|
||||
|
||||
HTTPDModule.plexApi().logging().info("Downloading Minecraft " + minecraftVersion + " client assets for HTTPD inventory view");
|
||||
api.logging().info("Downloading Minecraft " + minecraftVersion + " client assets for HTTPD inventory view");
|
||||
JSONObject version = findVersionJson();
|
||||
String clientUrl = version.getJSONObject("downloads").getJSONObject("client").getString("url");
|
||||
|
||||
@@ -142,7 +144,7 @@ public class MinecraftAssetsManager
|
||||
}
|
||||
|
||||
Files.writeString(versionFile, minecraftVersion + System.lineSeparator());
|
||||
HTTPDModule.plexApi().logging().info("HTTPD Minecraft assets cached for " + minecraftVersion);
|
||||
api.logging().info("HTTPD Minecraft assets cached for " + minecraftVersion);
|
||||
}
|
||||
|
||||
private JSONObject findVersionJson() throws IOException, InterruptedException
|
||||
|
||||
@@ -7,17 +7,17 @@ public class AuthenticationManager
|
||||
{
|
||||
private final OAuth2Provider provider;
|
||||
|
||||
public AuthenticationManager()
|
||||
public AuthenticationManager(HTTPDModule module)
|
||||
{
|
||||
final boolean enabled = HTTPDModule.moduleConfig.getBoolean("authentication.enabled", false);
|
||||
final boolean enabled = module.getModuleConfig().getBoolean("authentication.enabled", false);
|
||||
if (!enabled)
|
||||
{
|
||||
provider = null;
|
||||
return;
|
||||
}
|
||||
|
||||
HTTPDModule.plexApi().logging().info("[HTTPD] XenForo OAuth2 authentication is enabled");
|
||||
provider = new XenForoOAuth2Provider();
|
||||
module.api().logging().info("[HTTPD] XenForo OAuth2 authentication is enabled");
|
||||
provider = new XenForoOAuth2Provider(module);
|
||||
}
|
||||
|
||||
public OAuth2Provider provider()
|
||||
|
||||
@@ -49,19 +49,21 @@ public class XenForoOAuth2Provider implements OAuth2Provider
|
||||
private final String clientSecret;
|
||||
private final String redirectUri;
|
||||
private final Duration sessionTtl;
|
||||
private final HTTPDModule module;
|
||||
|
||||
public XenForoOAuth2Provider()
|
||||
public XenForoOAuth2Provider(HTTPDModule module)
|
||||
{
|
||||
String domain = HTTPDModule.moduleConfig.getString("authentication.provider.xenforo.domain", "");
|
||||
this.clientId = HTTPDModule.moduleConfig.getString("authentication.provider.xenforo.clientId", "");
|
||||
this.clientSecret = HTTPDModule.moduleConfig.getString("authentication.provider.xenforo.clientSecret", "");
|
||||
this.redirectUri = HTTPDModule.moduleConfig.getString("authentication.provider.redirectUri", "");
|
||||
long ttlMinutes = HTTPDModule.moduleConfig.getLong("authentication.provider.xenforo.sessionMinutes", 1440L);
|
||||
this.module = module;
|
||||
String domain = module.getModuleConfig().getString("authentication.provider.xenforo.domain", "");
|
||||
this.clientId = module.getModuleConfig().getString("authentication.provider.xenforo.clientId", "");
|
||||
this.clientSecret = module.getModuleConfig().getString("authentication.provider.xenforo.clientSecret", "");
|
||||
this.redirectUri = module.getModuleConfig().getString("authentication.provider.redirectUri", "");
|
||||
long ttlMinutes = module.getModuleConfig().getLong("authentication.provider.xenforo.sessionMinutes", 1440L);
|
||||
this.sessionTtl = Duration.ofMinutes(Math.max(ttlMinutes, 1L));
|
||||
|
||||
if (domain.isEmpty() || clientId.isEmpty() || clientSecret.isEmpty() || redirectUri.isEmpty())
|
||||
{
|
||||
HTTPDModule.plexApi().logging().error("XenForo OAuth2 misconfigured: domain, clientId, clientSecret, redirectUri are all required.");
|
||||
module.api().logging().error("XenForo OAuth2 misconfigured: domain, clientId, clientSecret, redirectUri are all required.");
|
||||
}
|
||||
|
||||
String base = "https://" + domain.replaceFirst("^https?://", "").replaceAll("/+$", "");
|
||||
@@ -285,7 +287,7 @@ public class XenForoOAuth2Provider implements OAuth2Provider
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
HTTPDModule.plexApi().logging().debug("Failed to revoke XenForo token: {0}", e.getMessage());
|
||||
module.api().logging().debug("Failed to revoke XenForo token: {0}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package dev.plex.logging;
|
||||
|
||||
import dev.plex.HTTPDModule;
|
||||
import dev.plex.config.ModuleConfig;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -11,19 +11,30 @@ import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
public class Log
|
||||
{
|
||||
private static final DateTimeFormatter STAMP = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS z");
|
||||
|
||||
private static BooleanSupplier consoleLoggingEnabled = () -> false;
|
||||
private static BooleanSupplier fileLoggingEnabled = () -> false;
|
||||
private static File accessLogFile;
|
||||
private static BufferedWriter writer;
|
||||
private static File writerTarget;
|
||||
|
||||
public static synchronized void configure(ModuleConfig moduleConfig, File target)
|
||||
{
|
||||
consoleLoggingEnabled = () -> moduleConfig.getBoolean("server.logging.console", false);
|
||||
fileLoggingEnabled = () -> moduleConfig.getBoolean("server.logging.file", true);
|
||||
accessLogFile = target;
|
||||
}
|
||||
|
||||
public static void log(String message, Object... strings)
|
||||
{
|
||||
String formatted = format(message, strings);
|
||||
writeFile(formatted);
|
||||
if (HTTPDModule.moduleConfig != null && HTTPDModule.moduleConfig.getBoolean("server.logging.console", false))
|
||||
if (consoleLoggingEnabled.getAsBoolean())
|
||||
{
|
||||
Bukkit.getConsoleSender().sendMessage(Component.text("[Plex HTTPD] ").color(NamedTextColor.DARK_AQUA).append(Component.text(formatted).color(NamedTextColor.GRAY)));
|
||||
}
|
||||
@@ -42,6 +53,9 @@ public class Log
|
||||
writer = null;
|
||||
writerTarget = null;
|
||||
}
|
||||
consoleLoggingEnabled = () -> false;
|
||||
fileLoggingEnabled = () -> false;
|
||||
accessLogFile = null;
|
||||
}
|
||||
|
||||
private static String format(String message, Object... strings)
|
||||
@@ -59,9 +73,8 @@ public class Log
|
||||
|
||||
private static synchronized void writeFile(String formatted)
|
||||
{
|
||||
if (HTTPDModule.moduleConfig == null) return;
|
||||
if (!HTTPDModule.moduleConfig.getBoolean("server.logging.file", true)) return;
|
||||
File target = HTTPDModule.getAccessLogFile();
|
||||
if (!fileLoggingEnabled.getAsBoolean()) return;
|
||||
File target = accessLogFile;
|
||||
if (target == null) return;
|
||||
if (writer == null || !target.equals(writerTarget))
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package dev.plex.ratelimit;
|
||||
|
||||
import dev.plex.HTTPDModule;
|
||||
import dev.plex.config.ModuleConfig;
|
||||
import dev.plex.logging.Log;
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
@@ -28,14 +28,14 @@ public class RateLimitFilter implements Filter
|
||||
private final ConcurrentHashMap<String, TokenBucket> ipBuckets = new ConcurrentHashMap<>();
|
||||
private final AtomicLong nextEvictMillis = new AtomicLong(System.currentTimeMillis() + EVICT_INTERVAL_MILLIS);
|
||||
|
||||
public RateLimitFilter()
|
||||
public RateLimitFilter(ModuleConfig config)
|
||||
{
|
||||
this.enabled = HTTPDModule.moduleConfig.getBoolean("rate-limit.enabled", true);
|
||||
double globalCapacity = HTTPDModule.moduleConfig.getDouble("rate-limit.global.capacity", 200.0);
|
||||
double globalRate = HTTPDModule.moduleConfig.getDouble("rate-limit.global.per-second", 100.0);
|
||||
this.enabled = config.getBoolean("rate-limit.enabled", true);
|
||||
double globalCapacity = config.getDouble("rate-limit.global.capacity", 200.0);
|
||||
double globalRate = config.getDouble("rate-limit.global.per-second", 100.0);
|
||||
this.globalBucket = new TokenBucket(globalCapacity, globalRate);
|
||||
this.ipCapacity = HTTPDModule.moduleConfig.getDouble("rate-limit.per-ip.capacity", 30.0);
|
||||
this.ipRefillPerSecond = HTTPDModule.moduleConfig.getDouble("rate-limit.per-ip.per-second", 10.0);
|
||||
this.ipCapacity = config.getDouble("rate-limit.per-ip.capacity", 30.0);
|
||||
this.ipRefillPerSecond = config.getDouble("rate-limit.per-ip.per-second", 10.0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,9 +28,11 @@ import org.eclipse.jetty.ee10.servlet.ServletHolder;
|
||||
public class AbstractServlet extends HttpServlet
|
||||
{
|
||||
private final List<Mapping> GET_MAPPINGS = Lists.newArrayList();
|
||||
protected final HTTPDModule module;
|
||||
|
||||
public AbstractServlet()
|
||||
public AbstractServlet(HTTPDModule module)
|
||||
{
|
||||
this.module = module;
|
||||
for (Method declaredMethod : this.getClass().getDeclaredMethods())
|
||||
{
|
||||
declaredMethod.setAccessible(true);
|
||||
@@ -46,7 +48,7 @@ public class AbstractServlet extends HttpServlet
|
||||
ServletHolder holder = new ServletHolder(this);
|
||||
String endpoint = getMapping.endpoint();
|
||||
String pattern = endpoint.endsWith("/") ? endpoint + "*" : endpoint;
|
||||
HTTPDModule.context.addServlet(holder, pattern);
|
||||
module.getContext().addServlet(holder, pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,11 +65,6 @@ public class AbstractServlet extends HttpServlet
|
||||
String requestPath = getRequestPath(req);
|
||||
Log.log(ipAddress + " visited endpoint " + requestPath);
|
||||
|
||||
/*Enumeration<String> headerz = req.getHeaderNames();
|
||||
while (headerz.hasMoreElements()) {
|
||||
String header = headerz.nextElement();
|
||||
HTTPDModule.plexApi().logging().debug("Header: {0} Value {1}", header, req.getHeader(header));
|
||||
}*/
|
||||
GET_MAPPINGS.stream().filter(mapping -> endpointMatchesRequest(mapping.getMapping().endpoint(), requestPath)).forEach(mapping ->
|
||||
{
|
||||
resp.setCharacterEncoding("UTF-8");
|
||||
@@ -137,27 +134,42 @@ public class AbstractServlet extends HttpServlet
|
||||
return requestPath.isEmpty() ? "/" : requestPath;
|
||||
}
|
||||
|
||||
public static AuthenticatedUser currentUser(HttpServletRequest request)
|
||||
protected AuthenticatedUser currentUser(HttpServletRequest request)
|
||||
{
|
||||
AuthenticationManager manager = HTTPDModule.getAuthenticationManager();
|
||||
return currentUser(module, request);
|
||||
}
|
||||
|
||||
public static AuthenticatedUser currentUser(HTTPDModule module, HttpServletRequest request)
|
||||
{
|
||||
AuthenticationManager manager = module.getAuthenticationManager();
|
||||
if (manager == null) return null;
|
||||
OAuth2Provider provider = manager.provider();
|
||||
if (provider == null) return null;
|
||||
return provider.lookup(request);
|
||||
}
|
||||
|
||||
public static AuthenticatedUser currentStaff(HttpServletRequest request)
|
||||
protected AuthenticatedUser currentStaff(HttpServletRequest request)
|
||||
{
|
||||
AuthenticatedUser user = currentUser(request);
|
||||
return currentStaff(module, request);
|
||||
}
|
||||
|
||||
public static AuthenticatedUser currentStaff(HTTPDModule module, HttpServletRequest request)
|
||||
{
|
||||
AuthenticatedUser user = currentUser(module, request);
|
||||
return (user != null && user.staff()) ? user : null;
|
||||
}
|
||||
|
||||
public static String signInPrompt(String action)
|
||||
protected String signInPrompt(String action)
|
||||
{
|
||||
return signInPrompt(null, action);
|
||||
}
|
||||
|
||||
public static String signInPrompt(HttpServletRequest request, String action)
|
||||
protected String signInPrompt(HttpServletRequest request, String action)
|
||||
{
|
||||
return signInPrompt(module, request, action);
|
||||
}
|
||||
|
||||
public static String signInPrompt(HTTPDModule module, HttpServletRequest request, String action)
|
||||
{
|
||||
String href = "/oauth2/login";
|
||||
if (request != null)
|
||||
@@ -170,9 +182,14 @@ public class AbstractServlet extends HttpServlet
|
||||
return "You must <a class=\"text-primary underline\" href=\"" + href + "\">sign in</a> as staff " + action + ".";
|
||||
}
|
||||
|
||||
public static String readFile(InputStream filename)
|
||||
protected String readFile(InputStream filename)
|
||||
{
|
||||
String base = HTTPDModule.template;
|
||||
return readFile(module, filename);
|
||||
}
|
||||
|
||||
public static String readFile(HTTPDModule module, InputStream filename)
|
||||
{
|
||||
String base = module.getTemplate();
|
||||
String page = readFileReal(filename);
|
||||
String[] info = page.split("\\r?\\n", 3);
|
||||
String title = info.length > 0 ? info[0] : "";
|
||||
|
||||
@@ -27,12 +27,18 @@ public class PlayerActionServlet extends HttpServlet
|
||||
private static final List<String> PERMANENT_ACTIONS = List.of("ban", "mute");
|
||||
private static final List<String> TEMP_ACTIONS = List.of("tempban", "tempmute", "freeze");
|
||||
private static final List<String> INVENTORY_ACTIONS = List.of("clear-inventory", "clear-selected");
|
||||
private final HTTPDModule module;
|
||||
|
||||
public PlayerActionServlet(HTTPDModule module)
|
||||
{
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
AuthenticatedUser staff = AbstractServlet.currentStaff(request);
|
||||
AuthenticatedUser staff = AbstractServlet.currentStaff(module, request);
|
||||
if (staff == null)
|
||||
{
|
||||
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
||||
@@ -71,7 +77,7 @@ public class PlayerActionServlet extends HttpServlet
|
||||
return;
|
||||
}
|
||||
|
||||
PlexPlayerView target = HTTPDModule.plexApi().players().byUuid(uuid).orElse(null);
|
||||
PlexPlayerView target = module.api().players().byUuid(uuid).orElse(null);
|
||||
if (target == null)
|
||||
{
|
||||
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||
@@ -119,11 +125,11 @@ public class PlayerActionServlet extends HttpServlet
|
||||
|
||||
final boolean kick = action.equals("ban") || action.equals("tempban");
|
||||
final PunishmentRequest toApply = punishment;
|
||||
HTTPDModule.plexApi().scheduler().runGlobal(() ->
|
||||
module.api().scheduler().runGlobal(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
HTTPDModule.plexApi().punishments().punish(target, toApply);
|
||||
module.api().punishments().punish(target, toApply);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
@@ -135,7 +141,7 @@ public class PlayerActionServlet extends HttpServlet
|
||||
Player online = Bukkit.getPlayer(uuid);
|
||||
if (online != null)
|
||||
{
|
||||
HTTPDModule.plexApi().scheduler().runEntity(online, () ->
|
||||
module.api().scheduler().runEntity(online, () ->
|
||||
{
|
||||
try { online.kick(Component.text("You have been banned: " + toApply.reason())); }
|
||||
catch (Throwable t) { t.printStackTrace(); }
|
||||
@@ -147,7 +153,7 @@ public class PlayerActionServlet extends HttpServlet
|
||||
response.sendRedirect("/player/" + uuid);
|
||||
}
|
||||
|
||||
private static void handleInventoryAction(HttpServletRequest request, HttpServletResponse response, AuthenticatedUser staff, UUID uuid, PlexPlayerView target, String action, String slot)
|
||||
private void handleInventoryAction(HttpServletRequest request, HttpServletResponse response, AuthenticatedUser staff, UUID uuid, PlexPlayerView target, String action, String slot)
|
||||
throws IOException
|
||||
{
|
||||
String ipAddress = request.getRemoteAddr();
|
||||
@@ -159,11 +165,11 @@ public class PlayerActionServlet extends HttpServlet
|
||||
|
||||
Log.log(ipAddress + " (xf:" + staff.username() + ") issued " + action + " on " + target.name() + " (" + uuid + ")" + (slot == null || slot.isBlank() ? "" : " slot " + slot));
|
||||
|
||||
HTTPDModule.plexApi().scheduler().runGlobal(() ->
|
||||
module.api().scheduler().runGlobal(() ->
|
||||
{
|
||||
Player online = Bukkit.getPlayer(uuid);
|
||||
if (online == null) return;
|
||||
HTTPDModule.plexApi().scheduler().runEntity(online, () ->
|
||||
module.api().scheduler().runEntity(online, () ->
|
||||
{
|
||||
PlayerInventory inv = online.getInventory();
|
||||
if ("clear-inventory".equals(action))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.plex.request;
|
||||
|
||||
import dev.plex.HTTPDModule;
|
||||
import dev.plex.logging.Log;
|
||||
import dev.plex.request.impl.PlayerInventoryBroadcaster;
|
||||
import jakarta.servlet.AsyncContext;
|
||||
@@ -16,11 +17,20 @@ import java.util.UUID;
|
||||
|
||||
public class PlayerInventoryStreamServlet extends HttpServlet
|
||||
{
|
||||
private final HTTPDModule module;
|
||||
private final PlayerInventoryBroadcaster broadcaster;
|
||||
|
||||
public PlayerInventoryStreamServlet(HTTPDModule module, PlayerInventoryBroadcaster broadcaster)
|
||||
{
|
||||
this.module = module;
|
||||
this.broadcaster = broadcaster;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
if (AbstractServlet.currentStaff(request) == null)
|
||||
if (AbstractServlet.currentStaff(module, request) == null)
|
||||
{
|
||||
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
||||
return;
|
||||
@@ -51,7 +61,6 @@ public class PlayerInventoryStreamServlet extends HttpServlet
|
||||
}
|
||||
Log.log(ipAddress + " opened inventory stream for " + uuid);
|
||||
|
||||
PlayerInventoryBroadcaster broadcaster = PlayerInventoryBroadcaster.get();
|
||||
if (broadcaster.atCapacity())
|
||||
{
|
||||
response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
|
||||
|
||||
@@ -15,6 +15,13 @@ import java.io.PrintWriter;
|
||||
|
||||
public class PlayersStreamServlet extends HttpServlet
|
||||
{
|
||||
private final PlayersBroadcaster broadcaster;
|
||||
|
||||
public PlayersStreamServlet(PlayersBroadcaster broadcaster)
|
||||
{
|
||||
this.broadcaster = broadcaster;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException
|
||||
@@ -27,7 +34,6 @@ public class PlayersStreamServlet extends HttpServlet
|
||||
}
|
||||
Log.log(ipAddress + " opened SSE stream /api/players/stream");
|
||||
|
||||
PlayersBroadcaster broadcaster = PlayersBroadcaster.get();
|
||||
if (broadcaster.atCapacity())
|
||||
{
|
||||
response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
|
||||
|
||||
@@ -22,14 +22,20 @@ 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);
|
||||
private final HTTPDModule module;
|
||||
|
||||
public SchematicUploadServlet(HTTPDModule module)
|
||||
{
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
AuthenticatedUser user = AbstractServlet.currentStaff(request);
|
||||
AuthenticatedUser user = AbstractServlet.currentStaff(module, request);
|
||||
if (user == null)
|
||||
{
|
||||
response.getWriter().println(schematicUploadBadHTML(AbstractServlet.signInPrompt(request, "to upload schematics")));
|
||||
response.getWriter().println(schematicUploadBadHTML(AbstractServlet.signInPrompt(module, request, "to upload schematics")));
|
||||
return;
|
||||
}
|
||||
File worldeditFolder = HTTPDModule.getWorldeditFolder();
|
||||
@@ -67,7 +73,7 @@ public class SchematicUploadServlet extends HttpServlet
|
||||
ClipboardFormat schematicFormat = ClipboardFormats.findByFile(schematicFile);
|
||||
if (schematicFormat == null)
|
||||
{
|
||||
HTTPDModule.plexApi().logging().info(user.username() + " FAILED to upload schematic with filename: " + filename);
|
||||
module.api().logging().info(user.username() + " FAILED to upload schematic with filename: " + filename);
|
||||
Log.log("{0} (xf:{1}) FAILED to upload schematic {2}", user.username(), user.userId(), filename);
|
||||
response.getWriter().println(schematicUploadBadHTML("Schematic is not a valid format."));
|
||||
FileUtils.deleteQuietly(schematicFile);
|
||||
@@ -79,7 +85,7 @@ public class SchematicUploadServlet extends HttpServlet
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
HTTPDModule.plexApi().logging().info(user.username() + " FAILED to upload schematic with filename: " + filename);
|
||||
module.api().logging().info(user.username() + " FAILED to upload schematic with filename: " + filename);
|
||||
Log.log("{0} (xf:{1}) FAILED to upload schematic {2}", user.username(), user.userId(), filename);
|
||||
response.getWriter().println(schematicUploadBadHTML("Schematic is not a valid format."));
|
||||
FileUtils.deleteQuietly(schematicFile);
|
||||
@@ -87,20 +93,20 @@ public class SchematicUploadServlet extends HttpServlet
|
||||
}
|
||||
inputStream.close();
|
||||
response.getWriter().println(schematicUploadGoodHTML("Successfully uploaded <b>" + filename + "</b>."));
|
||||
HTTPDModule.plexApi().logging().info(user.username() + " uploaded schematic with filename: " + filename);
|
||||
module.api().logging().info(user.username() + " uploaded schematic with filename: " + filename);
|
||||
Log.log("{0} (xf:{1}) uploaded schematic {2}", user.username(), user.userId(), filename);
|
||||
}
|
||||
|
||||
private String schematicUploadBadHTML(String message)
|
||||
{
|
||||
String file = AbstractServlet.readFile(this.getClass().getResourceAsStream("/httpd/schematic_upload_bad.html"));
|
||||
String file = AbstractServlet.readFile(module, this.getClass().getResourceAsStream("/httpd/schematic_upload_bad.html"));
|
||||
file = file.replace("${MESSAGE}", message);
|
||||
return file;
|
||||
}
|
||||
|
||||
private String schematicUploadGoodHTML(String message)
|
||||
{
|
||||
String file = AbstractServlet.readFile(this.getClass().getResourceAsStream("/httpd/schematic_upload_good.html"));
|
||||
String file = AbstractServlet.readFile(module, this.getClass().getResourceAsStream("/httpd/schematic_upload_good.html"));
|
||||
file = file.replace("${MESSAGE}", message);
|
||||
return file;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.plex.request;
|
||||
|
||||
import dev.plex.HTTPDModule;
|
||||
import dev.plex.logging.Log;
|
||||
import dev.plex.request.impl.PlayersBroadcaster;
|
||||
import jakarta.servlet.AsyncContext;
|
||||
@@ -15,11 +16,20 @@ import java.io.PrintWriter;
|
||||
|
||||
public class StaffPlayersStreamServlet extends HttpServlet
|
||||
{
|
||||
private final HTTPDModule module;
|
||||
private final PlayersBroadcaster broadcaster;
|
||||
|
||||
public StaffPlayersStreamServlet(HTTPDModule module, PlayersBroadcaster broadcaster)
|
||||
{
|
||||
this.module = module;
|
||||
this.broadcaster = broadcaster;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
if (AbstractServlet.currentStaff(request) == null)
|
||||
if (AbstractServlet.currentStaff(module, request) == null)
|
||||
{
|
||||
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
||||
return;
|
||||
@@ -33,7 +43,6 @@ public class StaffPlayersStreamServlet extends HttpServlet
|
||||
}
|
||||
Log.log(ipAddress + " opened SSE stream /api/players/stream/staff");
|
||||
|
||||
PlayersBroadcaster broadcaster = PlayersBroadcaster.get();
|
||||
if (broadcaster.atCapacity())
|
||||
{
|
||||
response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
|
||||
|
||||
@@ -15,6 +15,13 @@ import java.io.PrintWriter;
|
||||
|
||||
public class StatsStreamServlet extends HttpServlet
|
||||
{
|
||||
private final StatsBroadcaster broadcaster;
|
||||
|
||||
public StatsStreamServlet(StatsBroadcaster broadcaster)
|
||||
{
|
||||
this.broadcaster = broadcaster;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException
|
||||
@@ -27,7 +34,6 @@ public class StatsStreamServlet extends HttpServlet
|
||||
}
|
||||
Log.log(ipAddress + " opened SSE stream /api/stats/stream");
|
||||
|
||||
StatsBroadcaster broadcaster = StatsBroadcaster.get();
|
||||
if (broadcaster.atCapacity())
|
||||
{
|
||||
response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
|
||||
|
||||
@@ -20,6 +20,10 @@ public class AssetsEndpoint extends AbstractServlet
|
||||
private static final Pattern MODEL_PATH = Pattern.compile("(item|block)/[a-z0-9_]+\\.json");
|
||||
private static final Pattern ITEM_DEF_PATH = Pattern.compile("[a-z0-9_]+\\.json");
|
||||
|
||||
public AssetsEndpoint(HTTPDModule module)
|
||||
{
|
||||
super(module);
|
||||
}
|
||||
|
||||
@GetMapping(endpoint = "/assets/dashboard.js")
|
||||
@MappingHeaders(headers = {"content-type;application/javascript; charset=utf-8", "cache-control;public, max-age=300"})
|
||||
@@ -97,7 +101,7 @@ public class AssetsEndpoint extends AbstractServlet
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void servePathUnder(HttpServletRequest request, HttpServletResponse response, String urlPrefix, Pattern allowed, String cacheCategory, String resourcePrefix)
|
||||
private void servePathUnder(HttpServletRequest request, HttpServletResponse response, String urlPrefix, Pattern allowed, String cacheCategory, String resourcePrefix)
|
||||
{
|
||||
String uri = request.getRequestURI();
|
||||
if (!uri.startsWith(urlPrefix))
|
||||
@@ -123,13 +127,13 @@ public class AssetsEndpoint extends AbstractServlet
|
||||
serveResource(resourcePrefix + rest, response);
|
||||
}
|
||||
|
||||
private static boolean serveCached(String category, String relativePath, HttpServletResponse response)
|
||||
private boolean serveCached(String category, String relativePath, HttpServletResponse response)
|
||||
{
|
||||
if (HTTPDModule.getMinecraftAssetsManager() == null)
|
||||
if (module.getMinecraftAssetsManager() == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Path path = HTTPDModule.getMinecraftAssetsManager().resolve(category, relativePath);
|
||||
Path path = module.getMinecraftAssetsManager().resolve(category, relativePath);
|
||||
if (path == null)
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -21,10 +21,15 @@ public class AuthenticationEndpoint extends AbstractServlet
|
||||
{
|
||||
private static final String RETURN_TO_COOKIE = "plex_return_to";
|
||||
|
||||
public AuthenticationEndpoint(HTTPDModule module)
|
||||
{
|
||||
super(module);
|
||||
}
|
||||
|
||||
@GetMapping(endpoint = "/oauth2/login")
|
||||
public String login(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
OAuth2Provider provider = HTTPDModule.getAuthenticationManager().provider();
|
||||
OAuth2Provider provider = module.getAuthenticationManager().provider();
|
||||
if (provider == null)
|
||||
{
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND, "Authentication is not enabled.");
|
||||
@@ -51,7 +56,7 @@ public class AuthenticationEndpoint extends AbstractServlet
|
||||
@GetMapping(endpoint = "/oauth2/callback")
|
||||
public String callback(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
OAuth2Provider provider = HTTPDModule.getAuthenticationManager().provider();
|
||||
OAuth2Provider provider = module.getAuthenticationManager().provider();
|
||||
if (provider == null)
|
||||
{
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND, "Authentication is not enabled.");
|
||||
@@ -63,7 +68,7 @@ public class AuthenticationEndpoint extends AbstractServlet
|
||||
}
|
||||
catch (AuthenticationException e)
|
||||
{
|
||||
HTTPDModule.plexApi().logging().error("OAuth2 callback failed: " + e.getMessage());
|
||||
module.api().logging().error("OAuth2 callback failed: " + e.getMessage());
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
response.setContentType("text/html; charset=UTF-8");
|
||||
return "<!doctype html><meta charset=utf-8><title>Sign-in failed</title>"
|
||||
@@ -84,7 +89,7 @@ public class AuthenticationEndpoint extends AbstractServlet
|
||||
@GetMapping(endpoint = "/oauth2/logout")
|
||||
public String logout(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
OAuth2Provider provider = HTTPDModule.getAuthenticationManager().provider();
|
||||
OAuth2Provider provider = module.getAuthenticationManager().provider();
|
||||
if (provider == null)
|
||||
{
|
||||
response.sendRedirect("/");
|
||||
@@ -106,7 +111,7 @@ public class AuthenticationEndpoint extends AbstractServlet
|
||||
@MappingHeaders(headers = "content-type;application/json")
|
||||
public String me(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
OAuth2Provider provider = HTTPDModule.getAuthenticationManager().provider();
|
||||
OAuth2Provider provider = module.getAuthenticationManager().provider();
|
||||
if (provider == null)
|
||||
{
|
||||
return "{\"authenticated\":false,\"reason\":\"disabled\"}";
|
||||
|
||||
@@ -22,6 +22,11 @@ public class CommandsEndpoint extends AbstractServlet
|
||||
{
|
||||
private String cachedHtml;
|
||||
|
||||
public CommandsEndpoint(HTTPDModule module)
|
||||
{
|
||||
super(module);
|
||||
}
|
||||
|
||||
@GetMapping(endpoint = "/api/commands/")
|
||||
public String getCommands(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
@@ -34,12 +39,12 @@ public class CommandsEndpoint extends AbstractServlet
|
||||
return file;
|
||||
}
|
||||
|
||||
private static String buildSections()
|
||||
private String buildSections()
|
||||
{
|
||||
final SortedMap<String, List<CommandInfo>> commandMap = new TreeMap<>();
|
||||
|
||||
List<CommandInfo> plexCommands = commandMap.computeIfAbsent("Plex", k -> new ArrayList<>());
|
||||
for (PlexCommand command : HTTPDModule.plexApi().commands().registeredCommands())
|
||||
for (PlexCommand command : module.api().commands().registeredCommands())
|
||||
{
|
||||
plexCommands.add(CommandInfo.from(command));
|
||||
}
|
||||
|
||||
@@ -10,6 +10,11 @@ import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
public class IndefBansEndpoint extends AbstractServlet
|
||||
{
|
||||
public IndefBansEndpoint(HTTPDModule module)
|
||||
{
|
||||
super(module);
|
||||
}
|
||||
|
||||
@GetMapping(endpoint = "/api/indefbans/")
|
||||
public String getBans(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
@@ -20,7 +25,7 @@ public class IndefBansEndpoint extends AbstractServlet
|
||||
}
|
||||
|
||||
response.setHeader("content-type", "application/json");
|
||||
return new GsonBuilder().setPrettyPrinting().create().toJson(HTTPDModule.plexApi().punishments().indefiniteBans());
|
||||
return new GsonBuilder().setPrettyPrinting().create().toJson(module.api().punishments().indefiniteBans());
|
||||
}
|
||||
|
||||
private String indefbansHTML(String message)
|
||||
|
||||
@@ -13,6 +13,11 @@ import java.util.UUID;
|
||||
|
||||
public class IndefBansUIEndpoint extends AbstractServlet
|
||||
{
|
||||
public IndefBansUIEndpoint(HTTPDModule module)
|
||||
{
|
||||
super(module);
|
||||
}
|
||||
|
||||
@GetMapping(endpoint = "/indefbans/")
|
||||
public String getBans(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
@@ -22,7 +27,7 @@ public class IndefBansUIEndpoint extends AbstractServlet
|
||||
return errorHTML(signInPrompt(request, "to view this page"));
|
||||
}
|
||||
|
||||
List<? extends IndefiniteBanView> bans = HTTPDModule.plexApi().punishments().indefiniteBans();
|
||||
List<? extends IndefiniteBanView> bans = module.api().punishments().indefiniteBans();
|
||||
return listHTML(bans);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.plex.request.impl;
|
||||
|
||||
import dev.plex.HTTPDModule;
|
||||
import dev.plex.request.AbstractServlet;
|
||||
import dev.plex.request.GetMapping;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
@@ -7,6 +8,11 @@ import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
public class IndexEndpoint extends AbstractServlet
|
||||
{
|
||||
public IndexEndpoint(HTTPDModule module)
|
||||
{
|
||||
super(module);
|
||||
}
|
||||
|
||||
@GetMapping(endpoint = "//")
|
||||
public String getIndex(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.plex.request.impl;
|
||||
|
||||
import com.google.gson.GsonBuilder;
|
||||
import dev.plex.HTTPDModule;
|
||||
import dev.plex.request.AbstractServlet;
|
||||
import dev.plex.request.GetMapping;
|
||||
import dev.plex.request.MappingHeaders;
|
||||
@@ -14,6 +15,11 @@ import org.bukkit.entity.Player;
|
||||
|
||||
public class ListEndpoint extends AbstractServlet
|
||||
{
|
||||
public ListEndpoint(HTTPDModule module)
|
||||
{
|
||||
super(module);
|
||||
}
|
||||
|
||||
@GetMapping(endpoint = "/api/list/")
|
||||
@MappingHeaders(headers = "content-type;application/json")
|
||||
public String getOnlinePlayers(HttpServletRequest request, HttpServletResponse response)
|
||||
|
||||
@@ -23,6 +23,11 @@ public class PlayerAdminEndpoint extends AbstractServlet
|
||||
{
|
||||
private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm z");
|
||||
|
||||
public PlayerAdminEndpoint(HTTPDModule module)
|
||||
{
|
||||
super(module);
|
||||
}
|
||||
|
||||
@GetMapping(endpoint = "/player/")
|
||||
public String getPlayer(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
@@ -54,15 +59,15 @@ public class PlayerAdminEndpoint extends AbstractServlet
|
||||
return file;
|
||||
}
|
||||
|
||||
private static PlexPlayerView lookupPlayer(String query)
|
||||
private PlexPlayerView lookupPlayer(String query)
|
||||
{
|
||||
try
|
||||
{
|
||||
return HTTPDModule.plexApi().players().byUuid(UUID.fromString(query)).orElse(null);
|
||||
return module.api().players().byUuid(UUID.fromString(query)).orElse(null);
|
||||
}
|
||||
catch (IllegalArgumentException ignored)
|
||||
{
|
||||
return HTTPDModule.plexApi().players().byName(query).orElse(null);
|
||||
return module.api().players().byName(query).orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ import org.bukkit.persistence.PersistentDataContainer;
|
||||
*/
|
||||
public final class PlayerInventoryBroadcaster
|
||||
{
|
||||
private static final PlayerInventoryBroadcaster INSTANCE = new PlayerInventoryBroadcaster();
|
||||
private static final long REFRESH_TICKS = 20L; // 1 second
|
||||
private static final int MAX_NAME_CHARS = 256;
|
||||
private static final int MAX_LORE_LINES = 20;
|
||||
@@ -53,11 +52,7 @@ public final class PlayerInventoryBroadcaster
|
||||
private static final int MAX_PDC_KEYS = 64;
|
||||
private static final int MAX_PDC_KEY_CHARS = 128;
|
||||
|
||||
public static PlayerInventoryBroadcaster get()
|
||||
{
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private final HTTPDModule module;
|
||||
private final Map<UUID, Set<Subscriber>> subscribers = new ConcurrentHashMap<>();
|
||||
private final Map<UUID, String> cachedPayloads = new ConcurrentHashMap<>();
|
||||
private final AtomicInteger subscriberCount = new AtomicInteger();
|
||||
@@ -66,14 +61,17 @@ public final class PlayerInventoryBroadcaster
|
||||
private ScheduledTask refreshTask;
|
||||
private int maxConnections = 32;
|
||||
|
||||
private PlayerInventoryBroadcaster() {}
|
||||
public PlayerInventoryBroadcaster(HTTPDModule module)
|
||||
{
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
public synchronized void start()
|
||||
{
|
||||
if (executor != null) return;
|
||||
|
||||
maxConnections = HTTPDModule.moduleConfig.getInt("server.sse.max-connections", 32);
|
||||
int threads = Math.max(1, HTTPDModule.moduleConfig.getInt("server.sse.threads", 2));
|
||||
maxConnections = module.getModuleConfig().getInt("server.sse.max-connections", 32);
|
||||
int threads = Math.max(1, module.getModuleConfig().getInt("server.sse.threads", 2));
|
||||
|
||||
executor = Executors.newScheduledThreadPool(threads, r ->
|
||||
{
|
||||
@@ -84,11 +82,11 @@ public final class PlayerInventoryBroadcaster
|
||||
|
||||
try
|
||||
{
|
||||
refreshTask = HTTPDModule.plexApi().scheduler().runGlobalTimer(this::tick, 1L, REFRESH_TICKS);
|
||||
refreshTask = module.api().scheduler().runGlobalTimer(this::tick, 1L, REFRESH_TICKS);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
HTTPDModule.plexApi().logging().debug("PlayerInventoryBroadcaster: could not register refresh task: " + t.getMessage());
|
||||
module.api().logging().debug("PlayerInventoryBroadcaster: could not register refresh task: " + t.getMessage());
|
||||
}
|
||||
|
||||
try
|
||||
@@ -97,7 +95,7 @@ public final class PlayerInventoryBroadcaster
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
HTTPDModule.plexApi().logging().debug("PlayerInventoryBroadcaster: NBT-API preload failed: " + t.getMessage());
|
||||
module.api().logging().debug("PlayerInventoryBroadcaster: NBT-API preload failed: " + t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +179,7 @@ public final class PlayerInventoryBroadcaster
|
||||
}
|
||||
try
|
||||
{
|
||||
ScheduledTask task = HTTPDModule.plexApi().scheduler().runEntity(player, () ->
|
||||
ScheduledTask task = module.api().scheduler().runEntity(player, () ->
|
||||
{
|
||||
String json;
|
||||
try
|
||||
|
||||
@@ -36,14 +36,9 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
*/
|
||||
public final class PlayersBroadcaster
|
||||
{
|
||||
private static final PlayersBroadcaster INSTANCE = new PlayersBroadcaster();
|
||||
private static final long REFRESH_TICKS = 100L; // 5 seconds at 20 TPS
|
||||
|
||||
public static PlayersBroadcaster get()
|
||||
{
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private final HTTPDModule module;
|
||||
private final Set<Subscriber> subscribers = ConcurrentHashMap.newKeySet();
|
||||
private final AtomicInteger subscriberCount = new AtomicInteger();
|
||||
private final AtomicBoolean refreshScheduled = new AtomicBoolean(false);
|
||||
@@ -56,14 +51,17 @@ public final class PlayersBroadcaster
|
||||
private Listener listener;
|
||||
private int maxConnections = 32;
|
||||
|
||||
private PlayersBroadcaster() {}
|
||||
public PlayersBroadcaster(HTTPDModule module)
|
||||
{
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
public synchronized void start()
|
||||
{
|
||||
if (executor != null) return;
|
||||
|
||||
maxConnections = HTTPDModule.moduleConfig.getInt("server.sse.max-connections", 32);
|
||||
int threads = Math.max(1, HTTPDModule.moduleConfig.getInt("server.sse.threads", 2));
|
||||
maxConnections = module.getModuleConfig().getInt("server.sse.max-connections", 32);
|
||||
int threads = Math.max(1, module.getModuleConfig().getInt("server.sse.threads", 2));
|
||||
|
||||
executor = Executors.newScheduledThreadPool(threads, r ->
|
||||
{
|
||||
@@ -75,20 +73,20 @@ public final class PlayersBroadcaster
|
||||
listener = new PlayersListener();
|
||||
try
|
||||
{
|
||||
HTTPDModule.plexApi().listeners().register(listener);
|
||||
module.api().listeners().register(listener);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
HTTPDModule.plexApi().logging().debug("PlayersBroadcaster: could not register Bukkit listener: " + t.getMessage());
|
||||
module.api().logging().debug("PlayersBroadcaster: could not register Bukkit listener: " + t.getMessage());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
refreshTask = HTTPDModule.plexApi().scheduler().runGlobalTimer(this::refreshAndBroadcast, 1L, REFRESH_TICKS);
|
||||
refreshTask = module.api().scheduler().runGlobalTimer(this::refreshAndBroadcast, 1L, REFRESH_TICKS);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
HTTPDModule.plexApi().logging().debug("PlayersBroadcaster: could not register refresh task: " + t.getMessage());
|
||||
module.api().logging().debug("PlayersBroadcaster: could not register refresh task: " + t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,7 +171,7 @@ public final class PlayersBroadcaster
|
||||
Player player = online.get(i);
|
||||
try
|
||||
{
|
||||
ScheduledTask task = HTTPDModule.plexApi().scheduler().runEntity(player, () ->
|
||||
ScheduledTask task = module.api().scheduler().runEntity(player, () ->
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -276,7 +274,7 @@ public final class PlayersBroadcaster
|
||||
if (!refreshScheduled.compareAndSet(false, true)) return;
|
||||
try
|
||||
{
|
||||
HTTPDModule.plexApi().scheduler().runGlobalLater(() ->
|
||||
module.api().scheduler().runGlobalLater(() ->
|
||||
{
|
||||
refreshScheduled.set(false);
|
||||
refreshAndBroadcast();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.plex.request.impl;
|
||||
|
||||
import dev.plex.HTTPDModule;
|
||||
import dev.plex.request.AbstractServlet;
|
||||
import dev.plex.request.GetMapping;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
@@ -7,6 +8,11 @@ import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
public class PlayersEndpoint extends AbstractServlet
|
||||
{
|
||||
public PlayersEndpoint(HTTPDModule module)
|
||||
{
|
||||
super(module);
|
||||
}
|
||||
|
||||
@GetMapping(endpoint = "/players/")
|
||||
public String getPlayers(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
|
||||
@@ -16,6 +16,11 @@ import java.util.UUID;
|
||||
|
||||
public class PunishmentsEndpoint extends AbstractServlet
|
||||
{
|
||||
public PunishmentsEndpoint(HTTPDModule module)
|
||||
{
|
||||
super(module);
|
||||
}
|
||||
|
||||
@GetMapping(endpoint = "/api/punishments/")
|
||||
public String getPunishments(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
@@ -28,11 +33,11 @@ public class PunishmentsEndpoint extends AbstractServlet
|
||||
try
|
||||
{
|
||||
UUID pathUUID = UUID.fromString(request.getPathInfo().replace("/", ""));
|
||||
punishedPlayer = HTTPDModule.plexApi().players().byUuid(pathUUID).orElse(null);
|
||||
punishedPlayer = module.api().players().byUuid(pathUUID).orElse(null);
|
||||
}
|
||||
catch (IllegalArgumentException ignored)
|
||||
{
|
||||
punishedPlayer = HTTPDModule.plexApi().players().byName(request.getPathInfo().replace("/", "")).orElse(null);
|
||||
punishedPlayer = module.api().players().byName(request.getPathInfo().replace("/", "")).orElse(null);
|
||||
}
|
||||
|
||||
if (punishedPlayer == null)
|
||||
|
||||
@@ -18,6 +18,11 @@ public class PunishmentsUIEndpoint extends AbstractServlet
|
||||
{
|
||||
private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm z");
|
||||
|
||||
public PunishmentsUIEndpoint(HTTPDModule module)
|
||||
{
|
||||
super(module);
|
||||
}
|
||||
|
||||
@GetMapping(endpoint = "/punishments/")
|
||||
public String getPunishments(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
@@ -49,15 +54,15 @@ public class PunishmentsUIEndpoint extends AbstractServlet
|
||||
return resultsHTML(punished, punishments, showIps);
|
||||
}
|
||||
|
||||
private static PlexPlayerView lookupPlayer(String query)
|
||||
private PlexPlayerView lookupPlayer(String query)
|
||||
{
|
||||
try
|
||||
{
|
||||
return HTTPDModule.plexApi().players().byUuid(UUID.fromString(query)).orElse(null);
|
||||
return module.api().players().byUuid(UUID.fromString(query)).orElse(null);
|
||||
}
|
||||
catch (IllegalArgumentException ignored)
|
||||
{
|
||||
return HTTPDModule.plexApi().players().byName(query).orElse(null);
|
||||
return module.api().players().byName(query).orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,11 @@ public class SchematicDownloadEndpoint extends AbstractServlet
|
||||
{
|
||||
List<File> files = new ArrayList<>();
|
||||
|
||||
public SchematicDownloadEndpoint(HTTPDModule module)
|
||||
{
|
||||
super(module);
|
||||
}
|
||||
|
||||
@GetMapping(endpoint = "/api/schematics/download/")
|
||||
public String downloadSchematic(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
@@ -57,7 +62,7 @@ public class SchematicDownloadEndpoint extends AbstractServlet
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] schemData = HTTPDModule.fileCache.getFile(schemFile);
|
||||
byte[] schemData = module.getFileCache().getFile(schemFile);
|
||||
if (schemData != null)
|
||||
{
|
||||
outputStream.write(schemData);
|
||||
@@ -71,11 +76,11 @@ public class SchematicDownloadEndpoint extends AbstractServlet
|
||||
}
|
||||
}
|
||||
|
||||
private static void logDownload(HttpServletRequest request, File schemFile)
|
||||
private void logDownload(HttpServletRequest request, File schemFile)
|
||||
{
|
||||
AuthenticatedUser user = currentUser(request);
|
||||
String who = user != null ? user.username() + " (xf:" + user.userId() + ")" : request.getRemoteAddr();
|
||||
HTTPDModule.plexApi().logging().info("{0} downloaded schematic {1}", who, schemFile.getName());
|
||||
module.api().logging().info("{0} downloaded schematic {1}", who, schemFile.getName());
|
||||
Log.log("{0} downloaded schematic {1}", who, schemFile.getName());
|
||||
}
|
||||
|
||||
@@ -118,7 +123,7 @@ public class SchematicDownloadEndpoint extends AbstractServlet
|
||||
{
|
||||
if (fileEntry.isDirectory())
|
||||
{
|
||||
HTTPDModule.plexApi().logging().debug("Found directory");
|
||||
module.api().logging().debug("Found directory");
|
||||
listFilesForFolder(fileEntry);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.plex.request.impl;
|
||||
|
||||
import dev.plex.HTTPDModule;
|
||||
import dev.plex.authentication.AuthenticatedUser;
|
||||
import dev.plex.request.AbstractServlet;
|
||||
import dev.plex.request.GetMapping;
|
||||
@@ -8,6 +9,11 @@ import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
public class SchematicUploadEndpoint extends AbstractServlet
|
||||
{
|
||||
public SchematicUploadEndpoint(HTTPDModule module)
|
||||
{
|
||||
super(module);
|
||||
}
|
||||
|
||||
@GetMapping(endpoint = "/api/schematics/upload/")
|
||||
public String uploadSchematic(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
|
||||
@@ -27,13 +27,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
*/
|
||||
public final class StatsBroadcaster
|
||||
{
|
||||
private static final StatsBroadcaster INSTANCE = new StatsBroadcaster();
|
||||
|
||||
public static StatsBroadcaster get()
|
||||
{
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private final HTTPDModule module;
|
||||
private final Set<Subscriber> subscribers = ConcurrentHashMap.newKeySet();
|
||||
private final AtomicInteger subscriberCount = new AtomicInteger();
|
||||
|
||||
@@ -58,15 +52,18 @@ public final class StatsBroadcaster
|
||||
private int maxConnections = 32;
|
||||
private long broadcastIntervalMs = 2000L;
|
||||
|
||||
private StatsBroadcaster() {}
|
||||
public StatsBroadcaster(HTTPDModule module)
|
||||
{
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
public synchronized void start()
|
||||
{
|
||||
if (executor != null) return;
|
||||
|
||||
maxConnections = HTTPDModule.moduleConfig.getInt("server.sse.max-connections", 32);
|
||||
broadcastIntervalMs = HTTPDModule.moduleConfig.getLong("server.sse.broadcast-interval-ms", 2000L);
|
||||
int threads = Math.max(1, HTTPDModule.moduleConfig.getInt("server.sse.threads", 2));
|
||||
maxConnections = module.getModuleConfig().getInt("server.sse.max-connections", 32);
|
||||
broadcastIntervalMs = module.getModuleConfig().getLong("server.sse.broadcast-interval-ms", 2000L);
|
||||
int threads = Math.max(1, module.getModuleConfig().getInt("server.sse.threads", 2));
|
||||
|
||||
executor = Executors.newScheduledThreadPool(threads, r ->
|
||||
{
|
||||
@@ -77,11 +74,11 @@ public final class StatsBroadcaster
|
||||
|
||||
try
|
||||
{
|
||||
bukkitTask = HTTPDModule.plexApi().scheduler().runGlobalTimer(this::sampleBukkit, 1L, 40L);
|
||||
bukkitTask = module.api().scheduler().runGlobalTimer(this::sampleBukkit, 1L, 40L);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
HTTPDModule.plexApi().logging().debug("StatsBroadcaster: could not register Bukkit sampling task: " + t.getMessage());
|
||||
module.api().logging().debug("StatsBroadcaster: could not register Bukkit sampling task: " + t.getMessage());
|
||||
}
|
||||
|
||||
broadcastTask = executor.scheduleAtFixedRate(
|
||||
|
||||
Reference in New Issue
Block a user