Skip to content

Commit 7369f2c

Browse files
authored
Merge pull request #62 from prime-framework/degroff/npe_test
Test to cause NPE in ResourceBundleMessageProvider.findMessage
2 parents 334092d + ba480ee commit 7369f2c

File tree

6 files changed

+69
-45
lines changed

6 files changed

+69
-45
lines changed

.github/workflows/build.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ jobs:
1515
uses: actions/checkout@v4
1616
- name: savant setup
1717
run: |
18-
curl -O https://repository.savantbuild.org/org/savantbuild/savant-core/2.0.0-RC.7/savant-2.0.0-RC.7.tar.gz
19-
tar xzvf savant-2.0.0-RC.7.tar.gz
20-
savant-2.0.0-RC.7/bin/sb --version
21-
SAVANT_PATH=$(realpath -s "./savant-2.0.0-RC.7/bin")
18+
curl -O https://repository.savantbuild.org/org/savantbuild/savant-core/2.0.0/savant-2.0.0.tar.gz
19+
tar xzvf savant-2.0.0.tar.gz
20+
savant-2.0.0/bin/sb --version
21+
SAVANT_PATH=$(realpath -s "./savant-2.0.0/bin")
2222
echo "${SAVANT_PATH}" >> $GITHUB_PATH
2323
mkdir -p ~/.savant/plugins
2424
# For now, using the JDK that comes on the GHA runner

build.savant

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ logbackVersion = "1.4.14"
2929
slf4jVersion = "2.0.13"
3030
testngVersion = "7.8.0"
3131

