SEBSERV-560 SEBSERV-563 implementation
This commit is contained in:
parent
f2f8a561a8
commit
303b3ac548
8 changed files with 167 additions and 68 deletions
|
@ -8,11 +8,21 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui.content.monitoring;
|
package ch.ethz.seb.sebserver.gui.content.monitoring;
|
||||||
|
|
||||||
|
import static ch.ethz.seb.sebserver.gbl.model.user.UserFeatures.Feature.EXAM_SCREEN_PROCTORING;
|
||||||
|
import static ch.ethz.seb.sebserver.gbl.model.user.UserFeatures.Feature.MONITORING_RUNNING_EXAM_SCREEN_PROCTORING;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.BooleanSupplier;
|
import java.util.function.BooleanSupplier;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.exam.ScreenProctoringSettings;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.session.ScreenProctoringGroup;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetScreenProctoringGroups;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.session.proctoring.MonitoringProctoringService;
|
||||||
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.eclipse.rap.rwt.RWT;
|
import org.eclipse.rap.rwt.RWT;
|
||||||
import org.eclipse.rap.rwt.client.service.UrlLauncher;
|
import org.eclipse.rap.rwt.client.service.UrlLauncher;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
@ -93,6 +103,7 @@ public class FinishedExam implements TemplateComposer {
|
||||||
private final RestService restService;
|
private final RestService restService;
|
||||||
private final I18nSupport i18nSupport;
|
private final I18nSupport i18nSupport;
|
||||||
private final DownloadService downloadService;
|
private final DownloadService downloadService;
|
||||||
|
private final MonitoringProctoringService monitoringProctoringService;
|
||||||
private final String exportFileName;
|
private final String exportFileName;
|
||||||
private final int pageSize;
|
private final int pageSize;
|
||||||
|
|
||||||
|
@ -100,12 +111,14 @@ public class FinishedExam implements TemplateComposer {
|
||||||
final ServerPushService serverPushService,
|
final ServerPushService serverPushService,
|
||||||
final PageService pageService,
|
final PageService pageService,
|
||||||
final DownloadService downloadService,
|
final DownloadService downloadService,
|
||||||
|
final MonitoringProctoringService monitoringProctoringService,
|
||||||
@Value("${sebserver.gui.seb.client.logs.export.filename:SEBClientLogs}") final String exportFileName,
|
@Value("${sebserver.gui.seb.client.logs.export.filename:SEBClientLogs}") final String exportFileName,
|
||||||
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
|
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
|
||||||
|
|
||||||
this.pageService = pageService;
|
this.pageService = pageService;
|
||||||
this.restService = pageService.getRestService();
|
this.restService = pageService.getRestService();
|
||||||
this.downloadService = downloadService;
|
this.downloadService = downloadService;
|
||||||
|
this.monitoringProctoringService = monitoringProctoringService;
|
||||||
this.exportFileName = exportFileName;
|
this.exportFileName = exportFileName;
|
||||||
this.pageSize = pageSize;
|
this.pageSize = pageSize;
|
||||||
|
|
||||||
|
@ -209,6 +222,33 @@ public class FinishedExam implements TemplateComposer {
|
||||||
.withExec(this::exportCSV)
|
.withExec(this::exportCSV)
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publish();
|
.publish();
|
||||||
|
|
||||||
|
// screen proctoring link
|
||||||
|
final ScreenProctoringSettings screenProctoringSettings = new ScreenProctoringSettings(exam);
|
||||||
|
final boolean screenProctoringEnabled =
|
||||||
|
currentUser.isFeatureEnabled(MONITORING_RUNNING_EXAM_SCREEN_PROCTORING)
|
||||||
|
&& BooleanUtils.toBoolean(screenProctoringSettings.enableScreenProctoring);
|
||||||
|
if (screenProctoringEnabled) {
|
||||||
|
this.pageService
|
||||||
|
.getRestService()
|
||||||
|
.getBuilder(GetScreenProctoringGroups.class)
|
||||||
|
.withURIVariable(API.PARAM_MODEL_ID, exam.getModelId())
|
||||||
|
.call()
|
||||||
|
.onError(error -> log.error("Failed to get screen proctoring group data:", error))
|
||||||
|
.getOr(Collections.emptyList())
|
||||||
|
.forEach(group -> {
|
||||||
|
actionBuilder
|
||||||
|
.newAction(ActionDefinition.MONITOR_EXAM_VIEW_SCREEN_PROCTOR_GROUP)
|
||||||
|
.withEntityKey(exam.getEntityKey())
|
||||||
|
.withExec(_action -> monitoringProctoringService.openScreenProctoringTab(
|
||||||
|
screenProctoringSettings,
|
||||||
|
group,
|
||||||
|
_action))
|
||||||
|
.withNameAttributes(group.name, group.size)
|
||||||
|
.noEventPropagation()
|
||||||
|
.publish();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private PageAction exportCSV(final PageAction action) {
|
private PageAction exportCSV(final PageAction action) {
|
||||||
|
|
|
@ -22,7 +22,6 @@ import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.AllowedSEBVersion;
|
import ch.ethz.seb.sebserver.gbl.model.exam.AllowedSEBVersion;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.user.UserFeatures;
|
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.apache.commons.text.StringEscapeUtils;
|
import org.apache.commons.text.StringEscapeUtils;
|
||||||
import org.eclipse.swt.SWT;
|
import org.eclipse.swt.SWT;
|
||||||
|
@ -391,7 +390,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
.getBuilder(GetScreenProctoringGroups.class)
|
.getBuilder(GetScreenProctoringGroups.class)
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||||
.call()
|
.call()
|
||||||
.onError(error -> log.error("Failed to get collecting room data:", error))
|
.onError(error -> log.error("\"Failed to get screen proctoring group data:", error))
|
||||||
.getOr(Collections.emptyList())
|
.getOr(Collections.emptyList())
|
||||||
: Collections.emptyList();
|
: Collections.emptyList();
|
||||||
|
|
||||||
|
@ -684,7 +683,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
|
|
||||||
|
|
||||||
if (!this.actionItemPerClientGroup.isEmpty()) {
|
if (!this.actionItemPerClientGroup.isEmpty()) {
|
||||||
this.actionItemPerClientGroup.entrySet().stream().forEach(entry -> {
|
this.actionItemPerClientGroup.entrySet().forEach(entry -> {
|
||||||
final int numOfConnections = monitoringStatus.getNumOfConnections(entry.getKey());
|
final int numOfConnections = monitoringStatus.getNumOfConnections(entry.getKey());
|
||||||
if (numOfConnections >= 0) {
|
if (numOfConnections >= 0) {
|
||||||
final TreeItem treeItem = entry.getValue();
|
final TreeItem treeItem = entry.getValue();
|
||||||
|
|
|
@ -215,13 +215,8 @@ public class MonitoringProctoringService {
|
||||||
this.pageService.publishAction(
|
this.pageService.publishAction(
|
||||||
actionBuilder.newAction(ActionDefinition.MONITOR_EXAM_VIEW_SCREEN_PROCTOR_GROUP)
|
actionBuilder.newAction(ActionDefinition.MONITOR_EXAM_VIEW_SCREEN_PROCTOR_GROUP)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
.withExec(_action -> openScreenProctoringTab(
|
.withExec(_action -> openScreenProctoringTab(settings, group, _action))
|
||||||
settings,
|
.withNameAttributes(group.name, group.size)
|
||||||
group,
|
|
||||||
_action))
|
|
||||||
.withNameAttributes(
|
|
||||||
group.name,
|
|
||||||
group.size)
|
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.create(),
|
.create(),
|
||||||
_treeItem -> proctoringGUIService.registerScreeProctoringGroupAction(group, _treeItem));
|
_treeItem -> proctoringGUIService.registerScreeProctoringGroupAction(group, _treeItem));
|
||||||
|
@ -308,7 +303,7 @@ public class MonitoringProctoringService {
|
||||||
this.proctorRoomConnectionsPopup.show(pc, collectingRoom.subject);
|
this.proctorRoomConnectionsPopup.show(pc, collectingRoom.subject);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PageAction openScreenProctoringTab(
|
public PageAction openScreenProctoringTab(
|
||||||
final ScreenProctoringSettings settings,
|
final ScreenProctoringSettings settings,
|
||||||
final ScreenProctoringGroup group,
|
final ScreenProctoringGroup group,
|
||||||
final PageAction _action) {
|
final PageAction _action) {
|
||||||
|
|
|
@ -54,9 +54,7 @@ public interface ScreenProctoringGroupDAO {
|
||||||
*
|
*
|
||||||
* @param examId the exam identifier
|
* @param examId the exam identifier
|
||||||
* @param maxSize the maximum size of connection collected in one collecting group. Size of 0 means no limit.
|
* @param maxSize the maximum size of connection collected in one collecting group. Size of 0 means no limit.
|
||||||
* @param newGroupFunction Function to create data for a new collecting group if needed.
|
* @return Result refer to the collecting group record of place or to an error when happened*/
|
||||||
* @return Result refer to the collecting group record of place or to an error when happened
|
|
||||||
* @throws If the Result contains a AllGroupsFullException, there must be created a new Group first */
|
|
||||||
Result<ScreenProctoringGroup> reservePlaceInCollectingGroup(Long examId, int maxSize);
|
Result<ScreenProctoringGroup> reservePlaceInCollectingGroup(Long examId, int maxSize);
|
||||||
|
|
||||||
Result<ScreenProctoringGroup> releasePlaceInCollectingGroup(Long examId, Long groupId);
|
Result<ScreenProctoringGroup> releasePlaceInCollectingGroup(Long examId, Long groupId);
|
||||||
|
@ -80,4 +78,5 @@ public interface ScreenProctoringGroupDAO {
|
||||||
* @return Result refer to a collection of entity keys for all delete group records or to an error when happened */
|
* @return Result refer to a collection of entity keys for all delete group records or to an error when happened */
|
||||||
Result<Collection<EntityKey>> deleteGroups(Long examId);
|
Result<Collection<EntityKey>> deleteGroups(Long examId);
|
||||||
|
|
||||||
|
void updateGroupSize(String groupUUID, Integer activeCount, Integer totalCount);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl;
|
package ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl;
|
||||||
|
|
||||||
import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo;
|
import static org.mybatis.dynamic.sql.SqlBuilder.*;
|
||||||
import static org.mybatis.dynamic.sql.SqlBuilder.isIn;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -142,7 +141,8 @@ public class ScreenProctoringGroupDAOImpl implements ScreenProctoringGroupDAO {
|
||||||
.findFirst();
|
.findFirst();
|
||||||
|
|
||||||
if (room.isPresent()) {
|
if (room.isPresent()) {
|
||||||
return updateCollectingGroup(room.get());
|
return room.get();
|
||||||
|
//return updateCollectingGroup(room.get());
|
||||||
} else {
|
} else {
|
||||||
throw new AllGroupsFullException();
|
throw new AllGroupsFullException();
|
||||||
}
|
}
|
||||||
|
@ -234,6 +234,31 @@ public class ScreenProctoringGroupDAOImpl implements ScreenProctoringGroupDAO {
|
||||||
return tryCatch.onError(TransactionHandler::rollback);
|
return tryCatch.onError(TransactionHandler::rollback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void updateGroupSize(
|
||||||
|
final String groupUUID,
|
||||||
|
final Integer activeCount,
|
||||||
|
final Integer totalCount) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
UpdateDSL.updateWithMapper(
|
||||||
|
this.screenProctoringGroopRecordMapper::update,
|
||||||
|
ScreenProctoringGroopRecordDynamicSqlSupport.screenProctoringGroopRecord)
|
||||||
|
.set(ScreenProctoringGroopRecordDynamicSqlSupport.size)
|
||||||
|
.equalTo(activeCount)
|
||||||
|
.where(ScreenProctoringGroopRecordDynamicSqlSupport.uuid, isEqualTo(groupUUID))
|
||||||
|
.and(ScreenProctoringGroopRecordDynamicSqlSupport.size, isNotEqualTo(activeCount))
|
||||||
|
.build()
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
} catch (final Exception e) {
|
||||||
|
log.warn("Failed to update SPS group size: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private ScreenProctoringGroup toDomainModel(final ScreenProctoringGroopRecord record) {
|
private ScreenProctoringGroup toDomainModel(final ScreenProctoringGroopRecord record) {
|
||||||
return new ScreenProctoringGroup(
|
return new ScreenProctoringGroup(
|
||||||
record.getId(),
|
record.getId(),
|
||||||
|
@ -244,22 +269,22 @@ public class ScreenProctoringGroupDAOImpl implements ScreenProctoringGroupDAO {
|
||||||
record.getData());
|
record.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScreenProctoringGroopRecord updateCollectingGroup(
|
// private ScreenProctoringGroopRecord updateCollectingGroup(
|
||||||
final ScreenProctoringGroopRecord screenProctoringGroopRecord) {
|
// final ScreenProctoringGroopRecord screenProctoringGroupRecord) {
|
||||||
|
//
|
||||||
final Long id = screenProctoringGroopRecord.getId();
|
// final Long id = screenProctoringGroupRecord.getId();
|
||||||
|
//
|
||||||
UpdateDSL.updateWithMapper(
|
// UpdateDSL.updateWithMapper(
|
||||||
this.screenProctoringGroopRecordMapper::update,
|
// this.screenProctoringGroopRecordMapper::update,
|
||||||
ScreenProctoringGroopRecordDynamicSqlSupport.screenProctoringGroopRecord)
|
// ScreenProctoringGroopRecordDynamicSqlSupport.screenProctoringGroopRecord)
|
||||||
.set(ScreenProctoringGroopRecordDynamicSqlSupport.size)
|
// .set(ScreenProctoringGroopRecordDynamicSqlSupport.size)
|
||||||
.equalTo(screenProctoringGroopRecord.getSize() + 1)
|
// .equalTo(screenProctoringGroupRecord.getSize() + 1)
|
||||||
.where(ScreenProctoringGroopRecordDynamicSqlSupport.id, isEqualTo(id))
|
// .where(ScreenProctoringGroopRecordDynamicSqlSupport.id, isEqualTo(id))
|
||||||
.build()
|
// .build()
|
||||||
.execute();
|
// .execute();
|
||||||
|
//
|
||||||
return this.screenProctoringGroopRecordMapper.selectByPrimaryKey(id);
|
// return this.screenProctoringGroopRecordMapper.selectByPrimaryKey(id);
|
||||||
}
|
// }
|
||||||
|
|
||||||
public static final class AllGroupsFullException extends RuntimeException {
|
public static final class AllGroupsFullException extends RuntimeException {
|
||||||
private static final long serialVersionUID = 3283129187819160485L;
|
private static final long serialVersionUID = 3283129187819160485L;
|
||||||
|
|
|
@ -33,6 +33,7 @@ public interface ScreenProctoringService extends SessionUpdateTask {
|
||||||
@Override
|
@Override
|
||||||
default void processSessionUpdateTask() {
|
default void processSessionUpdateTask() {
|
||||||
updateClientConnections();
|
updateClientConnections();
|
||||||
|
updateActiveGroups();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isScreenProctoringEnabled(Long examId);
|
boolean isScreenProctoringEnabled(Long examId);
|
||||||
|
@ -98,6 +99,10 @@ public interface ScreenProctoringService extends SessionUpdateTask {
|
||||||
* SPS connection instruction to SEB client to connect and start sending screenshots. */
|
* SPS connection instruction to SEB client to connect and start sending screenshots. */
|
||||||
void updateClientConnections();
|
void updateClientConnections();
|
||||||
|
|
||||||
|
/** This goes through all running exams with screen proctoring enabled and updates the group attributes
|
||||||
|
* (mainly the number of active clients in the group) by call ing SPS API and store newest data. */
|
||||||
|
void updateActiveGroups();
|
||||||
|
|
||||||
@Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME)
|
@Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME)
|
||||||
void synchronizeSPSUser(final String userUUID);
|
void synchronizeSPSUser(final String userUUID);
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,8 @@ class ScreenProctoringAPIBinding {
|
||||||
String TOKEN_ENDPOINT = "/oauth/token";
|
String TOKEN_ENDPOINT = "/oauth/token";
|
||||||
String TEST_ENDPOINT = "/admin-api/v1/proctoring/group";
|
String TEST_ENDPOINT = "/admin-api/v1/proctoring/group";
|
||||||
|
|
||||||
|
String GROUP_COUNT_ENDPOINT = "/admin-api/v1/proctoring/active_counts";
|
||||||
|
|
||||||
String USER_ACCOUNT_ENDPOINT = "/admin-api/v1/useraccount/";
|
String USER_ACCOUNT_ENDPOINT = "/admin-api/v1/useraccount/";
|
||||||
String USERSYNC_SEBSERVER_ENDPOINT = USER_ACCOUNT_ENDPOINT + "usersync/sebserver";
|
String USERSYNC_SEBSERVER_ENDPOINT = USER_ACCOUNT_ENDPOINT + "usersync/sebserver";
|
||||||
String ENTITY_PRIVILEGES_ENDPOINT = USER_ACCOUNT_ENDPOINT + "entityprivilege";
|
String ENTITY_PRIVILEGES_ENDPOINT = USER_ACCOUNT_ENDPOINT + "entityprivilege";
|
||||||
|
@ -151,7 +153,7 @@ class ScreenProctoringAPIBinding {
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
static final class ExamUpdate {
|
final class ExamUpdate {
|
||||||
@JsonProperty(EXAM.ATTR_NAME)
|
@JsonProperty(EXAM.ATTR_NAME)
|
||||||
final String name;
|
final String name;
|
||||||
@JsonProperty(EXAM.ATTR_DESCRIPTION)
|
@JsonProperty(EXAM.ATTR_DESCRIPTION)
|
||||||
|
@ -187,6 +189,27 @@ class ScreenProctoringAPIBinding {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
static final class GroupSessionCount {
|
||||||
|
@JsonProperty("uuid")
|
||||||
|
public final String groupUUID;
|
||||||
|
@JsonProperty("activeCount")
|
||||||
|
public final Integer activeCount;
|
||||||
|
@JsonProperty("totalCount")
|
||||||
|
public final Integer totalCount;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public GroupSessionCount(
|
||||||
|
@JsonProperty("uuid") final String groupUUID,
|
||||||
|
@JsonProperty("activeCount") final Integer activeCount,
|
||||||
|
@JsonProperty("totalCount") final Integer totalCount) {
|
||||||
|
|
||||||
|
this.groupUUID = groupUUID;
|
||||||
|
this.activeCount = activeCount;
|
||||||
|
this.totalCount = totalCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final UserDAO userDAO;
|
private final UserDAO userDAO;
|
||||||
private final Cryptor cryptor;
|
private final Cryptor cryptor;
|
||||||
private final AsyncService asyncService;
|
private final AsyncService asyncService;
|
||||||
|
@ -749,6 +772,35 @@ class ScreenProctoringAPIBinding {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<GroupSessionCount> getActiveGroupSessionCounts() {
|
||||||
|
try {
|
||||||
|
|
||||||
|
final ScreenProctoringServiceOAuthTemplate apiTemplate = this.getAPITemplate(null);
|
||||||
|
|
||||||
|
final String uri = UriComponentsBuilder
|
||||||
|
.fromUriString(apiTemplate.spsAPIAccessData.getSpsServiceURL())
|
||||||
|
.path(SPS_API.GROUP_COUNT_ENDPOINT)
|
||||||
|
.build()
|
||||||
|
.toUriString();
|
||||||
|
|
||||||
|
|
||||||
|
final ResponseEntity<String> exchange = apiTemplate.exchange(uri, HttpMethod.POST);
|
||||||
|
if (exchange.getStatusCode() != HttpStatus.OK) {
|
||||||
|
log.error("Failed to request active group session counts: {}", exchange);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.jsonMapper.readValue(
|
||||||
|
exchange.getBody(),
|
||||||
|
new TypeReference<Collection<GroupSessionCount>>() {
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (final Exception e) {
|
||||||
|
log.error("Failed to get active group session counts: {}", e.getMessage());
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void synchronizeUserAccount(
|
private void synchronizeUserAccount(
|
||||||
final String userUUID,
|
final String userUUID,
|
||||||
final ScreenProctoringServiceOAuthTemplate apiTemplate) {
|
final ScreenProctoringServiceOAuthTemplate apiTemplate) {
|
||||||
|
@ -1187,39 +1239,6 @@ class ScreenProctoringAPIBinding {
|
||||||
|
|
||||||
return apiTemplateExam;
|
return apiTemplateExam;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (this.apiTemplate == null || !this.apiTemplate.isValid(examId)) {
|
|
||||||
// if (examId != null) {
|
|
||||||
//
|
|
||||||
// if (log.isDebugEnabled()) {
|
|
||||||
// log.debug("Create new ScreenProctoringServiceOAuthTemplate for exam: {}", examId);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// final ScreenProctoringSettings settings = this.proctoringSettingsDAO
|
|
||||||
// .getScreenProctoringSettings(new EntityKey(examId, EntityType.EXAM))
|
|
||||||
// .getOrThrow();
|
|
||||||
// this.testConnection(settings).getOrThrow();
|
|
||||||
// this.apiTemplate = new ScreenProctoringServiceOAuthTemplate(this, settings);
|
|
||||||
//
|
|
||||||
// } else if (this.webserviceInfo.getScreenProctoringServiceBundle().bundled) {
|
|
||||||
//
|
|
||||||
// if (log.isDebugEnabled()) {
|
|
||||||
// log.debug("Create new ScreenProctoringServiceOAuthTemplate for exam: {}", examId);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// final WebserviceInfo.ScreenProctoringServiceBundle bundle = this.webserviceInfo
|
|
||||||
// .getScreenProctoringServiceBundle();
|
|
||||||
//
|
|
||||||
// this.testConnection(bundle).getOrThrow();
|
|
||||||
// this.apiTemplate = new ScreenProctoringServiceOAuthTemplate(this, bundle);
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
// throw new IllegalStateException("No SPS API access information found!");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return this.apiTemplate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<String> getSupporterIds(final Exam exam) {
|
private static List<String> getSupporterIds(final Exam exam) {
|
||||||
|
|
|
@ -18,7 +18,6 @@ import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||||
import ch.ethz.seb.sebserver.webservice.WebserviceInfo;
|
import ch.ethz.seb.sebserver.webservice.WebserviceInfo;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.LmsSetupChangeEvent;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.LmsSetupChangeEvent;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.*;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.*;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -244,6 +243,24 @@ public class ScreenProctoringServiceImpl implements ScreenProctoringService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateActiveGroups() {
|
||||||
|
try {
|
||||||
|
|
||||||
|
screenProctoringAPIBinding
|
||||||
|
.getActiveGroupSessionCounts()
|
||||||
|
.forEach(groupCount -> {
|
||||||
|
screenProctoringGroupDAO.updateGroupSize(
|
||||||
|
groupCount.groupUUID,
|
||||||
|
groupCount.activeCount,
|
||||||
|
groupCount.totalCount);
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (final Exception e) {
|
||||||
|
log.warn("Failed to update actual group session counts.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyExamSaved(final Exam exam) {
|
public void notifyExamSaved(final Exam exam) {
|
||||||
if (!this.isScreenProctoringEnabled(exam.id)) {
|
if (!this.isScreenProctoringEnabled(exam.id)) {
|
||||||
|
|
Loading…
Reference in a new issue