From 72f6e7a06933045882e5ca2ce2ff7f94c4380873 Mon Sep 17 00:00:00 2001 From: BitterPanda Date: Mon, 7 Jul 2025 13:13:47 +0200 Subject: [PATCH 1/2] Add support for Object IDs and ULIDs in route building --- .../agent_api/helpers/url/BuildRouteFromUrl.java | 8 +++++++- .../test/java/helpers/BuildRouteFromUrlTest.java | 13 ++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/agent_api/src/main/java/dev/aikido/agent_api/helpers/url/BuildRouteFromUrl.java b/agent_api/src/main/java/dev/aikido/agent_api/helpers/url/BuildRouteFromUrl.java index fa5604592..e7b054784 100644 --- a/agent_api/src/main/java/dev/aikido/agent_api/helpers/url/BuildRouteFromUrl.java +++ b/agent_api/src/main/java/dev/aikido/agent_api/helpers/url/BuildRouteFromUrl.java @@ -12,6 +12,8 @@ private BuildRouteFromUrl() {} private static final Pattern UUID_REGEX = Pattern.compile( "[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff", Pattern.CASE_INSENSITIVE); + private static final Pattern OBJECT_ID_REGEX = Pattern.compile("^[0-9a-f]{24}$", Pattern.CASE_INSENSITIVE); + private static final Pattern ULID_REGEX = Pattern.compile("^[0-9A-HJKMNP-TV-Z]{26}$", Pattern.CASE_INSENSITIVE); private static final Pattern NUMBER_REGEX = Pattern.compile("^\\d+$"); private static final Pattern DATE_REGEX = Pattern.compile("^\\d{4}-\\d{2}-\\d{2}|\\d{2}-\\d{2}-\\d{4}$"); private static final Pattern EMAIL_REGEX = Pattern.compile( @@ -57,6 +59,10 @@ private static String replaceUrlSegmentWithParam(String segment) { return ":number"; } else if (segment.length() == 36 && UUID_REGEX.matcher(segment).matches()) { return ":uuid"; + } else if (segment.length() == 26 && ULID_REGEX.matcher(segment).matches()) { + return ":ulid"; + } else if (segment.length() == 24 && OBJECT_ID_REGEX.matcher(segment).matches()) { + return ":objectId"; } else if (startsWithNumber && DATE_REGEX.matcher(segment).matches()) { return ":date"; } else if (segment.contains("@") && EMAIL_REGEX.matcher(segment).matches()) { @@ -82,4 +88,4 @@ private static boolean isHash(String segment) { } return false; } -} \ No newline at end of file +} diff --git a/agent_api/src/test/java/helpers/BuildRouteFromUrlTest.java b/agent_api/src/test/java/helpers/BuildRouteFromUrlTest.java index 64a85c350..d484ae9f9 100644 --- a/agent_api/src/test/java/helpers/BuildRouteFromUrlTest.java +++ b/agent_api/src/test/java/helpers/BuildRouteFromUrlTest.java @@ -126,4 +126,15 @@ public void testReplaceHashes() { public void testReplaceSecrets() { assertEquals("/confirm/:secret", buildRouteFromUrl("/confirm/CnJ4DunhYfv2db6T1FRfciRBHtlNKOYrjoz")); } -} \ No newline at end of file + + @Test + public void testReplacesBsonObjectIds() { + assertEquals("/posts/:objectId", buildRouteFromUrl("/posts/66ec29159d00113616fc7184")); + } + + @Test + public void testReplacesUlidStrings() { + assertEquals("/posts/:ulid", buildRouteFromUrl("/posts/01ARZ3NDEKTSV4RRFFQ69G5FAV")); + assertEquals("/posts/:ulid", buildRouteFromUrl("/posts/01arz3ndektsv4rrffq69g5fav")); + } +} From 49bba9b0d5ac7700fa941a5aee9d954d69380514 Mon Sep 17 00:00:00 2001 From: BitterPanda Date: Mon, 7 Jul 2025 13:19:46 +0200 Subject: [PATCH 2/2] Add tests that check character length is verified --- .../src/test/java/helpers/BuildRouteFromUrlTest.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/agent_api/src/test/java/helpers/BuildRouteFromUrlTest.java b/agent_api/src/test/java/helpers/BuildRouteFromUrlTest.java index d484ae9f9..7f6dd9a91 100644 --- a/agent_api/src/test/java/helpers/BuildRouteFromUrlTest.java +++ b/agent_api/src/test/java/helpers/BuildRouteFromUrlTest.java @@ -6,8 +6,7 @@ import java.security.NoSuchAlgorithmException; import static dev.aikido.agent_api.helpers.url.BuildRouteFromUrl.buildRouteFromUrl; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.*; public class BuildRouteFromUrlTest { @@ -130,11 +129,19 @@ public void testReplaceSecrets() { @Test public void testReplacesBsonObjectIds() { assertEquals("/posts/:objectId", buildRouteFromUrl("/posts/66ec29159d00113616fc7184")); + // 25 characters : + assertNotEquals("/posts/:objectId", buildRouteFromUrl("/posts/66ec29159d00113616fc71845")); + // 23 characters : + assertNotEquals("/posts/:objectId", buildRouteFromUrl("/posts/66ec29159d00113616fc718")); } @Test public void testReplacesUlidStrings() { assertEquals("/posts/:ulid", buildRouteFromUrl("/posts/01ARZ3NDEKTSV4RRFFQ69G5FAV")); assertEquals("/posts/:ulid", buildRouteFromUrl("/posts/01arz3ndektsv4rrffq69g5fav")); + // 27 characters : + assertNotEquals("/posts/:ulid", buildRouteFromUrl("/posts/01arz3ndektsv4rrffq69g5favv")); + // 25 characters : + assertNotEquals("/posts/:ulid", buildRouteFromUrl("/posts/01arz3ndektsv4rrffq69g5fa")); } }