32-
project(group: "org.primeframework", name: "prime-mvc", version: "4.26.0", licenses: ["ApacheV2_0"]) {
32+
project(group: "org.primeframework", name: "prime-mvc", version: "4.26.1", licenses: ["ApacheV2_0"]) {
3333
workflow {
3434
fetch {
3535
// Dependency resolution order:
@@ -99,13 +99,13 @@ project(group: "org.primeframework", name: "prime-mvc", version: "4.26.0", licen
9999
}
100100

101101
// Plugins
102-
file = loadPlugin(id: "org.savantbuild.plugin:file:2.0.0-RC.7")
103-
dependency = loadPlugin(id: "org.savantbuild.plugin:dependency:2.0.0-RC.7")
104-
java = loadPlugin(id: "org.savantbuild.plugin:java:2.0.0-RC.6")
105-
javaTestNG = loadPlugin(id: "org.savantbuild.plugin:java-testng:2.0.0-RC.6")
106-
idea = loadPlugin(id: "org.savantbuild.plugin:idea:2.0.0-RC.7")
107-
pom = loadPlugin(id: "org.savantbuild.plugin:pom:2.0.0-RC.6")
108-
release = loadPlugin(id: "org.savantbuild.plugin:release-git:2.0.0-RC.6")
102+
file = loadPlugin(id: "org.savantbuild.plugin:file:2.0.0")
103+
dependency = loadPlugin(id: "org.savantbuild.plugin:dependency:2.0.0")
104+
java = loadPlugin(id: "org.savantbuild.plugin:java:2.0.0")
105+
javaTestNG = loadPlugin(id: "org.savantbuild.plugin:java-testng:2.0.0")
106+
idea = loadPlugin(id: "org.savantbuild.plugin:idea:2.0.0")
107+
pom = loadPlugin(id: "org.savantbuild.plugin:pom:2.0.0")
108+
release = loadPlugin(id: "org.savantbuild.plugin:release-git:2.0.0")
109109

110110
// Plugin settings
111111
java.settings.javaVersion = "17"

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
<groupId>org.primeframework</groupId>
77
<artifactId>prime-mvc</artifactId>
8-
<version>4.26.0</version>
8+
<version>4.26.1</version>
99
<packaging>jar</packaging>
1010

1111
<name>FusionAuth App</name>

src/main/java/org/primeframework/mvc/message/l10n/ResourceBundleMessageProvider.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ protected String findMessage(ActionInvocation actionInvocation, String key) {
137137
}
138138

139139
ActionConfiguration config = actionInvocation.configuration;
140+
if (config == null) {
141+
return null;
142+
}
143+
140144
return config.alternateMessageURIs.stream()
141145
.map(uri -> findMessage(uri, key))
142146
.filter(Objects::nonNull)

src/test/java/org/primeframework/mvc/GlobalTest.java

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,33 @@ public void escapePathSegmentsWithWildCard() throws Exception {
183183
"theRest=foo bar,foobar,foo bar,foo@bar"));
184184
}
185185

186+
@Test
187+
public void flash_scope_compatibility() throws Exception {
188+
// Use case: MVC is able to decrypt a flash message cookie that was encrypted with legacy methods
189+
// Create a SimpleMessage, serialize, encrypt, and encode. The message text is hard-coded here because there is no context to look up the message.
190+
var message = new SimpleMessage(MessageType.INFO, "[FlashScopeMessageKey]", "This is a message!");
191+
// Serialize List<Message>
192+
var serialized = objectMapper.writeValueAsBytes(List.of(message));
193+
// Instantiate DefaultEncryptor with two copies of CBCCipherProvider to encrypt with CBC
194+
Encryptor cbcEncryptor = new DefaultEncryptor(new CBCCipherProvider(configuration), new CBCCipherProvider(configuration));
195+
var encrypted = cbcEncryptor.encrypt(serialized);
196+
var encoded = Base64.getUrlEncoder().encodeToString(encrypted);
197+
198+
simulator.test("/flash-scope/")
199+
.withCookie(configuration.messageFlashScopeCookieName(), encoded)
200+
.get()
201+
.assertStatusCode(200)
202+
.assertContainsGeneralMessageCodes(MessageType.INFO, "[FlashScopeMessageKey]")
203+
.assertBodyContainsMessagesFromKey("[FlashScopeMessageKey]")
204+
.assertBody("""
205+
This is an index page.
206+
207+
Info:This is a message!
208+
209+
""")
210+
;
211+
}
212+
186213
@Test
187214
public void get() throws Exception {
188215
// Not called yet
@@ -1038,40 +1065,13 @@ public void get_redirect_flash_scope_messageLookup() throws Exception {
10381065
.assertBodyContainsMessagesFromKey("[FlashScopeMessageKey]")
10391066
.assertBody("""
10401067
This is an index page.
1041-
1068+
10421069
Info:This is a message!
1043-
1070+
10441071
""")
10451072
);
10461073
}
10471074

1048-
@Test
1049-
public void flash_scope_compatibility() throws Exception {
1050-
// Use case: MVC is able to decrypt a flash message cookie that was encrypted with legacy methods
1051-
// Create a SimpleMessage, serialize, encrypt, and encode. The message text is hard-coded here because there is no context to look up the message.
1052-
var message = new SimpleMessage(MessageType.INFO, "[FlashScopeMessageKey]", "This is a message!");
1053-
// Serialize List<Message>
1054-
var serialized = objectMapper.writeValueAsBytes(List.of(message));
1055-
// Instantiate DefaultEncryptor with two copies of CBCCipherProvider to encrypt with CBC
1056-
Encryptor cbcEncryptor = new DefaultEncryptor(new CBCCipherProvider(configuration), new CBCCipherProvider(configuration));
1057-
var encrypted = cbcEncryptor.encrypt(serialized);
1058-
var encoded = Base64.getUrlEncoder().encodeToString(encrypted);
1059-
1060-
simulator.test("/flash-scope/")
1061-
.withCookie(configuration.messageFlashScopeCookieName(), encoded)
1062-
.get()
1063-
.assertStatusCode(200)
1064-
.assertContainsGeneralMessageCodes(MessageType.INFO, "[FlashScopeMessageKey]")
1065-
.assertBodyContainsMessagesFromKey("[FlashScopeMessageKey]")
1066-
.assertBody("""
1067-
This is an index page.
1068-
1069-
Info:This is a message!
1070-
1071-
""")
1072-
;
1073-
}
1074-
10751075
@Test
10761076
public void get_redirect_withActual() throws Exception {
10771077
// Contains no parameters
@@ -1100,6 +1100,12 @@ public void get_template_noAction() throws Exception {
11001100
.assertStatusCode(200)
11011101
.assertBodyContains("Yo, nice template.");
11021102

1103+
// uses a message key that's not found
1104+
simulator.test("/freemarker/missing-message-template")
1105+
.get()
1106+
.assertStatusCode(200)
1107+
.assertBodyContains("Yo, nice template.", "the default message");
1108+
11031109
// Double slash, redirect to the correct location
11041110
simulator.test("/freemarker//stand-alone-template")
11051111
.get()
@@ -1961,7 +1967,7 @@ public void post_jsonContentType() throws Exception {
19611967
"message" : "Invalid [Content-Type] HTTP request header value of [application/test+json]. Supported values for this request include [application/json]."
19621968
} ]
19631969
}
1964-
""");
1970+
""");
19651971

19661972
// Patch not supported on this endpoint
19671973
simulator.test("/json-content-type-no-restriction")
@@ -1981,7 +1987,7 @@ public void post_jsonContentType() throws Exception {
19811987
"message" : "The [Content-Type] HTTP request header value of [application/json-patch+json] is not supported for this request."
19821988
} ]
19831989
}
1984-
""");
1990+
""");
19851991

19861992
// Missing Content-Type Header
19871993
simulator.test("/json-content-type")
@@ -2028,7 +2034,7 @@ public void post_jsonContentType() throws Exception {
20282034
"message" : "Invalid [Content-Type] HTTP request header value of [application/klingon]. Supported values for this request include [application/json]."
20292035
} ]
20302036
}
2031-
""");
2037+
""");
20322038

20332039
// Not supported in general
20342040
simulator.test("/json-content-type-no-restriction")
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<html lang="en_US">
2+
<body>
3+
<div>
4+
Yo, nice template.
5+
[#--
6+
Use case: We have a template that:
7+
1. Is rendered directly from a HTTP GET (/freemarker/missing-message-template), without an action class
8+
2. Specifies a message key that does not exist in the action URI search path.
9+
3. Tries to specify a default message in case the message key does not exist.
10+
--]
11+
<span>[@control.message key="testing" default="the default message"/]</span>
12+
</div>
13+
</body>
14+
</html>

0 commit comments

Comments
 (0)