From 1c38ef2a5e3fb11b2ca7b14fc431013f0aeb7242 Mon Sep 17 00:00:00 2001 From: Ryan Barlow <7389646+ryanbarlow97@users.noreply.github.com> Date: Tue, 13 Oct 2026 13:55:18 +0000 Subject: [PATCH] Add the will request routes to the realm allow-list The ProvinceSystem will pull (GET /characters/plugin/wills/pending) now gets realm_id in its query and the ack (POST /characters/plugin/wills/applied) gets it in its body. RPCharacters passes the realm itself; this is the second guard, and an explicit realm is left untouched. Co-Authored-By: Claude Opus 5.5 --- .../tfmcweb/api/ProvinceSystemGateway.java | 6 +++-- .../api/ProvinceSystemGatewayTest.java | 23 +++++++++++++++++-- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/tfminecraft/tfmcweb/api/ProvinceSystemGateway.java b/src/main/java/net/tfminecraft/tfmcweb/api/ProvinceSystemGateway.java index 2ac1256..d7add1b 100644 --- a/src/main/java/net/tfminecraft/tfmcweb/api/ProvinceSystemGateway.java +++ b/src/main/java/net/tfminecraft/tfmcweb/api/ProvinceSystemGateway.java @@ -210,7 +210,8 @@ private static boolean needsRealmQuery(String method, String barePath) { return equalsPath(barePath, "/characters/plugin/pending") || equalsPath(barePath, "/skins/plugin/approved") || equalsPath(barePath, "/drinks/plugin/pending-apply") - || equalsPath(barePath, "/characters/plugin/lore-items/pending"); + || equalsPath(barePath, "/characters/plugin/lore-items/pending") + || equalsPath(barePath, "/characters/plugin/wills/pending"); } private static boolean needsRealmBody(String method, String barePath) { @@ -223,7 +224,8 @@ private static boolean needsRealmBody(String method, String barePath) { // code from being spent on the live realm without a new plugin config key. if ("POST".equals(method)) { return equalsPath(barePath, "/wars/declare-codes/validate") - || equalsPath(barePath, "/wars/declare-codes/redeem"); + || equalsPath(barePath, "/wars/declare-codes/redeem") + || equalsPath(barePath, "/characters/plugin/wills/applied"); } return false; } diff --git a/src/test/java/net/tfminecraft/tfmcweb/api/ProvinceSystemGatewayTest.java b/src/test/java/net/tfminecraft/tfmcweb/api/ProvinceSystemGatewayTest.java index 7bb57f5..3152abb 100644 --- a/src/test/java/net/tfminecraft/tfmcweb/api/ProvinceSystemGatewayTest.java +++ b/src/test/java/net/tfminecraft/tfmcweb/api/ProvinceSystemGatewayTest.java @@ -52,7 +52,7 @@ class ProvinceSystemGatewayTest { @Test void injectsQueryOnlyOnAllowlistedGetsAndPreservesExplicitRealm() { assertNull(ProvinceSystemGateway.injectRealmPath("GET", null)); assertEquals(" ", ProvinceSystemGateway.injectRealmPath("GET", " ")); - for (String path : List.of("/characters/plugin/pending", "/skins/plugin/approved", "/drinks/plugin/pending-apply", "/characters/plugin/lore-items/pending")) { + for (String path : List.of("/characters/plugin/pending", "/skins/plugin/approved", "/drinks/plugin/pending-apply", "/characters/plugin/lore-items/pending", "/characters/plugin/wills/pending")) { assertEquals(path+"?realm_id=dev", ProvinceSystemGateway.injectRealmPath("GET", path)); assertEquals(path+"/?realm_id=dev", ProvinceSystemGateway.injectRealmPath("GET", path+"/")); assertEquals(path+"?a=1&realm_id=dev", ProvinceSystemGateway.injectRealmPath("GET", path+"?a=1")); @@ -67,7 +67,7 @@ class ProvinceSystemGatewayTest { } @Test void injectsBodiesOnlyOnAllowlistedWrites() { for (String method : List.of("PUT", "POST")) { - List paths = method.equals("PUT") ? List.of("/characters/plugin/roster", "/characters/plugin/rpc-player-meta") : List.of("/wars/declare-codes/validate", "/wars/declare-codes/redeem"); + List paths = method.equals("PUT") ? List.of("/characters/plugin/roster", "/characters/plugin/rpc-player-meta") : List.of("/wars/declare-codes/validate", "/wars/declare-codes/redeem", "/characters/plugin/wills/applied"); for (String path : paths) { assertEquals("{\"realm_id\":\"dev\"}", ProvinceSystemGateway.injectRealmBody(method, path, "{}")); assertEquals("{\"a\":1,\"realm_id\":\"dev\"}", ProvinceSystemGateway.injectRealmBody(method, path+"?x=1", " { \"a\":1 } ")); @@ -79,6 +79,25 @@ class ProvinceSystemGatewayTest { assertEquals("{}", ProvinceSystemGateway.injectRealmBody("PUT", "/other", "{}")); assertEquals("{}", ProvinceSystemGateway.injectRealmBody("PUT", null, "{}")); } + @Test void willRoutesCarryTheRealmAndKeepAnExplicitOne() throws Exception { + http.reply(200, "{\"requests\":[]}"); + assertTrue(ProvinceSystemGateway.request("GET", "/characters/plugin/wills/pending", null).ok); + assertEquals("/characters/plugin/wills/pending?realm_id=dev", http.request().path()); + http.reply(200, "{\"requests\":[]}"); + assertTrue(ProvinceSystemGateway.request("GET", "/characters/plugin/wills/pending?realm_id=main", null).ok); + assertEquals("/characters/plugin/wills/pending?realm_id=main", http.request().path()); + http.reply(200, "{\"ok\":true}"); + assertTrue(ProvinceSystemGateway.request("POST", "/characters/plugin/wills/applied", "{\"results\":[]}").ok); + var injected = com.google.gson.JsonParser.parseString(http.request().body()).getAsJsonObject(); + assertEquals("dev", injected.get("realm_id").getAsString()); assertTrue(injected.get("results").isJsonArray()); + http.reply(200, "{\"ok\":true}"); + assertTrue(ProvinceSystemGateway.request("POST", "/characters/plugin/wills/applied", "{\"realm_id\":\"main\",\"results\":[]}").ok); + assertEquals("{\"realm_id\":\"main\",\"results\":[]}", http.request().body()); + // The pull is GET-only and the ack is POST-only. + assertEquals("/characters/plugin/wills/applied", ProvinceSystemGateway.injectRealmPath("GET", "/characters/plugin/wills/applied")); + assertEquals("{}", ProvinceSystemGateway.injectRealmBody("PUT", "/characters/plugin/wills/applied", "{}")); + assertEquals("{}", ProvinceSystemGateway.injectRealmBody("POST", "/characters/plugin/wills/pending", "{}")); + } @Test void patchWorksOnSupportedJavaWithoutOpeningJdkModules() throws Exception { http.reply(200, "patched"); var result = ProvinceSystemGateway.request("PATCH", "/resource", "{}");