From 7fae3f4baf802186f55ea6bb3bcee4075682cd63 Mon Sep 17 00:00:00 2001 From: anhefti Date: Thu, 8 Apr 2021 10:36:32 +0200 Subject: [PATCH] SEBSERV-148 testing fixing --- .../ch/ethz/seb/sebserver/gbl/Constants.java | 3 + .../proctoring/JitsiWindowScriptResolver.java | 87 ++++----- .../ProctoringWindowScriptResolver.java | 14 ++ .../proctoring/ZoomWindowScriptResolver.java | 152 ++++----------- .../session/proctoring/jitsiWindow.html | 47 +++++ .../session/proctoring/zoomWindow.html | 102 +++++++++++ .../proctoring/ZoomRoomRequestResponse.java | 2 +- src/main/resources/messages.properties | 2 +- .../JitsiWindowScriptResolverTest.java | 118 ++++++++++++ .../ZoomWindowScriptResolverTest.java | 173 ++++++++++++++++++ 10 files changed, 530 insertions(+), 170 deletions(-) create mode 100644 src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/jitsiWindow.html create mode 100644 src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/zoomWindow.html create mode 100644 src/test/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/JitsiWindowScriptResolverTest.java create mode 100644 src/test/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/ZoomWindowScriptResolverTest.java diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/Constants.java b/src/main/java/ch/ethz/seb/sebserver/gbl/Constants.java index b1855220..0af7d6fc 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/Constants.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/Constants.java @@ -74,6 +74,9 @@ public final class Constants { public static final String URL_ADDRESS_SEPARATOR = COLON.toString() + SLASH.toString() + SLASH.toString(); public static final String URL_PATH_SEPARATOR = SLASH.toString(); + public static final String DYN_HTML_ATTR_OPEN = "%%_"; + public static final String DYN_HTML_ATTR_CLOSE = "_%%"; + public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; public static final String TIME_ZONE_OFFSET_TAIL_FORMAT = "|ZZ"; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/JitsiWindowScriptResolver.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/JitsiWindowScriptResolver.java index a1baea70..fa1299e3 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/JitsiWindowScriptResolver.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/JitsiWindowScriptResolver.java @@ -11,12 +11,16 @@ package ch.ethz.seb.sebserver.gui.service.session.proctoring; import java.util.HashMap; import java.util.Map; +import org.apache.commons.io.IOUtils; import org.apache.commons.text.StringSubstitutor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; +import org.springframework.core.io.Resource; import org.springframework.stereotype.Service; +import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gui.service.session.proctoring.ProctoringGUIService.ProctoringWindowData; @@ -28,58 +32,21 @@ public class JitsiWindowScriptResolver implements ProctoringWindowScriptResolver private static final Logger log = LoggerFactory.getLogger(JitsiWindowScriptResolver.class); - private static final String ATTR_SUBJECT = "_subject_"; - private static final String ATTR_ACCESS_TOKEN = "_accessToken_"; - private static final String ATTR_ROOM_NAME = "_roomName_"; - private static final String ATTR_HOST = "_host_"; + static final String RES_PATH = + "classpath:ch/ethz/seb/sebserver/gui/service/session/proctoring/jitsiWindow.html"; - // @formatter:off - private static final String JITSI_WINDOW_HTML = - "" + - "" + - "" + - " " + - " " + - "" + - "" + - "" + - "
" + - "" + - "" + - ""; - // @formatter:on + private static final String ATTR_SUBJECT = "ATTR_SUBJECT"; + private static final String ATTR_ACCESS_TOKEN = "ATTR_ACCESS_TOKEN"; + private static final String ATTR_ROOM_NAME = "ATTR_ROOM_NAME"; + private static final String ATTR_HOST = "ATTR_HOST"; + + private final Resource resourceFile; + + public JitsiWindowScriptResolver( + @Value(RES_PATH) final Resource resourceFile) { + + this.resourceFile = resourceFile; + } @Override public boolean applies(final ProctoringWindowData data) { @@ -93,14 +60,28 @@ public class JitsiWindowScriptResolver implements ProctoringWindowScriptResolver @Override public String getProctoringWindowScript(final ProctoringWindowData data) { + final Map args = new HashMap<>(); args.put(ATTR_HOST, data.connectionData.serverHost); args.put(ATTR_ROOM_NAME, data.connectionData.roomName); args.put(ATTR_ACCESS_TOKEN, String.valueOf(data.connectionData.accessToken)); args.put(ATTR_SUBJECT, data.connectionData.subject); - return new StringSubstitutor(args, "%%_", "_%%") - .replace(JITSI_WINDOW_HTML); + return new StringSubstitutor( + args, + Constants.DYN_HTML_ATTR_OPEN, + Constants.DYN_HTML_ATTR_CLOSE) + .replace(getHTMLWindow()); + + } + + private String getHTMLWindow() { + try { + return IOUtils.toString(this.resourceFile.getInputStream()); + } catch (final Exception e) { + log.error("Failed to load Jitsi Meet window resources", e); + return "ERROR: " + e.getLocalizedMessage(); + } } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/ProctoringWindowScriptResolver.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/ProctoringWindowScriptResolver.java index 84332244..259aad0c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/ProctoringWindowScriptResolver.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/ProctoringWindowScriptResolver.java @@ -10,10 +10,24 @@ package ch.ethz.seb.sebserver.gui.service.session.proctoring; import ch.ethz.seb.sebserver.gui.service.session.proctoring.ProctoringGUIService.ProctoringWindowData; +/** Defines a proctoring window script resolver that generates the + * proctoring window html and script code for a particular + * proctoring service. */ public interface ProctoringWindowScriptResolver { + /** Indicates if the concrete implementation applies to given proctoring data. + * Usually this looks after the proctoring service type within the given data + * and returns true if the implementation is compatible with the given proctoring + * service type. + * + * @param data ProctoringWindowData instance containing actual proctoring data + * @return true if a concrete implementation applies to the given data */ boolean applies(ProctoringWindowData data); + /** Produces the html and java script page to open in a proctoring window pop-up. + * + * @param data ProctoringWindowData instance containing actual proctoring data + * @return the html and java script page to open in a proctoring window pop-up */ String getProctoringWindowScript(ProctoringWindowData data); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/ZoomWindowScriptResolver.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/ZoomWindowScriptResolver.java index 61d88db1..e3da08ad 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/ZoomWindowScriptResolver.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/ZoomWindowScriptResolver.java @@ -11,13 +11,17 @@ package ch.ethz.seb.sebserver.gui.service.session.proctoring; import java.util.HashMap; import java.util.Map; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.text.StringSubstitutor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; +import org.springframework.core.io.Resource; import org.springframework.stereotype.Service; +import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gui.service.session.proctoring.ProctoringGUIService.ProctoringWindowData; @@ -29,120 +33,24 @@ public class ZoomWindowScriptResolver implements ProctoringWindowScriptResolver private static final Logger log = LoggerFactory.getLogger(ZoomWindowScriptResolver.class); - private static final String ATTR_SUBJECT = "_subject_"; - private static final String ATTR_API_KEY = "_apiKey_"; - private static final String ATTR_ACCESS_TOKEN = "_accessToken_"; - private static final String ATTR_ROOM_KEY = "_roomKey_"; - private static final String ATTR_ROOM_NAME = "_roomName_"; - private static final String ATTR_HOST = "_host_"; - private static final String ATTR_USER_NAME = "_username_"; + static final String RES_PATH = + "classpath:ch/ethz/seb/sebserver/gui/service/session/proctoring/zoomWindow.html"; - // @formatter:off - private static final String ZOOM_WINDOW_HTML = - "\n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + ""; - // @formatter:on + private static final String ATTR_SUBJECT = "ATTR_SUBJECT"; + private static final String ATTR_API_KEY = "ATTR_API_KEY"; + private static final String ATTR_ACCESS_TOKEN = "ATTR_ACCESS_TOKEN"; + private static final String ATTR_ROOM_KEY = "ATTR_ROOM_KEY"; + private static final String ATTR_ROOM_NAME = "ATTR_ROOM_NAME"; + private static final String ATTR_HOST = "ATTR_HOST"; + private static final String ATTR_USER_NAME = "ATTR_USER_NAME"; + + private final Resource resourceFile; + + public ZoomWindowScriptResolver( + @Value(RES_PATH) final Resource resourceFile) { + + this.resourceFile = resourceFile; + } @Override public boolean applies(final ProctoringWindowData data) { @@ -169,8 +77,22 @@ public class ZoomWindowScriptResolver implements ProctoringWindowScriptResolver args.put(ATTR_SUBJECT, data.connectionData.subject); args.put(ATTR_USER_NAME, data.connectionData.userName); - return new StringSubstitutor(args, "%%_", "_%%") - .replace(ZOOM_WINDOW_HTML); + final String htmlWindow = getHTMLWindow(); + final String replace = new StringSubstitutor( + args, + Constants.DYN_HTML_ATTR_OPEN, + Constants.DYN_HTML_ATTR_CLOSE) + .replace(htmlWindow); + return replace; + } + + private String getHTMLWindow() { + try { + return IOUtils.toString(this.resourceFile.getInputStream()); + } catch (final Exception e) { + log.error("Failed to load Jitsi Meet window resources", e); + return "ERROR: " + e.getLocalizedMessage(); + } } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/jitsiWindow.html b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/jitsiWindow.html new file mode 100644 index 00000000..66f94bb1 --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/jitsiWindow.html @@ -0,0 +1,47 @@ + + + + + + + +
+ + + \ No newline at end of file diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/zoomWindow.html b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/zoomWindow.html new file mode 100644 index 00000000..f5130ed3 --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/zoomWindow.html @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ZoomRoomRequestResponse.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ZoomRoomRequestResponse.java index 99daff85..d3cbd284 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ZoomRoomRequestResponse.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ZoomRoomRequestResponse.java @@ -131,7 +131,7 @@ public interface ZoomRoomRequestResponse { @JsonIgnoreProperties(ignoreUnknown = true) static class Settings { - @JsonProperty final boolean host_video = false; + @JsonProperty final boolean host_video = true; @JsonProperty final boolean participant_video = true; @JsonProperty final boolean join_before_host = true; @JsonProperty final int jbh_time = 0; diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index b5afb240..a6c46b4a 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -1403,7 +1403,7 @@ sebserver.examconfig.props.label.zoomFeatureFlagChat=Enable Chat sebserver.examconfig.props.label.zoomFeatureFlagChat.tooltip= sebserver.examconfig.props.label.zoomFeatureFlagCloseCaptions=Enable Close Captions sebserver.examconfig.props.label.zoomFeatureFlagCloseCaptions.tooltip= -sebserver.examconfig.props.label.zoomFeatureFlagDisplayingName=Display Meeting Name +sebserver.examconfig.props.label.zoomFeatureFlagDisplayingMeetingName=Display Meeting Name sebserver.examconfig.props.label.zoomFeatureFlagDisplayMeetingName.tooltip sebserver.examconfig.props.label.zoomFeatureFlagRaiseHand=Enable Raise Hand sebserver.examconfig.props.label.zoomFeatureFlagRaiseHand.tooltip= diff --git a/src/test/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/JitsiWindowScriptResolverTest.java b/src/test/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/JitsiWindowScriptResolverTest.java new file mode 100644 index 00000000..14bec9eb --- /dev/null +++ b/src/test/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/JitsiWindowScriptResolverTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2021 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver.gui.service.session.proctoring; + +import static org.junit.Assert.*; + +import org.junit.Test; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; + +import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringRoomConnection; +import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType; +import ch.ethz.seb.sebserver.gui.service.session.proctoring.ProctoringGUIService.ProctoringWindowData; + +public class JitsiWindowScriptResolverTest { + + @Test + public void testJitsiWindowScriptResolver() { + final DefaultResourceLoader defaultResourceLoader = new DefaultResourceLoader(); + final Resource resource = defaultResourceLoader.getResource(JitsiWindowScriptResolver.RES_PATH); + final JitsiWindowScriptResolver jitsiWindowScriptResolver = new JitsiWindowScriptResolver(resource); + + final ProctoringWindowData proctoringWindowData = new ProctoringWindowData( + "0", + "Test_Window", + new ProctoringRoomConnection( + ProctoringServerType.JITSI_MEET, + "CONNECTION_TOKEN", + "HOST", + "URL", + "ROOM", + "SUBJECT", + "ACCESS_TOKEN", + "API_KEY", + "ROOM_KEY", + "MEETING_ID", + "USER_NAME")); + + final ProctoringWindowData proctoringWindowDataOther = new ProctoringWindowData( + "0", + "Test_Window", + new ProctoringRoomConnection( + ProctoringServerType.ZOOM, + "CONNECTION_TOKEN", + "HOST", + "URL", + "ROOM", + "SUBJECT", + "ACCESS_TOKEN", + "API_KEY", + "ROOM_KEY", + "MEETING_ID", + "USER_NAME")); + + assertFalse(jitsiWindowScriptResolver.applies(proctoringWindowDataOther)); + assertTrue(jitsiWindowScriptResolver.applies(proctoringWindowData)); + + final String proctoringWindowScript = jitsiWindowScriptResolver + .getProctoringWindowScript(proctoringWindowData); + + assertEquals( + "\r\n" + + "\r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + "\r\n" + + "\r\n" + + "
\r\n" + + "\r\n" + + "\r\n" + + "", + proctoringWindowScript); + } + +} diff --git a/src/test/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/ZoomWindowScriptResolverTest.java b/src/test/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/ZoomWindowScriptResolverTest.java new file mode 100644 index 00000000..0bbd3517 --- /dev/null +++ b/src/test/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/ZoomWindowScriptResolverTest.java @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2021 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver.gui.service.session.proctoring; + +import static org.junit.Assert.*; + +import org.junit.Test; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; + +import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringRoomConnection; +import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType; +import ch.ethz.seb.sebserver.gui.service.session.proctoring.ProctoringGUIService.ProctoringWindowData; + +public class ZoomWindowScriptResolverTest { + + @Test + public void testJitsiWindowScriptResolver() { + final DefaultResourceLoader defaultResourceLoader = new DefaultResourceLoader(); + final Resource resource = defaultResourceLoader.getResource(ZoomWindowScriptResolver.RES_PATH); + final ZoomWindowScriptResolver zoomWindowScriptResolver = new ZoomWindowScriptResolver(resource); + + final ProctoringWindowData proctoringWindowDataZoom = new ProctoringWindowData( + "0", + "Test_Window", + new ProctoringRoomConnection( + ProctoringServerType.ZOOM, + "CONNECTION_TOKEN", + "HOST", + "URL", + "ROOM", + "SUBJECT", + "ACCESS_TOKEN", + "API_KEY", + "ROOM_KEY", + "MEETING_ID", + "USER_NAME")); + + final ProctoringWindowData proctoringWindowDataOther = new ProctoringWindowData( + "0", + "Test_Window", + new ProctoringRoomConnection( + ProctoringServerType.JITSI_MEET, + "CONNECTION_TOKEN", + "HOST", + "URL", + "ROOM", + "SUBJECT", + "ACCESS_TOKEN", + "API_KEY", + "ROOM_KEY", + "MEETING_ID", + "USER_NAME")); + + assertFalse(zoomWindowScriptResolver.applies(proctoringWindowDataOther)); + assertTrue(zoomWindowScriptResolver.applies(proctoringWindowDataZoom)); + + final String proctoringWindowScript = zoomWindowScriptResolver + .getProctoringWindowScript(proctoringWindowDataZoom); + + assertEquals( + "\r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + "", + proctoringWindowScript); + } + +}