fixed proctor room action update
This commit is contained in:
		
							parent
							
								
									5b9b336886
								
							
						
					
					
						commit
						55cfc07a9d
					
				
					 4 changed files with 140 additions and 154 deletions
				
			
		| 
						 | 
				
			
			@ -77,7 +77,7 @@ public class MonitoringClientConnection implements TemplateComposer {
 | 
			
		|||
 | 
			
		||||
    // @formatter:off
 | 
			
		||||
    private static final String OPEN_SINGEL_ROOM_SCRIPT =
 | 
			
		||||
            "var existingWin = window.open('', '%s', 'height=420,width=620,location=no,scrollbars=yes,status=no,menubar=yes,toolbar=yes,titlebar=yes,dialog=yes');\n" +
 | 
			
		||||
            "var existingWin = window.open('', '%s', 'height=420,width=640,location=no,scrollbars=yes,status=no,menubar=yes,toolbar=yes,titlebar=yes,dialog=yes');\n" +
 | 
			
		||||
            "if(existingWin.location.href === 'about:blank'){\n" +
 | 
			
		||||
            "    existingWin.location.href = '%s%s';\n" +
 | 
			
		||||
            "    existingWin.focus();\n" +
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,6 +49,7 @@ import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
 | 
			
		|||
import ch.ethz.seb.sebserver.gbl.model.session.RemoteProctoringRoom;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.util.Pair;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
 | 
			
		||||
import ch.ethz.seb.sebserver.gui.GuiServiceInfo;
 | 
			
		||||
| 
						 | 
				
			
			@ -114,6 +115,7 @@ public class MonitoringRunningExam implements TemplateComposer {
 | 
			
		|||
    private final InstructionProcessor instructionProcessor;
 | 
			
		||||
    private final GuiServiceInfo guiServiceInfo;
 | 
			
		||||
    private final long pollInterval;
 | 
			
		||||
    private final long proctoringRoomUpdateInterval;
 | 
			
		||||
    private final String remoteProctoringEndpoint;
 | 
			
		||||
    private final ProctorRoomConnectionsPopup proctorRoomConnectionsPopup;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -124,7 +126,8 @@ public class MonitoringRunningExam implements TemplateComposer {
 | 
			
		|||
            final GuiServiceInfo guiServiceInfo,
 | 
			
		||||
            final ProctorRoomConnectionsPopup proctorRoomConnectionsPopup,
 | 
			
		||||
            @Value("${sebserver.gui.webservice.poll-interval:1000}") final long pollInterval,
 | 
			
		||||
            @Value("${sebserver.gui.remote.proctoring.entrypoint:/remote-proctoring}") final String remoteProctoringEndpoint) {
 | 
			
		||||
            @Value("${sebserver.gui.remote.proctoring.entrypoint:/remote-proctoring}") final String remoteProctoringEndpoint,
 | 
			
		||||
            @Value("${sebserver.gui.remote.proctoring.rooms.update.poll-interval:5000}") final long proctoringRoomUpdateInterval) {
 | 
			
		||||
 | 
			
		||||
        this.serverPushService = serverPushService;
 | 
			
		||||
        this.pageService = pageService;
 | 
			
		||||
| 
						 | 
				
			
			@ -134,6 +137,7 @@ public class MonitoringRunningExam implements TemplateComposer {
 | 
			
		|||
        this.pollInterval = pollInterval;
 | 
			
		||||
        this.remoteProctoringEndpoint = remoteProctoringEndpoint;
 | 
			
		||||
        this.proctorRoomConnectionsPopup = proctorRoomConnectionsPopup;
 | 
			
		||||
        this.proctoringRoomUpdateInterval = proctoringRoomUpdateInterval;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
| 
						 | 
				
			
			@ -325,7 +329,7 @@ public class MonitoringRunningExam implements TemplateComposer {
 | 
			
		|||
                .getOr(null);
 | 
			
		||||
 | 
			
		||||
        if (proctoringSettings != null && proctoringSettings.enableProctoring) {
 | 
			
		||||
            final Map<RemoteProctoringRoom, TreeItem> availableRooms = new HashMap<>();
 | 
			
		||||
            final Map<String, Pair<RemoteProctoringRoom, TreeItem>> availableRooms = new HashMap<>();
 | 
			
		||||
            updateRoomActions(
 | 
			
		||||
                    entityKey,
 | 
			
		||||
                    pageContext,
 | 
			
		||||
| 
						 | 
				
			
			@ -334,7 +338,7 @@ public class MonitoringRunningExam implements TemplateComposer {
 | 
			
		|||
                    proctoringSettings);
 | 
			
		||||
            this.serverPushService.runServerPush(
 | 
			
		||||
                    new ServerPushContext(content, Utils.truePredicate()),
 | 
			
		||||
                    5000,
 | 
			
		||||
                    this.proctoringRoomUpdateInterval,
 | 
			
		||||
                    context -> updateRoomActions(
 | 
			
		||||
                            entityKey,
 | 
			
		||||
                            pageContext,
 | 
			
		||||
| 
						 | 
				
			
			@ -347,7 +351,7 @@ public class MonitoringRunningExam implements TemplateComposer {
 | 
			
		|||
    private void updateRoomActions(
 | 
			
		||||
            final EntityKey entityKey,
 | 
			
		||||
            final PageContext pageContext,
 | 
			
		||||
            final Map<RemoteProctoringRoom, TreeItem> rooms,
 | 
			
		||||
            final Map<String, Pair<RemoteProctoringRoom, TreeItem>> rooms,
 | 
			
		||||
            final PageActionBuilder actionBuilder,
 | 
			
		||||
            final ProctoringSettings proctoringSettings) {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -358,9 +362,10 @@ public class MonitoringRunningExam implements TemplateComposer {
 | 
			
		|||
                .getOrThrow()
 | 
			
		||||
                .stream()
 | 
			
		||||
                .forEach(room -> {
 | 
			
		||||
                    if (rooms.containsKey(room)) {
 | 
			
		||||
                    if (rooms.containsKey(room.name)) {
 | 
			
		||||
                        // update action
 | 
			
		||||
                        final TreeItem treeItem = rooms.get(room);
 | 
			
		||||
                        final TreeItem treeItem = rooms.get(room.name).b;
 | 
			
		||||
                        rooms.put(room.name, new Pair<>(room, treeItem));
 | 
			
		||||
                        treeItem.setText(i18nSupport.getText(new LocTextKey(
 | 
			
		||||
                                ActionDefinition.MONITOR_EXAM_VIEW_PROCTOR_ROOM.title.name,
 | 
			
		||||
                                room.subject,
 | 
			
		||||
| 
						 | 
				
			
			@ -372,7 +377,13 @@ public class MonitoringRunningExam implements TemplateComposer {
 | 
			
		|||
                        final PageAction action =
 | 
			
		||||
                                actionBuilder.newAction(ActionDefinition.MONITOR_EXAM_VIEW_PROCTOR_ROOM)
 | 
			
		||||
                                        .withEntityKey(entityKey)
 | 
			
		||||
                                        .withExec(a -> showExamProctoringRoom(proctoringSettings, room, rooms, a))
 | 
			
		||||
                                        .withExec(_action -> {
 | 
			
		||||
                                            final int actualRoomSize = getActualRoomSize(room, rooms);
 | 
			
		||||
                                            if (actualRoomSize <= 0) {
 | 
			
		||||
                                                return _action;
 | 
			
		||||
                                            }
 | 
			
		||||
                                            return showExamProctoringRoom(proctoringSettings, room, _action);
 | 
			
		||||
                                        })
 | 
			
		||||
                                        .withNameAttributes(
 | 
			
		||||
                                                room.subject,
 | 
			
		||||
                                                room.roomSize,
 | 
			
		||||
| 
						 | 
				
			
			@ -380,15 +391,11 @@ public class MonitoringRunningExam implements TemplateComposer {
 | 
			
		|||
                                        .noEventPropagation()
 | 
			
		||||
                                        .create();
 | 
			
		||||
 | 
			
		||||
                        this.pageService.publishAction(action, treeItem -> rooms.put(room, treeItem));
 | 
			
		||||
                        this.pageService.publishAction(
 | 
			
		||||
                                action,
 | 
			
		||||
                                _treeItem -> rooms.put(room.name, new Pair<>(room, _treeItem)));
 | 
			
		||||
                        addRoomConnectionsPopupListener(entityKey, pageContext, rooms);
 | 
			
		||||
                        rooms.entrySet().stream()
 | 
			
		||||
                                .filter(entry -> entry.getKey().equals(room))
 | 
			
		||||
                                .findFirst()
 | 
			
		||||
                                .ifPresent(entry -> processProctorRoomActionActivation(
 | 
			
		||||
                                        entry.getValue(),
 | 
			
		||||
                                        room,
 | 
			
		||||
                                        pageContext));
 | 
			
		||||
                        processProctorRoomActionActivation(rooms.get(room.name).b, room, pageContext);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -414,10 +421,10 @@ public class MonitoringRunningExam implements TemplateComposer {
 | 
			
		|||
    private void addRoomConnectionsPopupListener(
 | 
			
		||||
            final EntityKey entityKey,
 | 
			
		||||
            final PageContext pageContext,
 | 
			
		||||
            final Map<RemoteProctoringRoom, TreeItem> rooms) {
 | 
			
		||||
            final Map<String, Pair<RemoteProctoringRoom, TreeItem>> rooms) {
 | 
			
		||||
 | 
			
		||||
        if (!rooms.isEmpty()) {
 | 
			
		||||
            final TreeItem treeItem = rooms.values().iterator().next();
 | 
			
		||||
            final TreeItem treeItem = rooms.values().iterator().next().b;
 | 
			
		||||
            final Tree tree = treeItem.getParent();
 | 
			
		||||
            if (tree.getData(SHOW_CONNECTION_ACTION_APPLIED) == null) {
 | 
			
		||||
                tree.addListener(SWT.Selection, event -> {
 | 
			
		||||
| 
						 | 
				
			
			@ -426,16 +433,17 @@ public class MonitoringRunningExam implements TemplateComposer {
 | 
			
		|||
                    if (event.button == 3) {
 | 
			
		||||
                        rooms.entrySet()
 | 
			
		||||
                                .stream()
 | 
			
		||||
                                .filter(e -> e.getValue().equals(item))
 | 
			
		||||
                                .filter(e -> e.getValue().b.equals(item))
 | 
			
		||||
                                .findFirst()
 | 
			
		||||
                                .ifPresent(e -> {
 | 
			
		||||
                                    if (e.getKey().roomSize > 0) {
 | 
			
		||||
                                    final RemoteProctoringRoom room = e.getValue().a;
 | 
			
		||||
                                    if (room.roomSize > 0) {
 | 
			
		||||
                                        final PageContext pc = pageContext.copy()
 | 
			
		||||
                                                .clearAttributes()
 | 
			
		||||
                                                .withEntityKey(new EntityKey(e.getKey().getName(),
 | 
			
		||||
                                                .withEntityKey(new EntityKey(room.name,
 | 
			
		||||
                                                        EntityType.REMOTE_PROCTORING_ROOM))
 | 
			
		||||
                                                .withParentEntityKey(entityKey);
 | 
			
		||||
                                        this.proctorRoomConnectionsPopup.show(pc, e.getKey().getSubject());
 | 
			
		||||
                                        this.proctorRoomConnectionsPopup.show(pc, room.subject);
 | 
			
		||||
                                    }
 | 
			
		||||
                                });
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			@ -445,25 +453,18 @@ public class MonitoringRunningExam implements TemplateComposer {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private int getActualRoomSize(final RemoteProctoringRoom room, final Map<RemoteProctoringRoom, TreeItem> rooms) {
 | 
			
		||||
        return rooms.entrySet().stream()
 | 
			
		||||
                .filter(entry -> entry.getKey().equals(room))
 | 
			
		||||
                .findFirst()
 | 
			
		||||
                .map(entry -> entry.getKey().roomSize)
 | 
			
		||||
                .orElseGet(() -> 1);
 | 
			
		||||
    private int getActualRoomSize(
 | 
			
		||||
            final RemoteProctoringRoom room,
 | 
			
		||||
            final Map<String, Pair<RemoteProctoringRoom, TreeItem>> rooms) {
 | 
			
		||||
 | 
			
		||||
        return rooms.get(room.name).a.roomSize;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private PageAction showExamProctoringRoom(
 | 
			
		||||
            final ProctoringSettings proctoringSettings,
 | 
			
		||||
            final RemoteProctoringRoom room,
 | 
			
		||||
            final Map<RemoteProctoringRoom, TreeItem> rooms,
 | 
			
		||||
            final PageAction action) {
 | 
			
		||||
 | 
			
		||||
        final int actualRoomSize = getActualRoomSize(room, rooms);
 | 
			
		||||
        if (actualRoomSize <= 0) {
 | 
			
		||||
            return action;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        final SEBProctoringConnectionData proctoringConnectionData = this.pageService
 | 
			
		||||
                .getRestService()
 | 
			
		||||
                .getBuilder(GetProctorRoomConnectionData.class)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,8 @@ import org.eclipse.swt.layout.RowData;
 | 
			
		|||
import org.eclipse.swt.layout.RowLayout;
 | 
			
		||||
import org.eclipse.swt.widgets.Button;
 | 
			
		||||
import org.eclipse.swt.widgets.Composite;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Value;
 | 
			
		||||
import org.springframework.stereotype.Component;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -41,6 +43,8 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
 | 
			
		|||
@GuiProfile
 | 
			
		||||
public class JitsiMeetProctoringView implements RemoteProctoringView {
 | 
			
		||||
 | 
			
		||||
    private static final Logger log = LoggerFactory.getLogger(JitsiMeetProctoringView.class);
 | 
			
		||||
 | 
			
		||||
    private static final LocTextKey CLOSE_WINDOW_TEXT_KEY =
 | 
			
		||||
            new LocTextKey("sebserver.monitoring.exam.proctoring.action.close");
 | 
			
		||||
    private static final LocTextKey BROADCAST_AUDIO_ON_TEXT_KEY =
 | 
			
		||||
| 
						 | 
				
			
			@ -92,8 +96,17 @@ public class JitsiMeetProctoringView implements RemoteProctoringView {
 | 
			
		|||
                .getProctoringGUIService()
 | 
			
		||||
                .closeRoom(proctoringWindowData.connectionData.roomName));
 | 
			
		||||
 | 
			
		||||
        final String url = this.guiServiceInfo.getExternalServerURIBuilder().toUriString()
 | 
			
		||||
                + this.remoteProctoringEndpoint + this.remoteProctoringViewServletEndpoint + "/";
 | 
			
		||||
        final String url = this.guiServiceInfo
 | 
			
		||||
                .getExternalServerURIBuilder()
 | 
			
		||||
                .toUriString()
 | 
			
		||||
                + this.remoteProctoringEndpoint
 | 
			
		||||
                + this.remoteProctoringViewServletEndpoint
 | 
			
		||||
                + Constants.SLASH;
 | 
			
		||||
 | 
			
		||||
        if (log.isDebugEnabled()) {
 | 
			
		||||
            log.debug("Open proctoring Servlet in IFrame with URL: {}", url);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        final Browser browser = new Browser(content, SWT.NONE | SWT.NO_SCROLL);
 | 
			
		||||
        browser.setLayout(new GridLayout());
 | 
			
		||||
        final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
 | 
			
		||||
| 
						 | 
				
			
			@ -274,7 +287,7 @@ public class JitsiMeetProctoringView implements RemoteProctoringView {
 | 
			
		|||
        return ProctoringServerType.JITSI_MEET;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static class BroadcastActionState {
 | 
			
		||||
    private static final class BroadcastActionState {
 | 
			
		||||
        public static final String KEY_NAME = "BroadcastActionState";
 | 
			
		||||
        boolean audio = false;
 | 
			
		||||
        boolean video = false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -410,68 +410,13 @@ public class ExamMonitoringController {
 | 
			
		|||
        this.authorization.checkRead(
 | 
			
		||||
                this.examSessionService.getExamDAO().byPK(examId).getOrThrow());
 | 
			
		||||
 | 
			
		||||
        final Map<String, String> attributes = new HashMap<>();
 | 
			
		||||
        if (BooleanUtils.isTrue(sendReceiveAudio)) {
 | 
			
		||||
            attributes.put(
 | 
			
		||||
                    ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_RECONFIGURE_SETTINGS.JITSI_RECEIVE_AUDIO,
 | 
			
		||||
        final Map<String, String> attributes = createProctorInstructionAttributes(
 | 
			
		||||
                sendReceiveAudio,
 | 
			
		||||
                sendReceiveVideo,
 | 
			
		||||
                sendAllowChat,
 | 
			
		||||
                Constants.TRUE_STRING);
 | 
			
		||||
        }
 | 
			
		||||
        if (BooleanUtils.isTrue(sendReceiveVideo)) {
 | 
			
		||||
            attributes.put(
 | 
			
		||||
                    ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_RECONFIGURE_SETTINGS.JITSI_RECEIVE_VIDEO,
 | 
			
		||||
                    Constants.TRUE_STRING);
 | 
			
		||||
        }
 | 
			
		||||
        if (BooleanUtils.isTrue(sendAllowChat)) {
 | 
			
		||||
            attributes.put(
 | 
			
		||||
                    ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_RECONFIGURE_SETTINGS.JITSI_ALLOW_CHAT,
 | 
			
		||||
                    Constants.TRUE_STRING);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (attributes.isEmpty()) {
 | 
			
		||||
            log.warn("Missing reconfigure instruction attributes. Skip sending empty instruction to SEB clients");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (StringUtils.isNotBlank(connectionTokens)) {
 | 
			
		||||
            final boolean single = connectionTokens.contains(Constants.LIST_SEPARATOR);
 | 
			
		||||
            (single
 | 
			
		||||
                    ? Arrays.asList(StringUtils.split(connectionTokens, Constants.LIST_SEPARATOR))
 | 
			
		||||
                    : Arrays.asList(connectionTokens))
 | 
			
		||||
                            .stream()
 | 
			
		||||
                            .forEach(connectionToken -> {
 | 
			
		||||
                                this.sebInstructionService.registerInstruction(
 | 
			
		||||
                                        examId,
 | 
			
		||||
                                        InstructionType.SEB_RECONFIGURE_SETTINGS,
 | 
			
		||||
                                        attributes,
 | 
			
		||||
                                        connectionToken,
 | 
			
		||||
                                        true)
 | 
			
		||||
                                        .onError(error -> log.error(
 | 
			
		||||
                                                "Failed to register reconfiguring instruction for connection: {}",
 | 
			
		||||
                                                connectionToken,
 | 
			
		||||
                                                error));
 | 
			
		||||
 | 
			
		||||
                            });
 | 
			
		||||
        } else if (StringUtils.isNotBlank(roomName)) {
 | 
			
		||||
            this.examProcotringRoomService.getRoomConnections(examId, roomName)
 | 
			
		||||
                    .getOrThrow()
 | 
			
		||||
                    .stream()
 | 
			
		||||
                    .forEach(connection -> {
 | 
			
		||||
                        this.sebInstructionService.registerInstruction(
 | 
			
		||||
                                examId,
 | 
			
		||||
                                InstructionType.SEB_RECONFIGURE_SETTINGS,
 | 
			
		||||
                                attributes,
 | 
			
		||||
                                connection.connectionToken,
 | 
			
		||||
                                true)
 | 
			
		||||
                                .onError(error -> log.error(
 | 
			
		||||
                                        "Failed to register reconfiguring instruction for connection: {}",
 | 
			
		||||
                                        connection.connectionToken,
 | 
			
		||||
                                        error));
 | 
			
		||||
                    });
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new RuntimeException("API attribute validation error: missing  "
 | 
			
		||||
                    + Domain.REMOTE_PROCTORING_ROOM.ATTR_ID + " and/or" +
 | 
			
		||||
                    API.EXAM_API_SEB_CONNECTION_TOKEN + " attribute");
 | 
			
		||||
        }
 | 
			
		||||
        sendProctoringInstructions(examId, roomName, connectionTokens, attributes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @RequestMapping(
 | 
			
		||||
| 
						 | 
				
			
			@ -510,68 +455,18 @@ public class ExamMonitoringController {
 | 
			
		|||
        this.authorization.checkRead(
 | 
			
		||||
                this.examSessionService.getExamDAO().byPK(examId).getOrThrow());
 | 
			
		||||
 | 
			
		||||
        final Map<String, String> attributes = new HashMap<>();
 | 
			
		||||
        if (BooleanUtils.isTrue(sendReceiveAudio)) {
 | 
			
		||||
            attributes.put(
 | 
			
		||||
                    ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_RECONFIGURE_SETTINGS.JITSI_RECEIVE_AUDIO,
 | 
			
		||||
        final Map<String, String> attributes = createProctorInstructionAttributes(
 | 
			
		||||
                sendReceiveAudio,
 | 
			
		||||
                sendReceiveVideo,
 | 
			
		||||
                sendAllowChat,
 | 
			
		||||
                Constants.FALSE_STRING);
 | 
			
		||||
        }
 | 
			
		||||
        if (BooleanUtils.isTrue(sendReceiveVideo)) {
 | 
			
		||||
            attributes.put(
 | 
			
		||||
                    ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_RECONFIGURE_SETTINGS.JITSI_RECEIVE_VIDEO,
 | 
			
		||||
                    Constants.FALSE_STRING);
 | 
			
		||||
        }
 | 
			
		||||
        if (BooleanUtils.isTrue(sendAllowChat)) {
 | 
			
		||||
            attributes.put(
 | 
			
		||||
                    ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_RECONFIGURE_SETTINGS.JITSI_ALLOW_CHAT,
 | 
			
		||||
                    Constants.FALSE_STRING);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (attributes.isEmpty()) {
 | 
			
		||||
            log.warn("Missing reconfigure instruction attributes. Skip sending empty instruction to SEB clients");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (StringUtils.isNotBlank(connectionTokens)) {
 | 
			
		||||
            final boolean single = connectionTokens.contains(Constants.LIST_SEPARATOR);
 | 
			
		||||
            (single
 | 
			
		||||
                    ? Arrays.asList(StringUtils.split(connectionTokens, Constants.LIST_SEPARATOR))
 | 
			
		||||
                    : Arrays.asList(connectionTokens))
 | 
			
		||||
                            .stream()
 | 
			
		||||
                            .forEach(connectionToken -> {
 | 
			
		||||
                                this.sebInstructionService.registerInstruction(
 | 
			
		||||
                                        examId,
 | 
			
		||||
                                        InstructionType.SEB_RECONFIGURE_SETTINGS,
 | 
			
		||||
                                        attributes,
 | 
			
		||||
                                        connectionToken,
 | 
			
		||||
                                        true)
 | 
			
		||||
                                        .onError(error -> log.error(
 | 
			
		||||
                                                "Failed to register reconfiguring instruction for connection: {}",
 | 
			
		||||
                                                connectionToken,
 | 
			
		||||
                                                error));
 | 
			
		||||
                            });
 | 
			
		||||
        } else if (StringUtils.isNotBlank(roomName)) {
 | 
			
		||||
 | 
			
		||||
            this.examProcotringRoomService.getRoomConnections(examId, roomName)
 | 
			
		||||
                    .getOrThrow()
 | 
			
		||||
                    .stream()
 | 
			
		||||
                    .forEach(connection -> {
 | 
			
		||||
                        this.sebInstructionService.registerInstruction(
 | 
			
		||||
                                examId,
 | 
			
		||||
                                InstructionType.SEB_RECONFIGURE_SETTINGS,
 | 
			
		||||
                                attributes,
 | 
			
		||||
                                connection.connectionToken,
 | 
			
		||||
                                true)
 | 
			
		||||
                                .onError(error -> log.error(
 | 
			
		||||
                                        "Failed to register reconfiguring instruction for connection: {}",
 | 
			
		||||
                                        connection.connectionToken,
 | 
			
		||||
                                        error));
 | 
			
		||||
                    });
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new RuntimeException("API attribute validation error: missing  "
 | 
			
		||||
                    + Domain.REMOTE_PROCTORING_ROOM.ATTR_ID + " and/or" +
 | 
			
		||||
                    API.EXAM_API_SEB_CONNECTION_TOKEN + " attribute");
 | 
			
		||||
        }
 | 
			
		||||
        sendProctoringInstructions(examId, roomName, connectionTokens, attributes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @RequestMapping(
 | 
			
		||||
| 
						 | 
				
			
			@ -695,6 +590,83 @@ public class ExamMonitoringController {
 | 
			
		|||
                .getOrThrow();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void sendProctoringInstructions(
 | 
			
		||||
            final Long examId,
 | 
			
		||||
            final String roomName,
 | 
			
		||||
            final String connectionTokens,
 | 
			
		||||
            final Map<String, String> attributes) {
 | 
			
		||||
 | 
			
		||||
        if (attributes.isEmpty()) {
 | 
			
		||||
            log.warn("Missing reconfigure instruction attributes. Skip sending empty instruction to SEB clients");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (StringUtils.isNotBlank(connectionTokens)) {
 | 
			
		||||
            final boolean single = connectionTokens.contains(Constants.LIST_SEPARATOR);
 | 
			
		||||
            (single
 | 
			
		||||
                    ? Arrays.asList(StringUtils.split(connectionTokens, Constants.LIST_SEPARATOR))
 | 
			
		||||
                    : Arrays.asList(connectionTokens))
 | 
			
		||||
                            .stream()
 | 
			
		||||
                            .forEach(connectionToken -> {
 | 
			
		||||
                                this.sebInstructionService.registerInstruction(
 | 
			
		||||
                                        examId,
 | 
			
		||||
                                        InstructionType.SEB_RECONFIGURE_SETTINGS,
 | 
			
		||||
                                        attributes,
 | 
			
		||||
                                        connectionToken,
 | 
			
		||||
                                        true)
 | 
			
		||||
                                        .onError(error -> log.error(
 | 
			
		||||
                                                "Failed to register reconfiguring instruction for connection: {}",
 | 
			
		||||
                                                connectionToken,
 | 
			
		||||
                                                error));
 | 
			
		||||
 | 
			
		||||
                            });
 | 
			
		||||
        } else if (StringUtils.isNotBlank(roomName)) {
 | 
			
		||||
            this.examProcotringRoomService.getRoomConnections(examId, roomName)
 | 
			
		||||
                    .getOrThrow()
 | 
			
		||||
                    .stream()
 | 
			
		||||
                    .forEach(connection -> {
 | 
			
		||||
                        this.sebInstructionService.registerInstruction(
 | 
			
		||||
                                examId,
 | 
			
		||||
                                InstructionType.SEB_RECONFIGURE_SETTINGS,
 | 
			
		||||
                                attributes,
 | 
			
		||||
                                connection.connectionToken,
 | 
			
		||||
                                true)
 | 
			
		||||
                                .onError(error -> log.error(
 | 
			
		||||
                                        "Failed to register reconfiguring instruction for connection: {}",
 | 
			
		||||
                                        connection.connectionToken,
 | 
			
		||||
                                        error));
 | 
			
		||||
                    });
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new RuntimeException("API attribute validation error: missing  "
 | 
			
		||||
                    + Domain.REMOTE_PROCTORING_ROOM.ATTR_ID + " and/or" +
 | 
			
		||||
                    API.EXAM_API_SEB_CONNECTION_TOKEN + " attribute");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Map<String, String> createProctorInstructionAttributes(
 | 
			
		||||
            final Boolean sendReceiveAudio,
 | 
			
		||||
            final Boolean sendReceiveVideo,
 | 
			
		||||
            final Boolean sendAllowChat,
 | 
			
		||||
            final String flagValue) {
 | 
			
		||||
        final Map<String, String> attributes = new HashMap<>();
 | 
			
		||||
        if (BooleanUtils.isTrue(sendReceiveAudio)) {
 | 
			
		||||
            attributes.put(
 | 
			
		||||
                    ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_RECONFIGURE_SETTINGS.JITSI_RECEIVE_AUDIO,
 | 
			
		||||
                    flagValue);
 | 
			
		||||
        }
 | 
			
		||||
        if (BooleanUtils.isTrue(sendReceiveVideo)) {
 | 
			
		||||
            attributes.put(
 | 
			
		||||
                    ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_RECONFIGURE_SETTINGS.JITSI_RECEIVE_VIDEO,
 | 
			
		||||
                    flagValue);
 | 
			
		||||
        }
 | 
			
		||||
        if (BooleanUtils.isTrue(sendAllowChat)) {
 | 
			
		||||
            attributes.put(
 | 
			
		||||
                    ClientInstruction.SEB_INSTRUCTION_ATTRIBUTES.SEB_RECONFIGURE_SETTINGS.JITSI_ALLOW_CHAT,
 | 
			
		||||
                    flagValue);
 | 
			
		||||
        }
 | 
			
		||||
        return attributes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //**** Proctoring
 | 
			
		||||
    //***********************************************************************************************
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue