Skip to content

Commit 52c3794

Browse files
authored
fix: block new users immediately when enforcement=ON (#19816)
* fix: block new users immediately when enforcement=ON * fix formatting * add tests
1 parent 7ee907e commit 52c3794

File tree

4 files changed

+85
-13
lines changed

4 files changed

+85
-13
lines changed

flow-server/src/main/java/com/vaadin/flow/server/dau/DAUUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public static Optional<Cookie> getTrackingCookie(VaadinRequest request) {
110110
* contains invalid data.
111111
* @see FlowDauIntegration#generateNewCookie(VaadinRequest)
112112
*/
113-
static Optional<DauCookie> parserCookie(Cookie cookie) {
113+
static Optional<DauCookie> parseCookie(Cookie cookie) {
114114
String cookieValue = cookie.getValue();
115115
String[] tokens = cookieValue.split("\\$");
116116
if (tokens.length != 2) {

flow-server/src/main/java/com/vaadin/flow/server/dau/DAUVaadinRequestInterceptor.java

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,30 +45,38 @@ public void requestStart(VaadinRequest request, VaadinResponse response) {
4545

4646
// user is counted even if request handling throws an exception
4747
Optional<DAUUtils.DauCookie> maybePresentCookie = DAUUtils
48-
.getTrackingCookie(request).flatMap(DAUUtils::parserCookie);
48+
.getTrackingCookie(request).flatMap(DAUUtils::parseCookie);
4949
if (maybePresentCookie.isPresent()) {
5050
DAUUtils.DauCookie dauCookie = maybePresentCookie.get();
51-
if (dauCookie.isActive()) {
52-
53-
VaadinSession vaadinSession = VaadinSession.getCurrent();
54-
String userIdentity = Optional.ofNullable(userIdentitySupplier)
55-
.flatMap(supplier -> supplier
56-
.apply(new UserIdentityContext(request,
57-
vaadinSession)))
58-
.orElse(null);
59-
FlowDauIntegration.trackUser(request, dauCookie.trackingHash(),
60-
userIdentity);
51+
// ignore user's activity threshold if enforcement
52+
if (dauCookie.isActive() || FlowDauIntegration.shouldEnforce()) {
53+
trackUser(request, dauCookie.trackingHash());
6154
}
62-
6355
} else if (response != null) {
6456
// response can be null, for example for PUSH websocket requests
6557

6658
// DAU cookie is created if not present and re-created if invalid
6759
Cookie cookie = FlowDauIntegration.generateNewCookie(request);
6860
response.addCookie(cookie);
61+
62+
// Enforce new users immediately, even if they are not yet active
63+
// and tracked
64+
if (FlowDauIntegration.shouldEnforce()) {
65+
trackUser(request, DAUUtils.parseCookie(cookie).orElseThrow()
66+
.trackingHash());
67+
}
6968
}
7069
}
7170

71+
private void trackUser(VaadinRequest request, String trackingHash) {
72+
VaadinSession vaadinSession = VaadinSession.getCurrent();
73+
String userIdentity = Optional.ofNullable(userIdentitySupplier)
74+
.flatMap(supplier -> supplier
75+
.apply(new UserIdentityContext(request, vaadinSession)))
76+
.orElse(null);
77+
FlowDauIntegration.trackUser(request, trackingHash, userIdentity);
78+
}
79+
7280
@Override
7381
public void handleException(VaadinRequest request, VaadinResponse response,
7482
VaadinSession vaadinSession, Exception t) {

flow-server/src/main/java/com/vaadin/flow/server/dau/FlowDauIntegration.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,17 @@ static void trackUser(VaadinRequest request, String trackingHash,
9696
}
9797
}
9898

99+
/**
100+
* Tells whether new user, i.e. who just opens the browser, not yet tracked,
101+
* not yet counted, should be blocked immediately.
102+
*
103+
* @return {@literal true} if the current request/user should be blocked,
104+
* {@literal false} otherwise.
105+
*/
106+
static boolean shouldEnforce() {
107+
return DauIntegration.shouldEnforce();
108+
}
109+
99110
/**
100111
* Potentially applies enforcement to the current request if DAU limit is
101112
* exceeded.

flow-server/src/test/java/com/vaadin/flow/server/dau/DAUVaadinRequestInterceptorTest.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,59 @@ public void requestStart_invalidCookie_doNotTrack() {
362362
}
363363
}
364364

365+
@Test
366+
public void requestStart_dauCookiePresent_notActiveUser_enforcement_tracksUser() {
367+
VaadinRequest request = Mockito.mock(VaadinRequest.class);
368+
VaadinResponse response = Mockito.mock(VaadinResponse.class);
369+
Mockito.when(request
370+
.getParameter(ApplicationConstants.REQUEST_TYPE_PARAMETER))
371+
.thenReturn(HandlerHelper.RequestType.INIT.getIdentifier());
372+
373+
String trackingHash = "trackingHash";
374+
Instant creationTime = Instant.now()
375+
.minusSeconds(DAU_MIN_ACTIVITY_IN_SECONDS / 2);
376+
Cookie cookie = new Cookie(DAUUtils.DAU_COOKIE_NAME,
377+
trackingHash + "$" + creationTime.toEpochMilli());
378+
379+
Mockito.when(request.getCookies()).thenReturn(new Cookie[] { cookie });
380+
381+
VaadinSession.setCurrent(new MockVaadinSession(vaadinService));
382+
383+
try (MockedStatic<DauIntegration> dauIntegration = Mockito
384+
.mockStatic(DauIntegration.class)) {
385+
dauIntegration.when(DauIntegration::shouldEnforce).thenReturn(true);
386+
interceptor.requestStart(request, response);
387+
dauIntegration
388+
.verify(() -> DauIntegration.trackUser(trackingHash, null));
389+
} finally {
390+
VaadinSession.setCurrent(null);
391+
}
392+
}
393+
394+
@Test
395+
public void requestStart_noDauCookie_notActiveUser_enforcement_tracksUser() {
396+
VaadinRequest request = Mockito.mock(VaadinRequest.class);
397+
VaadinResponse response = Mockito.mock(VaadinResponse.class);
398+
Mockito.when(request
399+
.getParameter(ApplicationConstants.REQUEST_TYPE_PARAMETER))
400+
.thenReturn(HandlerHelper.RequestType.INIT.getIdentifier());
401+
402+
String trackingHash = "trackingHash";
403+
VaadinSession.setCurrent(new MockVaadinSession(vaadinService));
404+
405+
try (MockedStatic<DauIntegration> dauIntegration = Mockito
406+
.mockStatic(DauIntegration.class)) {
407+
dauIntegration.when(DauIntegration::shouldEnforce).thenReturn(true);
408+
dauIntegration.when(DauIntegration::newTrackingHash)
409+
.thenReturn(trackingHash);
410+
interceptor.requestStart(request, response);
411+
dauIntegration
412+
.verify(() -> DauIntegration.trackUser(trackingHash, null));
413+
} finally {
414+
VaadinSession.setCurrent(null);
415+
}
416+
}
417+
365418
private static Cookie createCookie(String trackingHash, boolean active) {
366419
Instant creationTime = Instant.now();
367420
if (active) {

0 commit comments

Comments
 (0)