SEBSERV-163 finished administration back and front-end

This commit is contained in:
anhefti 2022-09-05 14:38:13 +02:00
parent 3670fee6c3
commit cea166f065
13 changed files with 47 additions and 34 deletions

View file

@ -63,7 +63,9 @@ public class APIMessage implements Serializable {
EXAM_IMPORT_ERROR_AUTO_SETUP("1600", HttpStatus.PARTIAL_CONTENT, EXAM_IMPORT_ERROR_AUTO_SETUP("1600", HttpStatus.PARTIAL_CONTENT,
"Exam successfully imported but some additional initialization failed"), "Exam successfully imported but some additional initialization failed"),
EXAM_IMPORT_ERROR_AUTO_INDICATOR("1601", HttpStatus.PARTIAL_CONTENT, EXAM_IMPORT_ERROR_AUTO_INDICATOR("1601", HttpStatus.PARTIAL_CONTENT,
"Failed to automatically create pre-defined indicators for the exam"), "Failed to automatically create pre-defined indicator(s) for the exam"),
EXAM_IMPORT_ERROR_AUTO_CLIENT_GROUPS("1604", HttpStatus.PARTIAL_CONTENT,
"Failed to automatically create pre-defined client group(s) for the exam"),
EXAM_IMPORT_ERROR_AUTO_ATTRIBUTES("1602", HttpStatus.PARTIAL_CONTENT, EXAM_IMPORT_ERROR_AUTO_ATTRIBUTES("1602", HttpStatus.PARTIAL_CONTENT,
"Failed to automatically create pre-defined attributes for the exam"), "Failed to automatically create pre-defined attributes for the exam"),
EXAM_IMPORT_ERROR_AUTO_RESTRICTION("1603", HttpStatus.PARTIAL_CONTENT, EXAM_IMPORT_ERROR_AUTO_RESTRICTION("1603", HttpStatus.PARTIAL_CONTENT,

View file

@ -116,8 +116,6 @@ public class WebserviceInit implements ApplicationListener<ApplicationReadyEvent
if (this.webserviceInfo.isDistributed()) { if (this.webserviceInfo.isDistributed()) {
SEBServerInit.INIT_LOGGER.info("----> "); SEBServerInit.INIT_LOGGER.info("----> ");
SEBServerInit.INIT_LOGGER.info("----> Distributed Setup: {}", this.webserviceInfo.getWebserviceUUID()); SEBServerInit.INIT_LOGGER.info("----> Distributed Setup: {}", this.webserviceInfo.getWebserviceUUID());
SEBServerInit.INIT_LOGGER.info("----> Ping update time: {}",
this.environment.getProperty("sebserver.webservice.distributed.pingUpdate"));
SEBServerInit.INIT_LOGGER.info("----> Connection update time: {}", SEBServerInit.INIT_LOGGER.info("----> Connection update time: {}",
this.environment.getProperty("sebserver.webservice.distributed.connectionUpdate", "2000")); this.environment.getProperty("sebserver.webservice.distributed.connectionUpdate", "2000"));
} }

View file

@ -15,8 +15,6 @@ import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.springframework.transaction.annotation.Transactional;
import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency; import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
@ -52,7 +50,6 @@ public interface BulkActionSupportDAO<T extends Entity> {
* *
* @param bulkAction the BulkAction containing the source entity and all dependencies * @param bulkAction the BulkAction containing the source entity and all dependencies
* @return a Collection of EntityKey results of each Entity that has been processed. */ * @return a Collection of EntityKey results of each Entity that has been processed. */
@Transactional
default Collection<Result<EntityKey>> processBulkAction(final BulkAction bulkAction) { default Collection<Result<EntityKey>> processBulkAction(final BulkAction bulkAction) {
final Set<EntityKey> all = bulkAction.extractKeys(entityType()); final Set<EntityKey> all = bulkAction.extractKeys(entityType());

View file

@ -96,7 +96,6 @@ public class BulkActionServiceImpl implements BulkActionService {
} }
@Override @Override
public Result<BulkAction> doBulkAction(final BulkAction action) { public Result<BulkAction> doBulkAction(final BulkAction action) {
return Result.tryCatch(() -> { return Result.tryCatch(() -> {

View file

@ -322,7 +322,7 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
activityType.name(), activityType.name(),
entityType.name(), entityType.name(),
entityId, entityId,
message)); Utils.truncateText(message, 4000)));
} }
@Override @Override

View file

@ -384,7 +384,7 @@ public class ExamTemplateServiceImpl implements ExamTemplateService {
} }
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Init default indicator for exam: {}", exam.externalId); log.debug("Initialized default indicator for exam: {}", exam.externalId);
} }
final Collection<Indicator.Threshold> thresholds = this.jsonMapper.readValue( final Collection<Indicator.Threshold> thresholds = this.jsonMapper.readValue(

View file

@ -115,7 +115,10 @@ public class MockCourseAccessAPI implements CourseAccessAPI {
@Override @Override
public LmsSetupTestResult testCourseAccessAPI() { public LmsSetupTestResult testCourseAccessAPI() {
log.info("Test Lms Binding for Mockup and LmsSetup: {}", this.apiTemplateDataSupplier.getLmsSetup());
if (log.isDebugEnabled()) {
log.debug("Test Lms Binding for Mockup and LmsSetup: {}", this.apiTemplateDataSupplier.getLmsSetup());
}
final List<APIMessage> missingAttrs = checkAttributes(); final List<APIMessage> missingAttrs = checkAttributes();

View file

@ -139,16 +139,21 @@ public class ExamSessionCacheService {
key = "#connectionToken", key = "#connectionToken",
unless = "#result == null") unless = "#result == null")
public ClientConnectionDataInternal getClientConnection(final String connectionToken) { public ClientConnectionDataInternal getClientConnection(final String connectionToken) {
try {
if (log.isTraceEnabled()) {
log.trace("Verify ClientConnection for running exam for caching by connectionToken: {}",
connectionToken);
}
if (log.isTraceEnabled()) { final ClientConnection clientConnection = getClientConnectionByToken(connectionToken);
log.trace("Verify ClientConnection for running exam for caching by connectionToken: {}", connectionToken); if (clientConnection == null) {
} return null;
} else {
final ClientConnection clientConnection = getClientConnectionByToken(connectionToken); return this.internalClientConnectionDataFactory.createClientConnectionData(clientConnection);
if (clientConnection == null) { }
} catch (final Exception e) {
log.error("Failed to get client connection: ", e);
return null; return null;
} else {
return this.internalClientConnectionDataFactory.createClientConnectionData(clientConnection);
} }
} }

View file

@ -38,8 +38,8 @@ import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus; import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; 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.ClientConnection.ConnectionStatus;
import ch.ethz.seb.sebserver.gbl.monitoring.MonitoringSEBConnectionData;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
import ch.ethz.seb.sebserver.gbl.monitoring.MonitoringSEBConnectionData;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO;
@ -408,20 +408,22 @@ public class ExamSessionServiceImpl implements ExamSessionService {
updateClientConnections(examId); updateClientConnections(examId);
final List<ClientConnectionData> filteredConnections = this.clientConnectionDAO synchronized (this.examSessionCacheService) {
.getConnectionTokens(examId) final List<ClientConnectionData> filteredConnections = this.clientConnectionDAO
.getOrThrow() .getConnectionTokens(examId)
.stream() .getOrThrow()
.map(token -> getConnectionData(token).getOr(null)) .stream()
.filter(Objects::nonNull) .map(token -> this.examSessionCacheService.getClientConnection(token))
.map(c -> { .filter(Objects::nonNull)
statusMapping[c.clientConnection.status.code]++; .map(c -> {
return c; statusMapping[c.clientConnection.status.code]++;
}) return c;
.filter(filter) })
.collect(Collectors.toList()); .filter(filter)
.collect(Collectors.toList());
return new MonitoringSEBConnectionData(examId, filteredConnections, statusMapping); return new MonitoringSEBConnectionData(examId, filteredConnections, statusMapping);
}
}); });
} }

View file

@ -109,6 +109,8 @@ public class DistributedIndicatorValueService implements DisposableBean {
SEBServerInit.INIT_LOGGER.info("------> with distributedUpdateInterval: {}", SEBServerInit.INIT_LOGGER.info("------> with distributedUpdateInterval: {}",
this.distributedUpdateInterval); this.distributedUpdateInterval);
SEBServerInit.INIT_LOGGER.info("------> with update tolerance: {}",
this.updateTolerance);
SEBServerInit.INIT_LOGGER.info("------> with taskScheduler: {}", taskScheduler); SEBServerInit.INIT_LOGGER.info("------> with taskScheduler: {}", taskScheduler);
try { try {

View file

@ -393,6 +393,11 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
errors.add(ErrorMessage.EXAM_IMPORT_ERROR_AUTO_INDICATOR.of(error)); errors.add(ErrorMessage.EXAM_IMPORT_ERROR_AUTO_INDICATOR.of(error));
return entity; return entity;
}) })
.flatMap(this.examTemplateService::addDefinedClientGroups)
.onErrorDo(error -> {
errors.add(ErrorMessage.EXAM_IMPORT_ERROR_AUTO_CLIENT_GROUPS.of(error));
return entity;
})
.flatMap(this.examTemplateService::initAdditionalAttributes) .flatMap(this.examTemplateService::initAdditionalAttributes)
.onErrorDo(error -> { .onErrorDo(error -> {
errors.add(ErrorMessage.EXAM_IMPORT_ERROR_AUTO_ATTRIBUTES.of(error)); errors.add(ErrorMessage.EXAM_IMPORT_ERROR_AUTO_ATTRIBUTES.of(error));

View file

@ -675,8 +675,8 @@ sebserver.exam.indicator.type.description.WLAN_STATUS=This indicator shows the p
sebserver.exam.clientgroup.type.IP_V4_RANGE=IP v4 Range sebserver.exam.clientgroup.type.IP_V4_RANGE=IP v4 Range
sebserver.exam.clientgroup.type.CLIENT_OS=SEB Client OS sebserver.exam.clientgroup.type.CLIENT_OS=SEB Client OS
sebserver.exam.clientgroup.type.description.NONE=No Client Group type is selected.<br/>Please select one. sebserver.exam.clientgroup.type.description.NONE=No Client Group type is selected.<br/>Please select one.
sebserver.exam.clientgroup.type.description.IP_V4_RANGE=IP v4 Range TODO sebserver.exam.clientgroup.type.description.IP_V4_RANGE=With IP v4 range groups you can group the SEB client connections within a IP ranges.<br/>Every SEB client that is connected with a given client IP address that is within the<br/>defined range (including start and end address) belongs to this group.<br/>This is mostly useful if you have dedicated managed devices where you know<br/>the IP ranges for e.g. your computer rooms.
sebserver.exam.clientgroup.type.description.CLIENT_OS=SEB Client OS TODO sebserver.exam.clientgroup.type.description.CLIENT_OS=With SEB Client groups you can group the SEB client connections within the<br/>operating system they are running on.<br/>For this grouping type there is a defined SEB OS type for each<br/>supported OS; Windows, MacOS and iOS.<br/>This is mostly useful if you want to monitor and manage<br/>the SEB clients by different operating system types to give respective support.
sebserver.exam.indicator.info.pleaseSelect=At first please select an indicator from the list sebserver.exam.indicator.info.pleaseSelect=At first please select an indicator from the list

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 B

After

Width:  |  Height:  |  Size: 177 B