Skip to content

Commit e427930

Browse files
committed
SEBSP-173, SEBSP-116 minor fixes
1 parent 0f3e5e0 commit e427930

File tree

5 files changed

+135
-24
lines changed

5 files changed

+135
-24
lines changed

src/main/java/ch/ethz/seb/sps/server/datalayer/dao/impl/ClientAccessDAOBatis.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ public Long modelIdToPK(final String modelId) {
7474
if (pk != null) {
7575
return pk;
7676
} else {
77-
return pkByUUID(modelId).getOr(null);
77+
return pkByUUID(modelId)
78+
.getOrThrow();
7879
}
7980
}
8081

src/main/java/ch/ethz/seb/sps/server/datalayer/dao/impl/GroupDAOBatis.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ public Long modelIdToPK(final String modelId) {
9090
if (pk != null) {
9191
return pk;
9292
} else {
93-
return pkByUUID(modelId).getOr(null);
93+
return pkByUUID(modelId)
94+
.getOrThrow();
9495
}
9596
}
9697

src/main/java/ch/ethz/seb/sps/server/weblayer/SEBSessionController.java

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,16 @@
88

99
package ch.ethz.seb.sps.server.weblayer;
1010

11+
import java.util.HashMap;
12+
import java.util.Map;
1113
import java.util.concurrent.CompletableFuture;
1214
import java.util.concurrent.Executor;
1315

16+
import ch.ethz.seb.sps.domain.api.JSONMapper;
17+
import com.fasterxml.jackson.core.JsonProcessingException;
18+
import com.fasterxml.jackson.databind.ObjectMapper;
19+
import com.fasterxml.jackson.databind.type.MapType;
20+
import com.fasterxml.jackson.databind.type.TypeFactory;
1421
import jakarta.servlet.http.HttpServletRequest;
1522
import jakarta.servlet.http.HttpServletResponse;
1623

