Skip to content

Commit e23a828

Browse files
authored
fix: Check DisabledUpdateMode and isVisible in element request validation (#21427)
This takes into account the DisabledUpdateMode parameter of ElementRequestHandler and isVisible property of the owner element when validating the request in StreamRequestHandler.
1 parent d563e44 commit e23a828

File tree

2 files changed

+173
-9
lines changed

2 files changed

+173
-9
lines changed

flow-server/src/main/java/com/vaadin/flow/server/communication/StreamRequestHandler.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.slf4j.LoggerFactory;
2727

2828
import com.vaadin.flow.component.UI;
29+
import com.vaadin.flow.dom.DisabledUpdateMode;
2930
import com.vaadin.flow.dom.Element;
3031
import com.vaadin.flow.internal.StateNode;
3132
import com.vaadin.flow.internal.UrlUtil;
@@ -40,7 +41,6 @@
4041
import com.vaadin.flow.server.VaadinRequest;
4142
import com.vaadin.flow.server.VaadinResponse;
4243
import com.vaadin.flow.server.VaadinSession;
43-
import com.vaadin.flow.server.frontend.FrontendUtils;
4444
import com.vaadin.flow.server.streams.UploadHandler;
4545

4646
import static com.vaadin.flow.server.Constants.DEFAULT_FILE_COUNT_MAX;
@@ -138,9 +138,9 @@ private void callElementResourceHandler(VaadinSession session,
138138
Element owner = elementRequest.getOwner();
139139
StateNode node = owner.getNode();
140140

141-
if ((node.isInert()
142-
&& !elementRequest.getElementRequestHandler().allowInert())
143-
|| !node.isAttached() || !node.isEnabled()) {
141+
if (blockInert(elementRequest, node)
142+
|| blockDisabled(elementRequest, node) || !node.isAttached()
143+
|| !node.isVisible()) {
144144
response.sendError(HttpStatusCode.FORBIDDEN.getCode(),
145145
"Resource not available");
146146
return;
@@ -195,6 +195,20 @@ private void callElementResourceHandler(VaadinSession session,
195195
response, session, elementRequest.getOwner());
196196
}
197197

198+
private static boolean blockDisabled(
199+
StreamResourceRegistry.ElementStreamResource elementRequest,
200+
StateNode node) {
201+
return !node.isEnabled() && elementRequest.getElementRequestHandler()
202+
.getDisabledUpdateMode() == DisabledUpdateMode.ONLY_WHEN_ENABLED;
203+
}
204+
205+
private static boolean blockInert(
206+
StreamResourceRegistry.ElementStreamResource elementRequest,
207+
StateNode node) {
208+
return node.isInert()
209+
&& !elementRequest.getElementRequestHandler().allowInert();
210+
}
211+
198212
private record PathData(String UIid, String securityKey, String fileName) {
199213
}
200214

flow-server/src/test/java/com/vaadin/flow/server/communication/StreamRequestHandlerTest.java

Lines changed: 155 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@
1515
import org.mockito.Mockito;
1616

1717
import com.vaadin.flow.component.UI;
18+
import com.vaadin.flow.dom.DisabledUpdateMode;
1819
import com.vaadin.flow.dom.Element;
1920
import com.vaadin.flow.internal.CurrentInstance;
2021
import com.vaadin.flow.internal.StateNode;
22+
import com.vaadin.flow.server.VaadinRequest;
23+
import com.vaadin.flow.server.VaadinSession;
2124
import com.vaadin.flow.server.streams.ElementRequestHandler;
2225
import com.vaadin.flow.server.MockVaadinServletService;
2326
import com.vaadin.flow.server.MockVaadinSession;
@@ -143,6 +146,43 @@ public void stateNodeStates_handlerMustNotReplyWhenNodeDisabled()
143146
Mockito.verify(response).sendError(403, "Resource not available");
144147
}
145148

149+
@Test
150+
public void nodeDisabled_shouldReplyForDisabledUpdateModeAlways()
151+
throws IOException {
152+
TestElementHandlerBuilder builder = new TestElementHandlerBuilder()
153+
.withDisabledUpdateMode(DisabledUpdateMode.ALWAYS);
154+
stateNodeStatesTestInternal(builder);
155+
Mockito.verify(response, Mockito.never()).sendError(Mockito.anyInt(),
156+
Mockito.anyString());
157+
}
158+
159+
@Test
160+
public void nodeInert_shouldRespondWithResourceNotAvailable()
161+
throws IOException {
162+
TestElementHandlerBuilder builder = new TestElementHandlerBuilder()
163+
.withInert(true);
164+
stateNodeStatesTestInternal(builder);
165+
Mockito.verify(response).sendError(403, "Resource not available");
166+
}
167+
168+
@Test
169+
public void nodeInert_handlerShouldReplyForAllowInert() throws IOException {
170+
TestElementHandlerBuilder builder = new TestElementHandlerBuilder()
171+
.withInert(true).withAllowInert(true);
172+
stateNodeStatesTestInternal(builder);
173+
Mockito.verify(response, Mockito.never()).sendError(Mockito.anyInt(),
174+
Mockito.anyString());
175+
}
176+
177+
@Test
178+
public void nodeHidden_shouldRespondWithResourceNotAvailable()
179+
throws IOException {
180+
TestElementHandlerBuilder builder = new TestElementHandlerBuilder()
181+
.withVisible(false);
182+
stateNodeStatesTestInternal(builder);
183+
Mockito.verify(response).sendError(403, "Resource not available");
184+
}
185+
146186
@Test
147187
public void stateNodeStates_handlerMustNotReplyWhenNodeDetached()
148188
throws IOException {
@@ -160,16 +200,30 @@ public void stateNodeStates_handlerMustReplyWhenNodeAttachedAndEnabled()
160200

161201
private VaadinResponse stateNodeStatesTestInternal(boolean enabled,
162202
boolean attached) throws IOException {
163-
ElementRequestHandler stateHandler = (request, response, session,
164-
owner) -> {
165-
};
203+
TestElementHandlerBuilder builder = new TestElementHandlerBuilder()
204+
.withEnalbed(enabled).withAttached(attached);
205+
return stateNodeStatesTestInternal(builder);
206+
}
207+
208+
private VaadinResponse stateNodeStatesTestInternal(
209+
TestElementHandlerBuilder builder) throws IOException {
210+
ElementRequestHandler stateHandler = builder
211+
.buildElementRequestHandler();
212+
TestStateNodeProperties testStateNodeProperties = builder
213+
.buildStateNodeProperties();
166214

167215
Element owner = Mockito.mock(Element.class);
168216
StateNode stateNode = Mockito.mock(StateNode.class);
169217
Mockito.when(owner.getNode()).thenReturn(stateNode);
170218

171-
Mockito.when(stateNode.isEnabled()).thenReturn(enabled);
172-
Mockito.when(stateNode.isAttached()).thenReturn(attached);
219+
Mockito.when(stateNode.isEnabled())
220+
.thenReturn(testStateNodeProperties.enabled);
221+
Mockito.when(stateNode.isAttached())
222+
.thenReturn(testStateNodeProperties.attached);
223+
Mockito.when(stateNode.isVisible())
224+
.thenReturn(testStateNodeProperties.visible);
225+
Mockito.when(stateNode.isInert())
226+
.thenReturn(testStateNodeProperties.inert);
173227

174228
StreamResourceRegistry.ElementStreamResource res = new StreamResourceRegistry.ElementStreamResource(
175229
stateHandler, owner);
@@ -251,4 +305,100 @@ private void testStreamResourceStreamResourceWriter(String testString,
251305
Mockito.verify(response).setContentType("application/octet-stream");
252306
}
253307

308+
private static final class TestElementHandlerBuilder {
309+
private final TestElementHandlerProperties elementHandlerProperties;
310+
private final TestStateNodeProperties stateNodeProperties;
311+
312+
public TestElementHandlerBuilder() {
313+
this.elementHandlerProperties = new TestElementHandlerProperties(
314+
DisabledUpdateMode.ONLY_WHEN_ENABLED, false);
315+
this.stateNodeProperties = new TestStateNodeProperties(true, true,
316+
false, true);
317+
}
318+
319+
public TestElementHandlerBuilder withEnalbed(boolean enabled) {
320+
stateNodeProperties.enabled = enabled;
321+
return this;
322+
}
323+
324+
public TestElementHandlerBuilder withAttached(boolean attached) {
325+
stateNodeProperties.attached = attached;
326+
return this;
327+
}
328+
329+
public TestElementHandlerBuilder withInert(boolean inert) {
330+
stateNodeProperties.inert = inert;
331+
return this;
332+
}
333+
334+
public TestElementHandlerBuilder withVisible(boolean visible) {
335+
stateNodeProperties.visible = visible;
336+
return this;
337+
}
338+
339+
public TestElementHandlerBuilder withDisabledUpdateMode(
340+
DisabledUpdateMode disabledUpdateMode) {
341+
elementHandlerProperties.disabledUpdateMode = disabledUpdateMode;
342+
return this;
343+
}
344+
345+
public TestElementHandlerBuilder withAllowInert(boolean allowInert) {
346+
elementHandlerProperties.allowInert = allowInert;
347+
return this;
348+
}
349+
350+
public TestStateNodeProperties buildStateNodeProperties() {
351+
return new TestStateNodeProperties(stateNodeProperties.enabled,
352+
stateNodeProperties.attached, stateNodeProperties.inert,
353+
stateNodeProperties.visible);
354+
}
355+
356+
public ElementRequestHandler buildElementRequestHandler() {
357+
return new ElementRequestHandler() {
358+
@Override
359+
public void handleRequest(VaadinRequest request,
360+
VaadinResponse response, VaadinSession session,
361+
Element owner) {
362+
// Handle the request
363+
}
364+
365+
@Override
366+
public boolean allowInert() {
367+
return elementHandlerProperties.allowInert;
368+
}
369+
370+
@Override
371+
public DisabledUpdateMode getDisabledUpdateMode() {
372+
return elementHandlerProperties.disabledUpdateMode;
373+
}
374+
};
375+
}
376+
}
377+
378+
private static final class TestStateNodeProperties {
379+
private boolean enabled;
380+
private boolean attached;
381+
private boolean inert;
382+
private boolean visible;
383+
384+
private TestStateNodeProperties(boolean enabled, boolean attached,
385+
boolean inert, boolean visible) {
386+
this.enabled = enabled;
387+
this.attached = attached;
388+
this.inert = inert;
389+
this.visible = visible;
390+
}
391+
}
392+
393+
private static final class TestElementHandlerProperties {
394+
private DisabledUpdateMode disabledUpdateMode;
395+
private boolean allowInert;
396+
397+
private TestElementHandlerProperties(
398+
DisabledUpdateMode disabledUpdateMode, boolean allowInert) {
399+
this.disabledUpdateMode = disabledUpdateMode;
400+
this.allowInert = allowInert;
401+
}
402+
}
403+
254404
}

0 commit comments

Comments
 (0)