SEBSERV-435 fixes and preparing integration configuration
This commit is contained in:
parent
99ea2472f4
commit
6e5d5e7710
10 changed files with 61 additions and 22 deletions
|
@ -94,15 +94,15 @@ public class ProctoringServlet extends HttpServlet {
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/46582/response-redirect-with-post-instead-of-get
|
// https://stackoverflow.com/questions/46582/response-redirect-with-post-instead-of-get
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
sb.append("<html>");
|
// sb.append("<html>");
|
||||||
sb.append("<body onload='document.forms[\"form\"].submit()'>");
|
// sb.append("<body onload='document.forms[\"form\"].submit()'>");
|
||||||
sb.append("<form name='form' action='");
|
// sb.append("<form name='form' action='");
|
||||||
sb.append(data.loginLocation).append("' method='post'>");
|
// sb.append( "" /* data.loginLocation */).append("' method='post'>");
|
||||||
sb.append("</input type='hidden' name='username' value='").append("super-admin").append("'>");
|
// sb.append("</input type='hidden' name='username' value='").append("super-admin").append("'>");
|
||||||
sb.append("</input type='hidden' name='password' type='password' value='").append("admin").append("'>");
|
// sb.append("</input type='hidden' name='password' type='password' value='").append("admin").append("'>");
|
||||||
sb.append("</form>");
|
// sb.append("</form>");
|
||||||
sb.append("</body>");
|
// sb.append("</body>");
|
||||||
sb.append("</html>");
|
// sb.append("</html>");
|
||||||
|
|
||||||
resp.getOutputStream().println(sb.toString());
|
resp.getOutputStream().println(sb.toString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,6 +148,11 @@ public interface ClientConnectionDAO extends
|
||||||
key = "#connectionToken")
|
key = "#connectionToken")
|
||||||
Result<Void> assignToScreenProctoringGroup(Long connectionId, String connectionToken, Long groupId);
|
Result<Void> assignToScreenProctoringGroup(Long connectionId, String connectionToken, Long groupId);
|
||||||
|
|
||||||
|
@CacheEvict(
|
||||||
|
cacheNames = ExamSessionCacheService.CACHE_NAME_ACTIVE_CLIENT_CONNECTION,
|
||||||
|
key = "#connectionToken")
|
||||||
|
Result<Void> markScreenProcotringApplied(Long connectionId, String connectionToken);
|
||||||
|
|
||||||
/** Get a ClientConnection by connection token.
|
/** Get a ClientConnection by connection token.
|
||||||
*
|
*
|
||||||
* @param connectionToken the connection token
|
* @param connectionToken the connection token
|
||||||
|
|
|
@ -532,7 +532,7 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
|
||||||
|
|
||||||
final List<ClientConnectionRecord> execute = this.clientConnectionRecordMapper
|
final List<ClientConnectionRecord> execute = this.clientConnectionRecordMapper
|
||||||
.selectByExample()
|
.selectByExample()
|
||||||
.where(ClientConnectionRecordDynamicSqlSupport.screenProctoringGroupId, isNull())
|
.where(ClientConnectionRecordDynamicSqlSupport.screenProctoringGroupUpdate, isNotEqualTo((byte) 0))
|
||||||
.and(ClientConnectionRecordDynamicSqlSupport.examId, isIn(examIds))
|
.and(ClientConnectionRecordDynamicSqlSupport.examId, isIn(examIds))
|
||||||
.and(ClientConnectionRecordDynamicSqlSupport.status, isEqualTo(ConnectionStatus.ACTIVE.name()))
|
.and(ClientConnectionRecordDynamicSqlSupport.status, isEqualTo(ConnectionStatus.ACTIVE.name()))
|
||||||
.build()
|
.build()
|
||||||
|
@ -571,6 +571,20 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
|
||||||
this.clientConnectionRecordMapper::update,
|
this.clientConnectionRecordMapper::update,
|
||||||
ClientConnectionRecordDynamicSqlSupport.clientConnectionRecord)
|
ClientConnectionRecordDynamicSqlSupport.clientConnectionRecord)
|
||||||
.set(ClientConnectionRecordDynamicSqlSupport.screenProctoringGroupId).equalTo(groupId)
|
.set(ClientConnectionRecordDynamicSqlSupport.screenProctoringGroupId).equalTo(groupId)
|
||||||
|
//.set(ClientConnectionRecordDynamicSqlSupport.screenProctoringGroupUpdate).equalTo((byte) 0)
|
||||||
|
.where(ClientConnectionRecordDynamicSqlSupport.id, isEqualTo(connectionId))
|
||||||
|
.build()
|
||||||
|
.execute();
|
||||||
|
})
|
||||||
|
.onError(TransactionHandler::rollback);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<Void> markScreenProcotringApplied(final Long connectionId, final String connectionToken) {
|
||||||
|
return Result.tryCatch(() -> {
|
||||||
|
UpdateDSL.updateWithMapper(
|
||||||
|
this.clientConnectionRecordMapper::update,
|
||||||
|
ClientConnectionRecordDynamicSqlSupport.clientConnectionRecord)
|
||||||
.set(ClientConnectionRecordDynamicSqlSupport.screenProctoringGroupUpdate).equalTo((byte) 0)
|
.set(ClientConnectionRecordDynamicSqlSupport.screenProctoringGroupUpdate).equalTo((byte) 0)
|
||||||
.where(ClientConnectionRecordDynamicSqlSupport.id, isEqualTo(connectionId))
|
.where(ClientConnectionRecordDynamicSqlSupport.id, isEqualTo(connectionId))
|
||||||
.build()
|
.build()
|
||||||
|
@ -1136,4 +1150,5 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
|
||||||
.build()
|
.build()
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -381,12 +381,13 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if screen proctoring enabled mark for screen proctoring update
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
final Boolean proctoringEnabled = this.examAdminService
|
final Boolean proctoringEnabled = this.examAdminService
|
||||||
.isProctoringEnabled(clientConnection.examId)
|
.isProctoringEnabled(clientConnection.examId)
|
||||||
.getOr(false);
|
.getOr(false);
|
||||||
|
final Boolean screenProctoringEnabled = this.examAdminService
|
||||||
|
.isScreenProctoringEnabled(clientConnection.examId)
|
||||||
|
.getOr(false);
|
||||||
|
|
||||||
final Long currentExamId = (examId != null) ? examId : clientConnection.examId;
|
final Long currentExamId = (examId != null) ? examId : clientConnection.examId;
|
||||||
final String currentVdiConnectionId = (clientId != null)
|
final String currentVdiConnectionId = (clientId != null)
|
||||||
? clientId
|
? clientId
|
||||||
|
@ -410,7 +411,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
screenProctoringEnabled,
|
||||||
null,
|
null,
|
||||||
proctoringEnabled,
|
proctoringEnabled,
|
||||||
null,
|
null,
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl;
|
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -41,8 +42,10 @@ public class SEBClientPingBatchService implements SEBClientPingService {
|
||||||
private final ThreadPoolTaskScheduler threadPoolTaskScheduler;
|
private final ThreadPoolTaskScheduler threadPoolTaskScheduler;
|
||||||
private final long schendulerInterval;
|
private final long schendulerInterval;
|
||||||
|
|
||||||
|
private final Set<String> pingKeys = new HashSet<>();
|
||||||
private final Map<String, String> pings = new ConcurrentHashMap<>();
|
private final Map<String, String> pings = new ConcurrentHashMap<>();
|
||||||
private final Map<String, String> instructions = new ConcurrentHashMap<>();
|
private final Map<String, String> instructions = new ConcurrentHashMap<>();
|
||||||
|
private final Set<String> confirmedInstructions = Collections.synchronizedSet(new HashSet<>());
|
||||||
|
|
||||||
private ScheduledFuture<?> scheduleAtFixedRate = null;
|
private ScheduledFuture<?> scheduleAtFixedRate = null;
|
||||||
|
|
||||||
|
@ -83,9 +86,10 @@ public class SEBClientPingBatchService implements SEBClientPingService {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final Set<String> connections = new HashSet<>(this.pings.keySet());
|
this.pingKeys.clear();
|
||||||
|
this.pingKeys.addAll(this.pings.keySet());
|
||||||
connections.stream().forEach(cid -> processPing(
|
//final Set<String> connections = new HashSet<>(this.pings.keySet());
|
||||||
|
this.pingKeys.stream().forEach(cid -> processPing(
|
||||||
cid,
|
cid,
|
||||||
this.pings.remove(cid),
|
this.pings.remove(cid),
|
||||||
Utils.getMillisecondsNow()));
|
Utils.getMillisecondsNow()));
|
||||||
|
@ -111,10 +115,10 @@ public class SEBClientPingBatchService implements SEBClientPingService {
|
||||||
System.out.println("************ put instructionConfirm: " + instructionConfirm + " instructions: "
|
System.out.println("************ put instructionConfirm: " + instructionConfirm + " instructions: "
|
||||||
+ this.instructions);
|
+ this.instructions);
|
||||||
this.pings.put(connectionToken, instructionConfirm);
|
this.pings.put(connectionToken, instructionConfirm);
|
||||||
// TODO is this a good idea or is there another better way to deal with instruction confirm synchronization?
|
// // TODO is this a good idea or is there another better way to deal with instruction confirm synchronization?
|
||||||
if (instruction != null && instruction.contains("\"instruction-confirm\":\"" + instructionConfirm + "\"")) {
|
// if (instruction != null && instruction.contains("\"instruction-confirm\":\"" + instructionConfirm + "\"")) {
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
} else if (!this.pings.containsKey(connectionToken)) {
|
} else if (!this.pings.containsKey(connectionToken)) {
|
||||||
this.pings.put(connectionToken, StringUtils.EMPTY);
|
this.pings.put(connectionToken, StringUtils.EMPTY);
|
||||||
}
|
}
|
||||||
|
@ -147,6 +151,10 @@ public class SEBClientPingBatchService implements SEBClientPingService {
|
||||||
this.sebClientInstructionService.confirmInstructionDone(connectionToken, instructionConfirm);
|
this.sebClientInstructionService.confirmInstructionDone(connectionToken, instructionConfirm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.instructions.containsKey(connectionToken)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final String instructionJSON = this.sebClientInstructionService.getInstructionJSON(connectionToken);
|
final String instructionJSON = this.sebClientInstructionService.getInstructionJSON(connectionToken);
|
||||||
if (instructionJSON != null) {
|
if (instructionJSON != null) {
|
||||||
this.instructions.put(connectionToken, instructionJSON);
|
this.instructions.put(connectionToken, instructionJSON);
|
||||||
|
|
|
@ -33,7 +33,7 @@ public class SEBClientPingServiceFactory {
|
||||||
|
|
||||||
public SEBClientPingServiceFactory(
|
public SEBClientPingServiceFactory(
|
||||||
final Collection<SEBClientPingService> serviceBeans,
|
final Collection<SEBClientPingService> serviceBeans,
|
||||||
@Value("${sebserver.webservice.api.exam.session.ping.service.type:BLOCKING}") final String serviceType) {
|
@Value("${sebserver.webservice.api.exam.session.ping.service.strategy:BLOCKING}") final String serviceType) {
|
||||||
|
|
||||||
SEBClientPingService.PingServiceType serviceTypeToSet = SEBClientPingService.PingServiceType.BLOCKING;
|
SEBClientPingService.PingServiceType serviceTypeToSet = SEBClientPingService.PingServiceType.BLOCKING;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -485,6 +485,8 @@ class ScreenProctoringAPIBinding {
|
||||||
final ScreenProctoringGroup localGroup,
|
final ScreenProctoringGroup localGroup,
|
||||||
final ClientConnectionRecord clientConnection) {
|
final ClientConnectionRecord clientConnection) {
|
||||||
|
|
||||||
|
// TODO check if the Session with token UUID already exists and if true, return the token
|
||||||
|
|
||||||
final String token = clientConnection.getConnectionToken();
|
final String token = clientConnection.getConnectionToken();
|
||||||
final ScreenProctoringServiceOAuthTemplate apiTemplate = this.getAPITemplate(examId);
|
final ScreenProctoringServiceOAuthTemplate apiTemplate = this.getAPITemplate(examId);
|
||||||
final String uri = UriComponentsBuilder
|
final String uri = UriComponentsBuilder
|
||||||
|
|
|
@ -316,6 +316,10 @@ public class ScreenProctoringServiceImpl implements ScreenProctoringService {
|
||||||
// create instruction for SEB and add it to instruction queue for SEB connection
|
// create instruction for SEB and add it to instruction queue for SEB connection
|
||||||
registerJoinInstruction(ccRecord, spsSessionToken, group, runningExam);
|
registerJoinInstruction(ccRecord, spsSessionToken, group, runningExam);
|
||||||
|
|
||||||
|
this.clientConnectionDAO
|
||||||
|
.markScreenProcotringApplied(ccRecord.getId(), ccRecord.getConnectionToken())
|
||||||
|
.getOrThrow();
|
||||||
|
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
log.error("Failed to apply screen proctoring session to SEB with connection: ", ccRecord, e);
|
log.error("Failed to apply screen proctoring session to SEB with connection: ", ccRecord, e);
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ sebserver.webservice.api.exam.endpoint=/exam-api
|
||||||
sebserver.webservice.api.exam.endpoint.discovery=${sebserver.webservice.api.exam.endpoint}/discovery
|
sebserver.webservice.api.exam.endpoint.discovery=${sebserver.webservice.api.exam.endpoint}/discovery
|
||||||
sebserver.webservice.api.exam.endpoint.v1=${sebserver.webservice.api.exam.endpoint}/v1
|
sebserver.webservice.api.exam.endpoint.v1=${sebserver.webservice.api.exam.endpoint}/v1
|
||||||
sebserver.webservice.api.exam.event-handling-strategy=ASYNC_BATCH_STORE_STRATEGY
|
sebserver.webservice.api.exam.event-handling-strategy=ASYNC_BATCH_STORE_STRATEGY
|
||||||
|
sebserver.webservice.api.exam.session.ping.service.strategy=BATCH
|
||||||
sebserver.webservice.api.exam.enable-indicator-cache=true
|
sebserver.webservice.api.exam.enable-indicator-cache=true
|
||||||
sebserver.webservice.api.exam.defaultPingInterval=1000
|
sebserver.webservice.api.exam.defaultPingInterval=1000
|
||||||
sebserver.webservice.api.pagination.maxPageSize=500
|
sebserver.webservice.api.pagination.maxPageSize=500
|
||||||
|
|
|
@ -65,4 +65,7 @@ sebserver.ssl.redirect.html.port=8080
|
||||||
|
|
||||||
# features
|
# features
|
||||||
sebserver.feature.seb.screenProctoring=false
|
sebserver.feature.seb.screenProctoring=false
|
||||||
|
sebserver.feature.seb.screenProctoring.bundled=true
|
||||||
|
sebserver.feature.seb.screenProctoring.bundled.clientId=sebserverClient
|
||||||
|
sebserver.feature.seb.screenProctoring.bundled.clientPassword=${sebserver.password}
|
||||||
sebserver.feature.CollectingRoomStrategy.SEB-GROUP=false
|
sebserver.feature.CollectingRoomStrategy.SEB-GROUP=false
|
||||||
|
|
Loading…
Reference in a new issue