@@ -285,16 +292,10 @@ public CompletableFuture<Void> postScreenshot(
285292
() -> {
286293
try {
287294

288-
// SEBSP-169 Patch Issue 2.0.2: Prevent error and queue overflow when SEB sends to long metadata
289-
// TODO replace this with attempt to fix metadata instead of complete skip
290-
if (metadata != null && metadata.length() > Constants.MAX_METADATA_SIZE) {
291-
292-
log.warn("Sent metadata to long. Sent by SEB with session: {} metadata: {}", sessionUUID, metadata);
293-
294-
// skip request here
295-
response.setStatus(HttpStatus.OK.value());
296-
return;
297-
}
295+
String trimmedMetadata = Utils.trimJSONMap(
296+
Utils.decodeFormURL_UTF_8(metadata),
297+
Constants.MAX_METADATA_SIZE,
298+
100);
298299

299300
// TODO inject session cache and get session by sessionUUID and check if it is still active (not terminated)
300301
// if inactive throw error for SEB client to notify session closed
@@ -307,7 +308,7 @@ public CompletableFuture<Void> postScreenshot(
307308
sessionUUID,
308309
timestamp,
309310
imageFormat,
310-
Utils.decodeFormURL_UTF_8(metadata),
311+
trimmedMetadata,
311312
request.getInputStream());
312313

313314
response.setStatus(HttpStatus.OK.value());
@@ -323,4 +324,6 @@ public CompletableFuture<Void> postScreenshot(
323324
this.uploadExecutor);
324325
}
325326

327+
328+
326329
}

src/main/java/ch/ethz/seb/sps/utils/Utils.java

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,17 @@
2121
import java.nio.charset.StandardCharsets;
2222
import java.security.MessageDigest;
2323
import java.security.NoSuchAlgorithmException;
24-
import java.util.ArrayList;
25-
import java.util.Arrays;
26-
import java.util.Collection;
27-
import java.util.Collections;
28-
import java.util.HashSet;
29-
import java.util.Iterator;
30-
import java.util.LinkedHashSet;
31-
import java.util.List;
32-
import java.util.Map;
33-
import java.util.Objects;
34-
import java.util.Set;
24+
import java.util.*;
3525
import java.util.function.Predicate;
3626
import java.util.stream.Collector;
3727
import java.util.stream.Collectors;
3828

3929
import ch.ethz.seb.sps.domain.api.API;
30+
import ch.ethz.seb.sps.domain.api.JSONMapper;
4031
import ch.ethz.seb.sps.domain.model.FilterMap;
32+
import com.fasterxml.jackson.databind.JsonNode;
33+
import com.fasterxml.jackson.databind.type.MapType;
34+
import com.fasterxml.jackson.databind.type.TypeFactory;
4135
import org.apache.commons.codec.binary.Hex;
4236
import org.apache.commons.lang3.StringUtils;
4337
import org.apache.commons.text.StringEscapeUtils;
@@ -581,6 +575,7 @@ public static String toAppFormUrlEncodedBody(final MultiValueMap<String, String>
581575
return attributes
582576
.entrySet()
583577
.stream()
578+
584579
.reduce(
585580
new StringBuilder(),
586581
(sb, entry) -> {
@@ -624,6 +619,40 @@ public static String toAppFormUrlEncodedBody(final String name, final Collection
624619
.toString();
625620
}
626621

622+
public static String trimJSONMap(final String jsonData, int max, int step) {
623+
if (jsonData == null || jsonData.length() < max) {
624+
return jsonData;
625+
}
626+
627+
try {
628+
final MapType type = TypeFactory.defaultInstance().constructMapType(
629+
HashMap.class,
630+
String.class,
631+
String.class);
632+
633+
final JSONMapper jsonMapper = new JSONMapper();
634+
int singleTrim = max;
635+
String trimmed = jsonData;
636+
while (trimmed.length() >= max && singleTrim > 0) {
637+
final int trim = singleTrim;
638+
Map<String, String> map = jsonMapper.readValue(trimmed, type);
639+
map.entrySet().forEach(entry -> entry.setValue(Utils.truncateText(entry.getValue(), trim)));
640+
trimmed = jsonMapper.writeValueAsString(map);
641+
singleTrim -= step;
642+
}
643+
644+
if (trimmed.length() > max) {
645+
log.warn("JSON names are more then max allowed size: {} data: {}", max, trimmed);
646+
return null;
647+
}
648+
649+
return trimmed;
650+
} catch (Exception e) {
651+
log.error("Failed to trim json: {}", jsonData, e);
652+
return null;
653+
}
654+
}
655+
627656
public static String truncateText(final String text, final int toChars) {
628657
if (text == null || toChars < 3) {
629658
return text;
@@ -763,4 +792,16 @@ public static boolean hasMetaDataCriteria(final FilterMap filterMap) {
763792
return false;
764793
}
765794

795+
public static String prettyPrintJSON(String input) {
796+
if (input == null) {
797+
return null;
798+
}
799+
800+
JSONMapper jsonMapper = new JSONMapper();
801+
try {
802+
return jsonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonMapper.readTree(input));
803+
} catch (JsonProcessingException e) {
804+
return input;
805+
}
806+
}
766807
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright (c) 2024 ETH Zürich, IT Services
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
7+
*/
8+
9+
package ch.ethz.seb.sps.utils;
10+
11+
import static org.junit.Assert.assertEquals;
12+
13+
import org.junit.Test;
14+
15+
public class UtilsTest {
16+
17+
@Test
18+
public void testTrimJSONMap() {
19+
String value = """
20+
{
21+
"screenProctoringMetadataApplication":"SafeExamBrowser.Client.exe (SafeExamBrowser.Client.exe)",
22+
"screenProctoringMetadataBrowser":"Main Window: SEB Server (https://ralph.ethz.ch/), Additional Window: SEB Screen Proctoring (http://ralph.ethz.ch:3000/recording/04c59492-6221-4ded-917e-6fd8650649df)",
23+
"screenProctoringMetadataURL":"https://ralph.ethz.ch/, http://ralph.ethz.ch:3000/recording/04c59492-6221-4ded-917e-6fd8650649df",
24+
"screenProctoringMetadataUserAction":"Left mouse button has been released at (2087/961).",
25+
"screenProctoringMetadataWindowTitle":"Applikations-Protokoll"
26+
}""";
27+
28+
assertEquals(
29+
"{\r\n" +
30+
" \"screenProctoringMetadataApplication\" : \"SafeExamBrowser.Client.exe (SafeExamBrowser.Client.exe)\",\r\n" +
31+
" \"screenProctoringMetadataBrowser\" : \"Main Window: SEB Server (https://ralph.ethz.ch/), Additional Window: SEB Screen Proctoring (http://ralph.ethz.ch:3000/recording/04c59492-6221-4ded-917e-6fd8650649df)\",\r\n" +
32+
" \"screenProctoringMetadataURL\" : \"https://ralph.ethz.ch/, http://ralph.ethz.ch:3000/recording/04c59492-6221-4ded-917e-6fd8650649df\",\r\n" +
33+
" \"screenProctoringMetadataUserAction\" : \"Left mouse button has been released at (2087/961).\",\r\n" +
34+
" \"screenProctoringMetadataWindowTitle\" : \"Applikations-Protokoll\"\r\n" +
35+
"}",
36+
Utils.prettyPrintJSON(Utils.trimJSONMap(value, 1000, 10)));
37+
38+
assertEquals(
39+
"{\r\n" +
40+
" \"screenProctoringMetadataApplication\" : \"SafeExamBrowser.Client.exe (SafeExamBrowser.Client.exe)\",\r\n" +
41+
" \"screenProctoringMetadataUserAction\" : \"Left mouse button has been released at (2087/961).\",\r\n" +
42+
" \"screenProctoringMetadataBrowser\" : \"Main Window: SEB Server (https://ralph.ethz.ch/), Additional Window: SEB Scre...\",\r\n" +
43+
" \"screenProctoringMetadataURL\" : \"https://ralph.ethz.ch/, http://ralph.ethz.ch:3000/recording/04c59492-6221-4de...\",\r\n" +
44+
" \"screenProctoringMetadataWindowTitle\" : \"Applikations-Protokoll\"\r\n" +
45+
"}",
46+
Utils.prettyPrintJSON(Utils.trimJSONMap(value, 500, 10)));
47+
48+
assertEquals(
49+
"{\r\n" +
50+
" \"screenProctoringMetadataApplication\" : \"SafeExamBrowser.C...\",\r\n" +
51+
" \"screenProctoringMetadataUserAction\" : \"Left mouse button...\",\r\n" +
52+
" \"screenProctoringMetadataBrowser\" : \"Main Window: SEB ...\",\r\n" +
53+
" \"screenProctoringMetadataURL\" : \"https://ralph.eth...\",\r\n" +
54+
" \"screenProctoringMetadataWindowTitle\" : \"Applikations-Prot...\"\r\n" +
55+
"}",
56+
Utils.prettyPrintJSON(Utils.trimJSONMap(value, 300, 10)));
57+
58+
// Note if the max value is too small to fit all json attribute names, the utility returns null.
59+
assertEquals(
60+
null,
61+
Utils.prettyPrintJSON(Utils.trimJSONMap(value, 200, 10)));
62+
}
63+
64+
65+
}

0 commit comments

Comments
 (0)