diff options
author | Olli Tietäväinen <ollit@vaadin.com> | 2021-10-05 09:50:16 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-05 09:50:16 +0300 |
commit | ab775a32112ebfb7ae45f9c1efd6e85d43788f4b (patch) | |
tree | 20fa259f85285d8eed93b5b2c85b54a720bdcb91 /server | |
parent | 2b2028e22fabcf669008db1acfbfa33826809f10 (diff) | |
download | vaadin-framework-ab775a32112ebfb7ae45f9c1efd6e85d43788f4b.tar.gz vaadin-framework-ab775a32112ebfb7ae45f9c1efd6e85d43788f4b.zip |
8.14 cherry-picks (#12418)
* Improve thread safety (#12395)
See: https://vaadin.com/forum/thread/17522264/concurrentmodificationexception-in-vaadin-shared-on-karaf-4-2-x
* Fix incompatible selenium version in test module. (#12397)
* Fixed a dependency version in a karaf test module. (#12399)
* Checkstyle tweaks to DateField widgets. (#12400)
- Added and updated JavaDocs.
- Updated comments.
- Updated to use non-deprecated method calls.
- Removed unnecessary warning suppressions.
- Suppressed warnings for unavoidable deprecation.
* fix: set Vaadin session attribute using lock in reinitializeSession (#12401)
* Cherry picked unit test from Flow
See https://github.com/vaadin/flow/pull/11538
* Fix missing import
* Cherry pick fix from Flow
* deprecate vaadin-snasphots repo (#12405)
* deprecate vaadin-snasphots repo
* Update chrome version to 93
* add more screenshots
* fix: Add MPR UI id request parameter (#12412)
* fix: Add MPR UI id request parameter
Related-to https://github.com/vaadin/multiplatform-runtime/issues/85
* test: Remove redundant non-empty param test
* test: Remove leftovers
* fix: Init window.mprUiId earlier than window.vaadin
* Add missing '='
* Update links shown by license checker (#12402)
vaadin.com/pro does no longer have the info
* fix: Add row limit to DataCommunicator row data requests (#12415)
* Add row limit to DataCommunicator row data requests
* Add missing constant
* Add unit test
* Add test for extending Grid
* Fixed test
Co-authored-by: Tatu Lund <tatu@vaadin.com>
Co-authored-by: Anna Koskinen <Ansku@users.noreply.github.com>
Co-authored-by: Zhe Sun <31067185+ZheSun88@users.noreply.github.com>
Co-authored-by: Mikhail Shabarov <61410877+mshabarov@users.noreply.github.com>
Diffstat (limited to 'server')
6 files changed, 106 insertions, 4 deletions
diff --git a/server/src/main/java/com/vaadin/data/provider/DataCommunicator.java b/server/src/main/java/com/vaadin/data/provider/DataCommunicator.java index 0c1dafe09e..8d974c85d3 100644 --- a/server/src/main/java/com/vaadin/data/provider/DataCommunicator.java +++ b/server/src/main/java/com/vaadin/data/provider/DataCommunicator.java @@ -60,6 +60,7 @@ import elemental.json.JsonObject; public class DataCommunicator<T> extends AbstractExtension { private Registration dataProviderUpdateRegistration; + private static final int MAXIMUM_ALLOWED_ROWS = 500; /** * Simple implementation of collection data provider communication. All data @@ -306,11 +307,25 @@ public class DataCommunicator<T> extends AbstractExtension { */ protected void onRequestRows(int firstRowIndex, int numberOfRows, int firstCachedRowIndex, int cacheSize) { + if (numberOfRows > getMaximumAllowedRows()) { + throw new IllegalStateException( + "Client tried fetch more rows than allowed. This is denied to prevent denial of service."); + } setPushRows(Range.withLength(firstRowIndex, numberOfRows)); markAsDirty(); } /** + * Set the maximum allowed rows to be fetched in one query. + * + * @return Maximum allowed rows for one query. + * @since 8.14.1 + */ + protected int getMaximumAllowedRows() { + return MAXIMUM_ALLOWED_ROWS; + } + + /** * Triggered when rows have been dropped from the client side cache. * * @param keys diff --git a/server/src/main/java/com/vaadin/server/VaadinService.java b/server/src/main/java/com/vaadin/server/VaadinService.java index 888b82a3cb..25354074e1 100644 --- a/server/src/main/java/com/vaadin/server/VaadinService.java +++ b/server/src/main/java/com/vaadin/server/VaadinService.java @@ -1156,8 +1156,13 @@ public abstract class VaadinService implements Serializable { if (value instanceof VaadinSession) { // set flag to avoid cleanup VaadinSession serviceSession = (VaadinSession) value; - serviceSession.setAttribute(PRESERVE_UNBOUND_SESSION_ATTRIBUTE, - Boolean.TRUE); + serviceSession.lock(); + try { + serviceSession.setAttribute( + PRESERVE_UNBOUND_SESSION_ATTRIBUTE, Boolean.TRUE); + } finally { + serviceSession.unlock(); + } } attrs.put(name, value); } @@ -1183,8 +1188,13 @@ public abstract class VaadinService implements Serializable { serviceSession.getLockInstance()); service.storeSession(serviceSession, newSession); - serviceSession.setAttribute(PRESERVE_UNBOUND_SESSION_ATTRIBUTE, - null); + serviceSession.lock(); + try { + serviceSession.setAttribute( + PRESERVE_UNBOUND_SESSION_ATTRIBUTE, null); + } finally { + serviceSession.unlock(); + } } } diff --git a/server/src/main/resources/VAADIN/vaadinBootstrap.js b/server/src/main/resources/VAADIN/vaadinBootstrap.js index a6830f434b..82e7482216 100644 --- a/server/src/main/resources/VAADIN/vaadinBootstrap.js +++ b/server/src/main/resources/VAADIN/vaadinBootstrap.js @@ -365,6 +365,12 @@ params += '&v-wn=' + encodeURIComponent(window.name); } + // This parameter is used in multiplatform-runtime as a key for + // storing the MPR UI content in the session + if (window.mprUiId) { + params += '&v-mui=' + encodeURIComponent(window.mprUiId); + } + // Detect touch device support var supportsTouch = false; try { diff --git a/server/src/test/java/com/vaadin/data/provider/DataCommunicatorTest.java b/server/src/test/java/com/vaadin/data/provider/DataCommunicatorTest.java index c187c91471..ed681f298d 100644 --- a/server/src/test/java/com/vaadin/data/provider/DataCommunicatorTest.java +++ b/server/src/test/java/com/vaadin/data/provider/DataCommunicatorTest.java @@ -314,4 +314,12 @@ public class DataCommunicatorTest { assertTrue("DataCommunicator should be marked as dirty", ui.getConnectorTracker().isDirty(communicator)); } + + + @Test(expected = IllegalStateException.class) + public void requestTooMuchRowsFail() { + TestDataCommunicator communicator = new TestDataCommunicator(); + communicator.onRequestRows(0, communicator.getMaximumAllowedRows() + 10, + 0, 0); + } } diff --git a/server/src/test/java/com/vaadin/server/VaadinServiceTest.java b/server/src/test/java/com/vaadin/server/VaadinServiceTest.java index f10f55db36..f179ad1d58 100644 --- a/server/src/test/java/com/vaadin/server/VaadinServiceTest.java +++ b/server/src/test/java/com/vaadin/server/VaadinServiceTest.java @@ -8,8 +8,11 @@ import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpSessionBindingEvent; +import java.util.Collections; + import org.easymock.EasyMock; import org.junit.Test; +import org.mockito.Mockito; import com.vaadin.shared.Registration; import com.vaadin.util.CurrentInstance; @@ -179,4 +182,45 @@ public class VaadinServiceTest { assertEquals(1, listener.callCount); assertEquals(1, listener2.callCount); } + + @Test + public void reinitializeSession_setVaadinSessionAttriuteWithLock() { + VaadinRequest request = Mockito.mock(VaadinRequest.class); + + VaadinSession vaadinSession = Mockito.mock(VaadinSession.class); + VaadinSession newVaadinSession = Mockito.mock(VaadinSession.class); + + WrappedSession session = mockSession(request, vaadinSession, "foo"); + + Mockito.doAnswer(invocation -> { + mockSession(request, newVaadinSession, "bar"); + return null; + }).when(session).invalidate(); + + VaadinService.reinitializeSession(request); + + Mockito.verify(vaadinSession, Mockito.times(2)).lock(); + Mockito.verify(vaadinSession).setAttribute( + VaadinService.PRESERVE_UNBOUND_SESSION_ATTRIBUTE, Boolean.TRUE); + Mockito.verify(vaadinSession).setAttribute( + VaadinService.PRESERVE_UNBOUND_SESSION_ATTRIBUTE, null); + Mockito.verify(vaadinSession, Mockito.times(2)).unlock(); + } + + private WrappedSession mockSession(VaadinRequest request, + VaadinSession vaadinSession, String attributeName) { + WrappedSession session = Mockito.mock(WrappedSession.class); + Mockito.when(request.getWrappedSession()).thenReturn(session); + + Mockito.when(session.getAttributeNames()) + .thenReturn(Collections.singleton(attributeName)); + + Mockito.when(session.getAttribute(attributeName)) + .thenReturn(vaadinSession); + + VaadinService service = Mockito.mock(VaadinService.class); + + Mockito.when(vaadinSession.getService()).thenReturn(service); + return session; + } } diff --git a/server/src/test/java/com/vaadin/tests/server/component/grid/GridTest.java b/server/src/test/java/com/vaadin/tests/server/component/grid/GridTest.java index 5320959967..f0284b7f28 100644 --- a/server/src/test/java/com/vaadin/tests/server/component/grid/GridTest.java +++ b/server/src/test/java/com/vaadin/tests/server/component/grid/GridTest.java @@ -827,4 +827,23 @@ public class GridTest { column.isSortableByUser()); } + @Test + public void extendGridCustomDataCommunicator() { + Grid<String> grid = new MyGrid<>(); + } + + public class MyDataCommunicator<T> extends DataCommunicator<T> { + @Override + protected int getMaximumAllowedRows() { + return 600; + } + } + + public class MyGrid<T> extends Grid<T> { + + public MyGrid() { + super(new MyDataCommunicator()); + } + + } } |