SEBSLI-9 create new endpoint for light setup to stream exam config
This commit is contained in:
parent
074b63580b
commit
cecce64ba0
5 changed files with 173 additions and 27 deletions
|
@ -84,6 +84,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements E
|
||||||
.antMatchers(ERROR_PATH)
|
.antMatchers(ERROR_PATH)
|
||||||
.antMatchers(CHECK_PATH)
|
.antMatchers(CHECK_PATH)
|
||||||
.antMatchers(this.examAPIDiscoveryEndpoint)
|
.antMatchers(this.examAPIDiscoveryEndpoint)
|
||||||
|
.antMatchers(this.examAPIDiscoveryEndpoint + API.EXAM_API_CONFIGURATION_LIGHT_ENDPOINT)
|
||||||
.antMatchers(this.adminAPIEndpoint + API.INFO_ENDPOINT + API.LOGO_PATH_SEGMENT + "/**")
|
.antMatchers(this.adminAPIEndpoint + API.INFO_ENDPOINT + API.LOGO_PATH_SEGMENT + "/**")
|
||||||
.antMatchers(this.adminAPIEndpoint + API.INFO_ENDPOINT + API.INFO_INST_PATH_SEGMENT + "/**")
|
.antMatchers(this.adminAPIEndpoint + API.INFO_ENDPOINT + API.INFO_INST_PATH_SEGMENT + "/**")
|
||||||
.antMatchers(this.adminAPIEndpoint + API.REGISTER_ENDPOINT);
|
.antMatchers(this.adminAPIEndpoint + API.REGISTER_ENDPOINT);
|
||||||
|
|
|
@ -123,6 +123,8 @@ public final class API {
|
||||||
|
|
||||||
public static final String EXAM_API_CONFIGURATION_REQUEST_ENDPOINT = "/examconfig";
|
public static final String EXAM_API_CONFIGURATION_REQUEST_ENDPOINT = "/examconfig";
|
||||||
|
|
||||||
|
public static final String EXAM_API_CONFIGURATION_LIGHT_ENDPOINT = "/light-config";
|
||||||
|
|
||||||
public static final String EXAM_API_PING_ENDPOINT = "/sebping";
|
public static final String EXAM_API_PING_ENDPOINT = "/sebping";
|
||||||
|
|
||||||
public static final String EXAM_API_PING_TIMESTAMP = "timestamp";
|
public static final String EXAM_API_PING_TIMESTAMP = "timestamp";
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
package ch.ethz.seb.sebserver.webservice.servicelayer.session;
|
package ch.ethz.seb.sebserver.webservice.servicelayer.session;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
@ -173,4 +174,8 @@ public interface SEBClientConnectionService {
|
||||||
String ipAddress,
|
String ipAddress,
|
||||||
HttpServletResponse response);
|
HttpServletResponse response);
|
||||||
|
|
||||||
|
void streamLightExamConfig(
|
||||||
|
String modelId,
|
||||||
|
HttpServletResponse response) throws IOException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,23 +8,36 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl;
|
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl;
|
||||||
|
|
||||||
import javax.servlet.ServletOutputStream;
|
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.security.Principal;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
|
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.exam.ScreenProctoringSettings;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.sebconfig.SEBClientConfig;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.sebconfig.SEBClientConfig.VDIType;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.WebserviceInfo;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.SEBClientConfigDAO;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.institution.SecurityKeyService;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ClientConfigService;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientConnectionService;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientInstructionService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientInstructionService;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator.DistributedIndicatorValueService;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.weblayer.api.APIConstraintViolationException;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
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;
|
||||||
|
@ -34,25 +47,20 @@ import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.security.access.AccessDeniedException;
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
import javax.servlet.ServletOutputStream;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
import java.io.IOException;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.SEBClientConfig;
|
import java.io.PipedInputStream;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.SEBClientConfig.VDIType;
|
import java.io.PipedOutputStream;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
|
import java.security.Principal;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
|
import java.util.Arrays;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
|
import java.util.Collection;
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
import java.util.Collections;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
import java.util.Objects;
|
||||||
import ch.ethz.seb.sebserver.webservice.WebserviceInfo;
|
import java.util.UUID;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO;
|
import java.util.function.Predicate;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.SEBClientConfigDAO;
|
import java.util.stream.Collectors;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService;
|
import java.util.stream.Stream;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.institution.SecurityKeyService;
|
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService;
|
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientConnectionService;
|
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator.DistributedIndicatorValueService;
|
|
||||||
import ch.ethz.seb.sebserver.webservice.weblayer.api.APIConstraintViolationException;
|
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
@Service
|
@Service
|
||||||
|
@ -79,6 +87,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
|
||||||
private final SecurityKeyService securityKeyService;
|
private final SecurityKeyService securityKeyService;
|
||||||
private final SEBClientEventBatchService sebClientEventBatchService;
|
private final SEBClientEventBatchService sebClientEventBatchService;
|
||||||
private final SEBClientInstructionService sebClientInstructionService;
|
private final SEBClientInstructionService sebClientInstructionService;
|
||||||
|
private final ClientConfigService clientConfigService;
|
||||||
private final JSONMapper jsonMapper;
|
private final JSONMapper jsonMapper;
|
||||||
private final boolean isDistributedSetup;
|
private final boolean isDistributedSetup;
|
||||||
|
|
||||||
|
@ -92,6 +101,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
|
||||||
final WebserviceInfo webserviceInfo,
|
final WebserviceInfo webserviceInfo,
|
||||||
final SEBClientEventBatchService sebClientEventBatchService,
|
final SEBClientEventBatchService sebClientEventBatchService,
|
||||||
final SEBClientInstructionService sebClientInstructionService,
|
final SEBClientInstructionService sebClientInstructionService,
|
||||||
|
final ClientConfigService clientConfigService,
|
||||||
final JSONMapper jsonMapper) {
|
final JSONMapper jsonMapper) {
|
||||||
|
|
||||||
this.examSessionService = examSessionService;
|
this.examSessionService = examSessionService;
|
||||||
|
@ -105,6 +115,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
|
||||||
this.isDistributedSetup = webserviceInfo.isDistributed();
|
this.isDistributedSetup = webserviceInfo.isDistributed();
|
||||||
this.sebClientEventBatchService = sebClientEventBatchService;
|
this.sebClientEventBatchService = sebClientEventBatchService;
|
||||||
this.sebClientInstructionService = sebClientInstructionService;
|
this.sebClientInstructionService = sebClientInstructionService;
|
||||||
|
this.clientConfigService = clientConfigService;
|
||||||
this.jsonMapper = jsonMapper;
|
this.jsonMapper = jsonMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -623,6 +634,38 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void streamLightExamConfig(final String modelId, final HttpServletResponse response) throws IOException{
|
||||||
|
|
||||||
|
final ServletOutputStream outputStream = response.getOutputStream();
|
||||||
|
PipedOutputStream pout;
|
||||||
|
PipedInputStream pin;
|
||||||
|
|
||||||
|
try {
|
||||||
|
pout = new PipedOutputStream();
|
||||||
|
pin = new PipedInputStream(pout);
|
||||||
|
|
||||||
|
this.clientConfigService.exportSEBClientConfiguration(
|
||||||
|
pout,
|
||||||
|
modelId,
|
||||||
|
null);
|
||||||
|
|
||||||
|
IOUtils.copyLarge(pin, outputStream);
|
||||||
|
|
||||||
|
response.setStatus(HttpStatus.OK.value());
|
||||||
|
|
||||||
|
outputStream.flush();
|
||||||
|
|
||||||
|
}catch(Exception e){
|
||||||
|
final APIMessage errorMessage = APIMessage.ErrorMessage.GENERIC.of(e.getMessage());
|
||||||
|
outputStream.write(Utils.toByteArray(this.jsonMapper.writeValueAsString(errorMessage)));
|
||||||
|
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
outputStream.flush();
|
||||||
|
outputStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void writeSEBClientErrors(
|
private void writeSEBClientErrors(
|
||||||
final HttpServletResponse response,
|
final HttpServletResponse response,
|
||||||
final Collection<APIMessage> errorMessages) {
|
final Collection<APIMessage> errorMessages) {
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 ETH Zürich, IT Services / Informatikdienste (ID)
|
||||||
|
*
|
||||||
|
* 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.webservice.weblayer.api;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.async.AsyncServiceSpringConfig;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.SEBClientConfigDAO;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientConnectionService;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@WebServiceProfile
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("${sebserver.webservice.api.exam.endpoint.discovery}")
|
||||||
|
@ConditionalOnExpression("'${sebserver.webservice.light.setup}'.equals('true')")
|
||||||
|
public class ExamAPIDiscoveryLightController {
|
||||||
|
|
||||||
|
private final SEBClientConnectionService sebClientConnectionService;
|
||||||
|
private final SEBClientConfigDAO sebClientConfigDAO;
|
||||||
|
private final Executor executor;
|
||||||
|
|
||||||
|
protected ExamAPIDiscoveryLightController(
|
||||||
|
final SEBClientConnectionService sebClientConnectionService,
|
||||||
|
final SEBClientConfigDAO sebClientConfigDAO,
|
||||||
|
@Qualifier(AsyncServiceSpringConfig.EXAM_API_EXECUTOR_BEAN_NAME) final Executor executor) {
|
||||||
|
|
||||||
|
this.sebClientConnectionService = sebClientConnectionService;
|
||||||
|
this.sebClientConfigDAO = sebClientConfigDAO;
|
||||||
|
this.executor = executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
//this.examAPI_V1_Endpoint + API.EXAM_API_CONFIGURATION_LIGHT_ENDPOINT
|
||||||
|
//http://localhost:8080/exam-api/discovery/light-config
|
||||||
|
@RequestMapping(
|
||||||
|
path = API.EXAM_API_CONFIGURATION_LIGHT_ENDPOINT,
|
||||||
|
method = RequestMethod.GET,
|
||||||
|
produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||||
|
public CompletableFuture<Void> getLightConfig(
|
||||||
|
final HttpServletRequest request,
|
||||||
|
final HttpServletResponse response){
|
||||||
|
|
||||||
|
//temp solution: get first active seb client config we can get -->
|
||||||
|
//in a light setup there should be only one setup so this step is not necessary and we can just use the first and only item in the db
|
||||||
|
String modelId = getSebClientConfigId();
|
||||||
|
|
||||||
|
return CompletableFuture.runAsync(
|
||||||
|
() -> {
|
||||||
|
try {
|
||||||
|
this.sebClientConnectionService.streamLightExamConfig(modelId, response);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
this.executor
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getSebClientConfigId() {
|
||||||
|
return this.sebClientConfigDAO
|
||||||
|
.allMatching(
|
||||||
|
new FilterMap().putIfAbsent(
|
||||||
|
"active",
|
||||||
|
String.valueOf(true)
|
||||||
|
),
|
||||||
|
Utils.truePredicate()
|
||||||
|
)
|
||||||
|
.getOrThrow()
|
||||||
|
.stream()
|
||||||
|
.collect(Collectors.toList())
|
||||||
|
.get(0)
|
||||||
|
.getModelId();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue