SEBSERV-62 controller implementation and prepare for testing
This commit is contained in:
parent
44688429bb
commit
b314ca651f
42 changed files with 1681 additions and 183 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -60,3 +60,4 @@ pom.xml.tag
|
|||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
/log-byDay_IS_UNDEFINED.txt
|
||||
/log/
|
||||
|
|
|
@ -104,7 +104,9 @@ public final class API {
|
|||
|
||||
public static final String EXAM_API_PARAM_EXAM_ID = "examId";
|
||||
|
||||
public static final String EXAM_API_SEB_CONNECTION_TOKEN = "seb-connection-token";
|
||||
public static final String EXAM_API_SEB_CONNECTION_TOKEN = "SEBConnectionToken";
|
||||
|
||||
public static final String EXAM_API_USER_SESSION_ID = "seb_user_session_id";
|
||||
|
||||
public static final String EXAM_API_HANDSHAKE_ENDPOINT = "/handshake";
|
||||
|
||||
|
@ -112,6 +114,10 @@ public final class API {
|
|||
|
||||
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_NUMBER = "ping-number";
|
||||
|
||||
public static final String EXAM_API_EVENT_ENDPOINT = "/seblog";
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ package ch.ethz.seb.sebserver.gbl.model.session;
|
|||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||
|
||||
public final class RunningExam {
|
||||
|
||||
@JsonProperty("examId")
|
||||
|
@ -31,6 +33,12 @@ public final class RunningExam {
|
|||
this.url = url;
|
||||
}
|
||||
|
||||
public RunningExam(final Exam exam) {
|
||||
this.examId = exam.getModelId();
|
||||
this.name = exam.name;
|
||||
this.url = exam.startURL;
|
||||
}
|
||||
|
||||
public String getExamId() {
|
||||
return this.examId;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ public final class Utils {
|
|||
return Collectors.collectingAndThen(
|
||||
Collectors.toList(),
|
||||
list -> {
|
||||
if (list == null) {
|
||||
if (list == null || list.size() == 0) {
|
||||
throw new IllegalStateException(
|
||||
"Expected one elements in the given list but is empty");
|
||||
}
|
||||
|
@ -335,4 +335,8 @@ public final class Utils {
|
|||
return string;
|
||||
}
|
||||
|
||||
public static String toSQLWildcard(final String text) {
|
||||
return (text == null) ? null : Constants.PERCENTAGE + text + Constants.PERCENTAGE;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -55,11 +55,11 @@ public interface ClientCredentialService {
|
|||
return encryptClientCredentials(clientIdPlaintext, secretPlaintext, null);
|
||||
}
|
||||
|
||||
/** Use this to get a decrypted plain text clientId form given ClientCredentials
|
||||
*
|
||||
* @param credentials ClientCredentials containing the clientId to decrypt
|
||||
* @return decrypted plain text clientId */
|
||||
CharSequence getPlainClientId(ClientCredentials credentials);
|
||||
// /** Use this to get a decrypted plain text clientId form given ClientCredentials
|
||||
// *
|
||||
// * @param credentials ClientCredentials containing the clientId to decrypt
|
||||
// * @return decrypted plain text clientId */
|
||||
// CharSequence getPlainClientId(ClientCredentials credentials);
|
||||
|
||||
/** Use this to get a decrypted plain text secret form given ClientCredentials
|
||||
*
|
||||
|
|
|
@ -64,9 +64,7 @@ public class ClientCredentialServiceImpl implements ClientCredentialService {
|
|||
.getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY);
|
||||
|
||||
return new ClientCredentials(
|
||||
(clientIdPlaintext != null)
|
||||
? encrypt(clientIdPlaintext, secret).toString()
|
||||
: null,
|
||||
clientIdPlaintext,
|
||||
(secretPlaintext != null)
|
||||
? encrypt(secretPlaintext, secret).toString()
|
||||
: null,
|
||||
|
@ -75,17 +73,10 @@ public class ClientCredentialServiceImpl implements ClientCredentialService {
|
|||
: null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPlainClientId(final ClientCredentials credentials) {
|
||||
if (credentials == null || !credentials.hasClientId()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final CharSequence secret = this.environment
|
||||
.getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY);
|
||||
|
||||
return this.decrypt(credentials.clientId, secret);
|
||||
}
|
||||
// @Override
|
||||
// public CharSequence getPlainClientId(final ClientCredentials credentials) {
|
||||
// return credentials.clientId;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public CharSequence getPlainClientSecret(final ClientCredentials credentials) {
|
||||
|
|
|
@ -15,4 +15,6 @@ public interface ClientConnectionDAO extends EntityDAO<ClientConnection, ClientC
|
|||
|
||||
Result<ClientConnection> byConnectionToken(Long institutionId, String connectionToken);
|
||||
|
||||
Result<ClientConnection> byConnectionToken(String connectionToken);
|
||||
|
||||
}
|
||||
|
|
|
@ -9,10 +9,15 @@
|
|||
package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSupportDAO;
|
||||
|
||||
public interface ExamConfigurationMapDAO extends
|
||||
EntityDAO<ExamConfigurationMap, ExamConfigurationMap>,
|
||||
BulkActionSupportDAO<ExamConfigurationMap> {
|
||||
|
||||
public Result<Long> getDefaultConfigurationForExam(Long examId);
|
||||
|
||||
public Result<Long> getUserConfigurationIdForExam(final Long examId, final String userId);
|
||||
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import org.joda.time.DateTimeZone;
|
|||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||
|
@ -179,11 +178,7 @@ public class FilterMap extends POSTMapper {
|
|||
}
|
||||
|
||||
public String getSQLWildcard(final String name) {
|
||||
return toSQLWildcard(this.params.getFirst(name));
|
||||
}
|
||||
|
||||
public static String toSQLWildcard(final String text) {
|
||||
return (text == null) ? null : Constants.PERCENTAGE + text + Constants.PERCENTAGE;
|
||||
return Utils.toSQLWildcard(this.params.getFirst(name));
|
||||
}
|
||||
|
||||
public Long getClientConnectionExamId() {
|
||||
|
|
|
@ -18,6 +18,12 @@ public interface SebClientConfigDAO extends
|
|||
ActivatableEntityDAO<SebClientConfig, SebClientConfig>,
|
||||
BulkActionSupportDAO<SebClientConfig> {
|
||||
|
||||
/** Get a SebClientConfig by specified client identifier
|
||||
*
|
||||
* @param clientId the client identifier
|
||||
* @return Result refer to the SebClientConfig for client or refer to an error if happened */
|
||||
Result<SebClientConfig> byClientId(String clientId);
|
||||
|
||||
/** Get the configured ClientCredentials for a given SebClientConfig.
|
||||
* The ClientCredentials are still encoded as they are on DB storage
|
||||
*
|
||||
|
|
|
@ -120,7 +120,7 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
|
|||
data.institutionId,
|
||||
data.examId,
|
||||
ConnectionStatus.CONNECTION_REQUESTED.name(),
|
||||
null,
|
||||
data.connectionToken,
|
||||
null,
|
||||
data.clientAddress,
|
||||
data.virtualClientAddress);
|
||||
|
@ -214,6 +214,31 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
|
|||
.flatMap(ClientConnectionDAOImpl::toDomainModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<ClientConnection> byConnectionToken(final String connectionToken) {
|
||||
return Result.tryCatch(() -> {
|
||||
final List<ClientConnectionRecord> list = this.clientConnectionRecordMapper
|
||||
.selectByExample()
|
||||
.where(
|
||||
ClientConnectionRecordDynamicSqlSupport.connectionToken,
|
||||
SqlBuilder.isEqualTo(connectionToken))
|
||||
|
||||
.build()
|
||||
.execute();
|
||||
|
||||
if (list.isEmpty()) {
|
||||
throw new ResourceNotFoundException(EntityType.CLIENT_CONNECTION, "connectionToken");
|
||||
}
|
||||
|
||||
if (list.size() > 1) {
|
||||
throw new IllegalStateException("Only one ClientConnection expected but there are: " + list.size());
|
||||
}
|
||||
|
||||
return list.get(0);
|
||||
})
|
||||
.flatMap(ClientConnectionDAOImpl::toDomainModel);
|
||||
}
|
||||
|
||||
private Result<ClientConnectionRecord> recordById(final Long id) {
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
|
|||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
|
||||
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.webservice.datalayer.batis.mapper.ConfigurationNodeRecordMapper;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamConfigurationMapRecordDynamicSqlSupport;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamConfigurationMapRecordMapper;
|
||||
|
@ -125,6 +126,39 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
|
|||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Result<Long> getDefaultConfigurationForExam(final Long examId) {
|
||||
return Result.tryCatch(() -> this.examConfigurationMapRecordMapper
|
||||
.selectIdsByExample()
|
||||
.where(
|
||||
ExamConfigurationMapRecordDynamicSqlSupport.examId,
|
||||
SqlBuilder.isEqualTo(examId))
|
||||
.and(
|
||||
ExamConfigurationMapRecordDynamicSqlSupport.userNames,
|
||||
SqlBuilder.isNull())
|
||||
.build()
|
||||
.execute()
|
||||
.stream()
|
||||
.collect(Utils.toSingleton()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Long> getUserConfigurationIdForExam(final Long examId, final String userId) {
|
||||
return Result.tryCatch(() -> this.examConfigurationMapRecordMapper
|
||||
.selectIdsByExample()
|
||||
.where(
|
||||
ExamConfigurationMapRecordDynamicSqlSupport.examId,
|
||||
SqlBuilder.isEqualTo(examId))
|
||||
.and(
|
||||
ExamConfigurationMapRecordDynamicSqlSupport.userNames,
|
||||
SqlBuilder.isLike(Utils.toSQLWildcard(userId)))
|
||||
.build()
|
||||
.execute()
|
||||
.stream()
|
||||
.collect(Utils.toSingleton()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Result<ExamConfigurationMap> createNew(final ExamConfigurationMap data) {
|
||||
|
|
|
@ -318,15 +318,13 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
|
|||
record.getLmsClientsecret(),
|
||||
record.getLmsRestApiToken());
|
||||
|
||||
final CharSequence plainClientId = this.clientCredentialService.getPlainClientId(clientCredentials);
|
||||
final CharSequence plainAccessToken = this.clientCredentialService.getPlainAccessToken(clientCredentials);
|
||||
|
||||
return Result.tryCatch(() -> new LmsSetup(
|
||||
record.getId(),
|
||||
record.getInstitutionId(),
|
||||
record.getName(),
|
||||
LmsType.valueOf(record.getLmsType()),
|
||||
Utils.toString(plainClientId),
|
||||
Utils.toString(clientCredentials.clientId),
|
||||
null,
|
||||
record.getLmsUrl(),
|
||||
Utils.toString(plainAccessToken),
|
||||
|
|
|
@ -35,6 +35,7 @@ import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
|||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.SebClientConfig;
|
||||
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.webservice.datalayer.batis.mapper.SebClientConfigRecordDynamicSqlSupport;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.SebClientConfigRecordMapper;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.SebClientConfigRecord;
|
||||
|
@ -131,6 +132,24 @@ public class SebClientConfigDAOImpl implements SebClientConfigDAO {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<SebClientConfig> byClientId(final String clientId) {
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
return this.sebClientConfigRecordMapper
|
||||
.selectByExample()
|
||||
.where(
|
||||
SebClientConfigRecordDynamicSqlSupport.clientName,
|
||||
isEqualTo(clientId))
|
||||
.build()
|
||||
.execute()
|
||||
.stream()
|
||||
.map(SebClientConfigDAOImpl::toDomainModel)
|
||||
.flatMap(DAOLoggingSupport::logAndSkipOnError)
|
||||
.collect(Utils.toSingleton());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public boolean isActive(final String modelId) {
|
||||
|
|
|
@ -58,7 +58,7 @@ public class LmsAPIServiceImpl implements LmsAPIService {
|
|||
final LmsSetupDAO lmsSetupDAO,
|
||||
final ClientCredentialService clientCredentialService,
|
||||
final ClientHttpRequestFactory clientHttpRequestFactory,
|
||||
@Value("${sebserver.lms.openedix.api.token.request.paths}") final String alternativeTokenRequestPaths) {
|
||||
@Value("${sebserver.webservice.lms.openedx.api.token.request.paths}") final String alternativeTokenRequestPaths) {
|
||||
|
||||
this.asyncService = asyncService;
|
||||
this.lmsSetupDAO = lmsSetupDAO;
|
||||
|
|
|
@ -130,7 +130,7 @@ final class MockupLmsAPITemplate implements LmsAPITemplate {
|
|||
private boolean authenticate() {
|
||||
try {
|
||||
|
||||
final CharSequence plainClientId = this.clientCredentialService.getPlainClientId(this.credentials);
|
||||
final CharSequence plainClientId = this.credentials.clientId;
|
||||
if (plainClientId == null || plainClientId.length() <= 0) {
|
||||
throw new IllegalAccessException("Wrong client credential");
|
||||
}
|
||||
|
|
|
@ -202,7 +202,7 @@ final class OpenEdxLmsAPITemplate implements LmsAPITemplate {
|
|||
final ClientCredentials credentials,
|
||||
final String accessTokenRequestPath) {
|
||||
|
||||
final CharSequence plainClientId = this.clientCredentialService.getPlainClientId(credentials);
|
||||
final CharSequence plainClientId = credentials.clientId;
|
||||
final CharSequence plainClientSecret = this.clientCredentialService.getPlainClientSecret(credentials);
|
||||
|
||||
final ClientCredentialsResourceDetails details = new ClientCredentialsResourceDetails();
|
||||
|
|
|
@ -73,6 +73,6 @@ public interface SebClientConfigService {
|
|||
*
|
||||
* @param clientId the clientId/clientName
|
||||
* @return encoded clientSecret for that SebClientConfiguration with clientId or null of not existing */
|
||||
Result<String> getEncodedClientSecret(String clientId);
|
||||
Result<CharSequence> getEncodedClientSecret(String clientId);
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import java.io.OutputStream;
|
|||
import ch.ethz.seb.sebserver.gbl.api.APIMessage.FieldValidationException;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
|
||||
/** The base interface and service for all SEB Exam Configuration related functionality. */
|
||||
public interface SebExamConfigService {
|
||||
|
@ -31,6 +32,10 @@ public interface SebExamConfigService {
|
|||
* @throws FieldValidationException on validation exception */
|
||||
void validate(ConfigurationTableValues tableValue) throws FieldValidationException;
|
||||
|
||||
Result<Long> getDefaultConfigurationIdForExam(Long examId);
|
||||
|
||||
Result<Long> getUserConfigurationIdForExam(Long examId, String userId);
|
||||
|
||||
/** Used to export a specified SEB Exam Configuration as plain XML
|
||||
* This exports the values of the follow-up configuration defined by a given
|
||||
* ConfigurationNode (configurationNodeId)
|
||||
|
|
|
@ -17,8 +17,6 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -28,14 +26,10 @@ import org.springframework.context.annotation.Lazy;
|
|||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import ch.ethz.seb.sebserver.WebSecurityConfig;
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.SebClientConfig;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
|
@ -135,46 +129,14 @@ public class SebClientConfigServiceImpl implements SebClientConfigService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Result<String> getEncodedClientSecret(final String clientId) {
|
||||
return Result.tryCatch(() -> {
|
||||
final Collection<SebClientConfig> clientConfigs = this.sebClientConfigDAO.all(extractInstitution(), true)
|
||||
.getOrThrow();
|
||||
|
||||
final ClientCredentials clientCredentials = findClientCredentialsFor(clientId, clientConfigs);
|
||||
return this.clientPasswordEncoder.encode(
|
||||
this.clientCredentialService.getPlainClientSecret(clientCredentials));
|
||||
|
||||
});
|
||||
public Result<CharSequence> getEncodedClientSecret(final String clientId) {
|
||||
return this.sebClientConfigDAO.byClientId(clientId)
|
||||
.flatMap(this::getEncodedSecret);
|
||||
}
|
||||
|
||||
public ClientCredentials findClientCredentialsFor(final String clientId,
|
||||
final Collection<SebClientConfig> clientConfigs) {
|
||||
for (final SebClientConfig config : clientConfigs) {
|
||||
try {
|
||||
final ClientCredentials clientCredentials =
|
||||
this.sebClientConfigDAO.getSebClientCredentials(config.getModelId())
|
||||
.getOrThrow();
|
||||
if (clientId.equals(this.clientCredentialService.getPlainClientId(clientCredentials))) {
|
||||
return clientCredentials;
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
log.error("Unexpected error while trying to fetch client credentials: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Long extractInstitution() {
|
||||
try {
|
||||
final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
|
||||
final HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
|
||||
return Long.parseLong(request.getParameter(API.PARAM_INSTITUTION_ID));
|
||||
} catch (final Exception e) {
|
||||
log.error(
|
||||
"Failed to extract institution from current request. Search client Id over all active client configurations");
|
||||
return null;
|
||||
}
|
||||
private Result<CharSequence> getEncodedSecret(final SebClientConfig clientConfig) {
|
||||
return this.sebClientConfigDAO.getSebClientCredentials(clientConfig.getModelId())
|
||||
.map(cc -> this.clientPasswordEncoder.encode(this.clientCredentialService.getPlainClientSecret(cc)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -193,8 +155,7 @@ public class SebClientConfigServiceImpl implements SebClientConfigService {
|
|||
.getConfigPasswortCipher(config.getModelId())
|
||||
.getOrThrow();
|
||||
|
||||
final CharSequence plainClientId = this.clientCredentialService
|
||||
.getPlainClientId(sebClientCredentials);
|
||||
final CharSequence plainClientId = sebClientCredentials.clientId;
|
||||
final CharSequence plainClientSecret = this.clientCredentialService
|
||||
.getPlainClientSecret(sebClientCredentials);
|
||||
|
||||
|
|
|
@ -25,7 +25,9 @@ import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
|
|||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationAttributeDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamConfigurationMapDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ConfigurationValueValidator;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebExamConfigService;
|
||||
|
||||
|
@ -38,15 +40,18 @@ public class SebExamConfigServiceImpl implements SebExamConfigService {
|
|||
|
||||
private final ExamConfigIO examConfigIO;
|
||||
private final ConfigurationAttributeDAO configurationAttributeDAO;
|
||||
private final ExamConfigurationMapDAO examConfigurationMapDAO;
|
||||
private final Collection<ConfigurationValueValidator> validators;
|
||||
|
||||
protected SebExamConfigServiceImpl(
|
||||
final ExamConfigIO examConfigIO,
|
||||
final ConfigurationAttributeDAO configurationAttributeDAO,
|
||||
final ExamConfigurationMapDAO examConfigurationMapDAO,
|
||||
final Collection<ConfigurationValueValidator> validators) {
|
||||
|
||||
this.examConfigIO = examConfigIO;
|
||||
this.configurationAttributeDAO = configurationAttributeDAO;
|
||||
this.examConfigurationMapDAO = examConfigurationMapDAO;
|
||||
this.validators = validators;
|
||||
|
||||
}
|
||||
|
@ -122,6 +127,16 @@ public class SebExamConfigServiceImpl implements SebExamConfigService {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Long> getDefaultConfigurationIdForExam(final Long examId) {
|
||||
return this.examConfigurationMapDAO.getDefaultConfigurationForExam(examId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Long> getUserConfigurationIdForExam(final Long examId, final String userId) {
|
||||
return this.examConfigurationMapDAO.getUserConfigurationIdForExam(examId, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportForExam(final OutputStream out, final Long configExamMappingId) {
|
||||
// TODO Auto-generated method stub
|
||||
|
|
|
@ -12,6 +12,8 @@ import java.util.function.Consumer;
|
|||
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
||||
|
||||
/** A exam session SEB client event handling strategy implements a certain strategy to
|
||||
* store ClientEvent that are coming in within the specified endpoint in height frequency. */
|
||||
public interface EventHandlingStrategy extends Consumer<ClientEvent> {
|
||||
|
||||
String EVENT_CONSUMER_STRATEGY_CONFIG_PROPERTY_KEY = "sebserver.webservice.api.exam.event-handling-strategy";
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.webservice.servicelayer.session;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collection;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||
|
@ -38,4 +39,6 @@ public interface ExamSessionService {
|
|||
* happened. */
|
||||
Result<Collection<Exam>> getRunningExamsForInstitution(Long institutionId);
|
||||
|
||||
void streamDefaultExamConfig(Long institutionId, String connectionToken, OutputStream out);
|
||||
|
||||
}
|
||||
|
|
|
@ -12,24 +12,95 @@ import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
|
|||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
|
||||
/** Service interface defining functionality to handle SEB client connections on running exams. */
|
||||
public interface SebClientConnectionService {
|
||||
|
||||
/** If a SEB client connects to the SEB Server the first time for a exam session,
|
||||
* this is used to create a ClientConnection for this connection attempt.
|
||||
* So this starts the SEB Client - SEB Server handshake.
|
||||
* <p>
|
||||
* The examId is not mandatory here an can still be null if at this time
|
||||
* no exam was selected.
|
||||
* <p>
|
||||
* A connection-token to identify the connection is generated and stored within the
|
||||
* returned ClientConnection.
|
||||
*
|
||||
* @param institutionId The institution identifier
|
||||
* @param clientAddress The clients remote IP address
|
||||
* @param examId the exam identifier (can be null)
|
||||
* @return A Result refer to the newly created ClientConnection in state: CONNECTION_REQUESTED, or refer to an error
|
||||
* if happened */
|
||||
Result<ClientConnection> createClientConnection(
|
||||
Long institutionId,
|
||||
String clientAddress,
|
||||
Long examId);
|
||||
|
||||
Result<ClientConnection> establishClientConnection(
|
||||
final Long institutionId,
|
||||
/** This updates an already existing ClientConnection with the given connectionToken.
|
||||
* <p>
|
||||
* If a clientAddress is given and it differs from the existing clientAddress and the there is
|
||||
* an exam mapping to an exam of type VDI, the given clientAddress is used to update the virtualClientAddress
|
||||
* of the ClientConnection.
|
||||
* <p>
|
||||
* If an examId is given this is used to update the ClientConnection
|
||||
* <p>
|
||||
* If a userSessionId is given this is used to update the ClientConnection
|
||||
*
|
||||
* @param connectionToken The connection-token that was given on ClientConnection creation and that identifies the
|
||||
* connection
|
||||
* @param institutionId The institution identifier
|
||||
* @param clientAddress The clients remote IP address
|
||||
* @param examId The exam identifier
|
||||
* @param userSessionId The user session identifier of the users http-session with the LMS
|
||||
* @return A Result refer to the updated ClientConnection instance, or refer to an error if happened */
|
||||
Result<ClientConnection> updateClientConnection(
|
||||
String connectionToken,
|
||||
Long institutionId,
|
||||
String clientAddress,
|
||||
Long examId,
|
||||
final String clientAddress,
|
||||
String userSessionId);
|
||||
|
||||
Result<ClientConnection> closeConnection(String connectionToken);
|
||||
/** This is used to establish a already created ClientConnection and set it to sate: ESTABLISHED
|
||||
* The connectionToken identifies the ClientConnection and the given clientAddress must match with
|
||||
* the clientAddress of the already created ClientConnection in state CONNECTION_REQUESTED.
|
||||
* <p>
|
||||
* This may not be the case for VDI exams. In case of VDI exams the different clientAddress is stored
|
||||
* in the virtualClientAddress field of the ClientConnection.
|
||||
* <p>
|
||||
* The examId may also be null here if the examId is already known within the existing ClientConnection.
|
||||
* If not, an error is thrown and send to the calling SEB Client.
|
||||
* <p>
|
||||
* If a userSessionId is provided within the establish request, this is also stored within the ClientConnection.
|
||||
*
|
||||
* @param connectionToken The connection-token that was given on ClientConnection creation and that identifies the
|
||||
* connection
|
||||
* @param institutionId The institution identifier
|
||||
* @param examId The exam identifier (may be null of already known)
|
||||
* @param clientAddress The clients remote IP address
|
||||
* @param userSessionId The user session identifier of the users http-session with the LMS
|
||||
* @return A Result refer to the established ClientConnection instance, or refer to an error if happened */
|
||||
Result<ClientConnection> establishClientConnection(
|
||||
String connectionToken,
|
||||
Long institutionId,
|
||||
Long examId,
|
||||
String clientAddress,
|
||||
String userSessionId);
|
||||
|
||||
void notifyPing(Long connectionId, long timestamp, int pingNumber);
|
||||
/** This is used to regular close an established ClientConnection from SEB Client side.
|
||||
* <p>
|
||||
* This will save the existing established ClientConnection in new CLOSED state and flush all caches.
|
||||
*
|
||||
* @param connectionToken The connection-token that was given on ClientConnection creation and that identifies the
|
||||
* connection
|
||||
* @param institutionId institution identifier
|
||||
* @param clientAddress The clients remote IP address
|
||||
* @return A Result refer to the closed ClientConnection instance, or refer to an error if happened */
|
||||
Result<ClientConnection> closeConnection(
|
||||
String connectionToken,
|
||||
Long institutionId,
|
||||
String clientAddress);
|
||||
|
||||
void notifyClientEvent(final ClientEvent event, Long connectionId);
|
||||
void notifyPing(String connectionToken, long timestamp, int pingNumber);
|
||||
|
||||
void notifyClientEvent(String connectionToken, final ClientEvent event);
|
||||
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ public class ClientIndicatorFactory {
|
|||
public ClientIndicatorFactory(
|
||||
final ApplicationContext applicationContext,
|
||||
final IndicatorDAO indicatorDAO,
|
||||
@Value("${sebserver.indicator.caching}") final boolean enableCaching) {
|
||||
@Value("${sebserver.webservice.api.exam.enable-indicator-cache:true}") final boolean enableCaching) {
|
||||
|
||||
this.applicationContext = applicationContext;
|
||||
this.indicatorDAO = indicatorDAO;
|
||||
|
@ -60,9 +60,15 @@ public class ClientIndicatorFactory {
|
|||
|
||||
for (final Indicator indicatorDef : examIndicators) {
|
||||
try {
|
||||
|
||||
final ClientIndicator indicator = this.applicationContext
|
||||
.getBean(indicatorDef.type.name(), ClientIndicator.class);
|
||||
indicator.init(indicatorDef, clientConnection.id, this.enableCaching);
|
||||
|
||||
indicator.init(
|
||||
indicatorDef,
|
||||
clientConnection.id,
|
||||
this.enableCaching);
|
||||
|
||||
result.add(indicator);
|
||||
} catch (final Exception e) {
|
||||
log.warn("No Indicator with type: {} found as registered bean. Ignore this one.", indicatorDef.type,
|
||||
|
|
|
@ -8,6 +8,13 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PipedInputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
|
||||
import org.apache.tomcat.util.http.fileupload.IOUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
|
@ -17,6 +24,7 @@ import org.springframework.stereotype.Service;
|
|||
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||
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.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO;
|
||||
|
@ -98,25 +106,34 @@ public class ExamSessionCacheService {
|
|||
|
||||
@Cacheable(
|
||||
cacheNames = CACHE_NAME_ACTIVE_CLIENT_CONNECTION,
|
||||
key = "#connectionId",
|
||||
key = "#connectionToken",
|
||||
unless = "#result == null")
|
||||
ClientConnectionDataInternal getActiveClientConnection(final Long connectionId) {
|
||||
ClientConnectionDataInternal getActiveClientConnection(final String connectionToken) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Verify ClientConnection for running exam for caching by id: ", connectionId);
|
||||
log.debug("Verify ClientConnection for running exam for caching by connectionToken: ", connectionToken);
|
||||
}
|
||||
|
||||
final Result<ClientConnection> byPK = this.clientConnectionDAO.byPK(connectionId);
|
||||
final Result<ClientConnection> byPK = this.clientConnectionDAO
|
||||
.byConnectionToken(connectionToken);
|
||||
|
||||
if (byPK.hasError()) {
|
||||
log.error("Failed to find/load ClientConnection with id {}", connectionId, byPK.getError());
|
||||
log.error("Failed to find/load ClientConnection with connectionToken {}", connectionToken, byPK.getError());
|
||||
return null;
|
||||
}
|
||||
|
||||
final ClientConnection clientConnection = byPK.get();
|
||||
|
||||
// verify connection is established
|
||||
if (clientConnection.status != ConnectionStatus.ESTABLISHED) {
|
||||
log.error("Illegal state: ClientConnection is not in expected state; ESTABLISHED. ClientConnection: ",
|
||||
clientConnection);
|
||||
return null;
|
||||
}
|
||||
|
||||
// verify exam is running
|
||||
if (getRunningExam(clientConnection.examId) == null) {
|
||||
log.error("Exam for ClientConnection with id { is not currently running}", connectionId);
|
||||
log.error("Exam for ClientConnection with id { is not currently running}", clientConnection.id);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -127,10 +144,10 @@ public class ExamSessionCacheService {
|
|||
|
||||
@CacheEvict(
|
||||
cacheNames = CACHE_NAME_ACTIVE_CLIENT_CONNECTION,
|
||||
key = "#connectionId")
|
||||
void evictClientConnection(final Long connectionId) {
|
||||
key = "#connectionToken")
|
||||
void evictClientConnection(final String connectionToken) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Eviction of ClientConnectionData from cache: {}", connectionId);
|
||||
log.debug("Eviction of ClientConnectionData from cache: {}", connectionToken);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,8 +156,27 @@ public class ExamSessionCacheService {
|
|||
key = "#examId",
|
||||
unless = "#result == null")
|
||||
InMemorySebConfig getDefaultSebConfigForExam(final Long examId) {
|
||||
// TODO
|
||||
return null;
|
||||
final Exam runningExam = this.getRunningExam(examId);
|
||||
final PipedOutputStream pipOut = new PipedOutputStream();
|
||||
try {
|
||||
final Long configId = this.sebExamConfigService
|
||||
.getDefaultConfigurationIdForExam(runningExam.id)
|
||||
.getOrThrow();
|
||||
|
||||
// TODO add header, zip and encrypt if needed
|
||||
|
||||
final BufferedInputStream in = new BufferedInputStream(new PipedInputStream(pipOut));
|
||||
this.sebExamConfigService.exportPlainXML(pipOut, runningExam.institutionId, configId);
|
||||
|
||||
final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
|
||||
IOUtils.copyLarge(in, byteOut);
|
||||
|
||||
return new InMemorySebConfig(configId, runningExam.id, byteOut.toByteArray());
|
||||
|
||||
} catch (final IOException e) {
|
||||
log.error("Unexpected error while getting default exam configuration for running exam; {}", runningExam, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@CacheEvict(
|
||||
|
|
|
@ -8,35 +8,46 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||
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.profile.WebServiceProfile;
|
||||
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.ExamDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SebClientConnectionService;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
@WebServiceProfile
|
||||
public class ExamSessionServiceImpl implements ExamSessionService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ExamSessionServiceImpl.class);
|
||||
|
||||
private final ClientConnectionDAO clientConnectionDAO;
|
||||
private final ExamSessionCacheService examSessionCacheService;
|
||||
private final ExamDAO examDAO;
|
||||
|
||||
protected ExamSessionServiceImpl(
|
||||
final ExamSessionCacheService examSessionCacheService,
|
||||
final ExamDAO examDAO,
|
||||
final SebClientConnectionService sebClientConnectionService) {
|
||||
final ClientConnectionDAO clientConnectionDAO) {
|
||||
|
||||
this.examSessionCacheService = examSessionCacheService;
|
||||
this.examDAO = examDAO;
|
||||
this.clientConnectionDAO = clientConnectionDAO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -47,13 +58,24 @@ public class ExamSessionServiceImpl implements ExamSessionService {
|
|||
|
||||
@Override
|
||||
public Result<Exam> getRunningExam(final Long examId) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Running exam request for exam {}", examId);
|
||||
}
|
||||
|
||||
final Exam exam = this.examSessionCacheService.getRunningExam(examId);
|
||||
if (this.examSessionCacheService.isRunning(exam)) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Exam {} is running and cached", examId);
|
||||
}
|
||||
|
||||
return Result.of(exam);
|
||||
} else {
|
||||
if (exam != null) {
|
||||
this.examSessionCacheService.evict(exam);
|
||||
}
|
||||
|
||||
log.warn("Exam {} is not currently running", examId);
|
||||
|
||||
return Result.ofError(new NoSuchElementException(
|
||||
"No currenlty running exam found for id: " + examId));
|
||||
}
|
||||
|
@ -68,4 +90,55 @@ public class ExamSessionServiceImpl implements ExamSessionService {
|
|||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void streamDefaultExamConfig(
|
||||
final Long institutionId,
|
||||
final String connectionToken,
|
||||
final OutputStream out) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("SEB exam configuration download request, connectionToken: {}", connectionToken);
|
||||
}
|
||||
|
||||
final ClientConnection connection = this.clientConnectionDAO
|
||||
.byConnectionToken(institutionId, connectionToken)
|
||||
.getOrThrow();
|
||||
|
||||
if (connection == null || connection.status != ConnectionStatus.ESTABLISHED) {
|
||||
log.warn("SEB exam configuration download request, no active ClientConnection found for token: {}",
|
||||
connectionToken);
|
||||
throw new AccessDeniedException("Illegal connection token. No active ClientConnection found for token");
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("SEB exam configuration download request: {}", connection);
|
||||
log.debug("Trying to get exam form InMemorySebConfig");
|
||||
}
|
||||
|
||||
final InMemorySebConfig sebConfigForExam = this.examSessionCacheService
|
||||
.getDefaultSebConfigForExam(connection.examId);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
if (sebConfigForExam == null) {
|
||||
log.debug("Failed to get and cache InMemorySebConfig for connection: {}", connection);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("SEB exam configuration download request, start writing SEB exam configuration");
|
||||
}
|
||||
|
||||
out.write(sebConfigForExam.getData());
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("SEB exam configuration download request, finished writing SEB exam configuration");
|
||||
}
|
||||
|
||||
} catch (final IOException e) {
|
||||
log.error("SEB exam configuration download request, failed to write SEB exam configuration: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,10 +13,15 @@ import java.util.UUID;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType;
|
||||
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.ClientEvent;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.EventHandlingStrategy;
|
||||
|
@ -24,6 +29,9 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService;
|
|||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SebClientConnectionService;
|
||||
import io.micrometer.core.instrument.util.StringUtils;
|
||||
|
||||
@Lazy
|
||||
@Service
|
||||
@WebServiceProfile
|
||||
public class SebClientConnectionServiceImpl implements SebClientConnectionService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SebClientConnectionServiceImpl.class);
|
||||
|
@ -65,15 +73,16 @@ public class SebClientConnectionServiceImpl implements SebClientConnectionServic
|
|||
return Result.tryCatch(() -> {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("SEB client connection attempt, create ClientConnection for instituion {} and exam: {}",
|
||||
log.debug("SEB client connection attempt, create ClientConnection for "
|
||||
+ "instituion {} "
|
||||
+ "exam: {} "
|
||||
+ "client address: {}",
|
||||
institutionId,
|
||||
examId);
|
||||
examId,
|
||||
clientAddress);
|
||||
}
|
||||
|
||||
// Integrity check: in case examId is provided is the specified exam running?
|
||||
if (examId != null && !this.examSessionService.isExamRunning(examId)) {
|
||||
examNotRunningException(examId);
|
||||
}
|
||||
checkExamRunning(examId);
|
||||
|
||||
// Create ClientConnection in status CONNECTION_REQUESTED for further processing
|
||||
final String connectionToken = createToken();
|
||||
|
@ -97,9 +106,69 @@ public class SebClientConnectionServiceImpl implements SebClientConnectionServic
|
|||
}
|
||||
|
||||
@Override
|
||||
public Result<ClientConnection> establishClientConnection(
|
||||
final Long institutionId,
|
||||
public Result<ClientConnection> updateClientConnection(
|
||||
final String connectionToken,
|
||||
final Long institutionId,
|
||||
final String clientAddress,
|
||||
final Long examId,
|
||||
final String userSessionId) {
|
||||
|
||||
return Result.tryCatch(() -> {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(
|
||||
"SEB client connection, update ClientConnection for "
|
||||
+ "connectionToken {} "
|
||||
+ "institutionId"
|
||||
+ "exam: {} "
|
||||
+ "client address: {} "
|
||||
+ "userSessionId: {}",
|
||||
connectionToken,
|
||||
institutionId,
|
||||
examId,
|
||||
clientAddress,
|
||||
userSessionId);
|
||||
}
|
||||
|
||||
checkExamRunning(examId);
|
||||
|
||||
final ClientConnection clientConnection = getClientConnection(
|
||||
connectionToken,
|
||||
institutionId);
|
||||
|
||||
checkInstitutionalIntegrity(
|
||||
institutionId,
|
||||
clientConnection);
|
||||
|
||||
final String virtualClientAddress = getVirtualClientAddress(
|
||||
(examId != null) ? examId : clientConnection.examId,
|
||||
clientAddress,
|
||||
clientConnection.clientAddress);
|
||||
|
||||
final ClientConnection updatedClientConnection = this.clientConnectionDAO
|
||||
.save(new ClientConnection(
|
||||
clientConnection.id,
|
||||
null,
|
||||
examId,
|
||||
null,
|
||||
null,
|
||||
userSessionId,
|
||||
null,
|
||||
virtualClientAddress))
|
||||
.getOrThrow();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("SEB client connection, successfully updated ClientConnection: {}",
|
||||
updatedClientConnection);
|
||||
}
|
||||
|
||||
return updatedClientConnection;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<ClientConnection> establishClientConnection(
|
||||
final String connectionToken,
|
||||
final Long institutionId,
|
||||
final Long examId,
|
||||
final String clientAddress,
|
||||
final String userSessionId) {
|
||||
|
@ -108,38 +177,30 @@ public class SebClientConnectionServiceImpl implements SebClientConnectionServic
|
|||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(
|
||||
"SEB client connection, establish ClientConnection for instituion {} and exam: {} and userSessionId: {}",
|
||||
"SEB client connection, establish ClientConnection for "
|
||||
+ "connectionToken {} "
|
||||
+ "institutionId"
|
||||
+ "exam: {} "
|
||||
+ "client address: {} "
|
||||
+ "userSessionId: {}",
|
||||
connectionToken,
|
||||
institutionId,
|
||||
examId,
|
||||
clientAddress,
|
||||
userSessionId);
|
||||
}
|
||||
|
||||
// Integrity check: is the specified exam running?
|
||||
if (!this.examSessionService.isExamRunning(examId)) {
|
||||
examNotRunningException(examId);
|
||||
}
|
||||
checkExamRunning(examId);
|
||||
|
||||
final ClientConnection clientConnection = this.clientConnectionDAO
|
||||
.byConnectionToken(institutionId, connectionToken)
|
||||
.get(t -> {
|
||||
// TODO: This indicates some irregularity on SEB-Client connection attempt.
|
||||
// Later we should handle this more accurately, and maybe indicate this to the monitoring board
|
||||
// For example; check if there is already a connection for the userIdentifier and
|
||||
// if true in which state it is.
|
||||
log.debug("Unable to connect SEB-Client {} to exam {}",
|
||||
clientAddress,
|
||||
this.examSessionService.getRunningExam(examId).map(exam -> exam.name));
|
||||
throw new IllegalStateException("Unable to connect SEB-Client to exam");
|
||||
});
|
||||
final ClientConnection clientConnection = getClientConnection(
|
||||
connectionToken,
|
||||
institutionId);
|
||||
|
||||
// Integrity checks:
|
||||
if (!institutionId.equals(clientConnection.institutionId)) {
|
||||
log.error("Instituion integrity violation with institution: {} on clientConnection: {}",
|
||||
institutionId,
|
||||
clientConnection);
|
||||
throw new IllegalAccessError("Instituion integrity violation");
|
||||
}
|
||||
checkInstitutionalIntegrity(
|
||||
institutionId,
|
||||
clientConnection);
|
||||
|
||||
// Exam integrity
|
||||
if (clientConnection.examId != null && !examId.equals(clientConnection.examId)) {
|
||||
log.error("Exam integrity violation with examId: {} on clientConnection: {}",
|
||||
examId,
|
||||
|
@ -147,30 +208,111 @@ public class SebClientConnectionServiceImpl implements SebClientConnectionServic
|
|||
throw new IllegalAccessError("Exam integrity violation");
|
||||
}
|
||||
|
||||
final ClientConnection updatedClientConnection = this.clientConnectionDAO.save(new ClientConnection(
|
||||
final String virtualClientAddress = getVirtualClientAddress(
|
||||
(examId != null) ? examId : clientConnection.examId,
|
||||
clientAddress,
|
||||
clientConnection.clientAddress);
|
||||
|
||||
final ClientConnection establishedClientConnection = new ClientConnection(
|
||||
clientConnection.id,
|
||||
clientConnection.institutionId,
|
||||
clientConnection.examId,
|
||||
null,
|
||||
examId,
|
||||
ClientConnection.ConnectionStatus.ESTABLISHED,
|
||||
null,
|
||||
userSessionId,
|
||||
null,
|
||||
null)).getOrThrow();
|
||||
virtualClientAddress);
|
||||
|
||||
// ClientConnection integrity
|
||||
if (establishedClientConnection.institutionId == null ||
|
||||
establishedClientConnection.examId == null ||
|
||||
establishedClientConnection.clientAddress == null ||
|
||||
establishedClientConnection.connectionToken == null) {
|
||||
|
||||
log.error("ClientConnection integrity violation: {}", establishedClientConnection);
|
||||
throw new IllegalStateException("ClientConnection integrity violation: " + establishedClientConnection);
|
||||
}
|
||||
|
||||
final ClientConnection updatedClientConnection = this.clientConnectionDAO
|
||||
.save(establishedClientConnection)
|
||||
.getOrThrow();
|
||||
|
||||
if (updatedClientConnection.status == ConnectionStatus.ESTABLISHED) {
|
||||
// load into cache...
|
||||
final ClientConnectionDataInternal activeClientConnection = this.examSessionCacheService
|
||||
.getActiveClientConnection(updatedClientConnection.connectionToken);
|
||||
|
||||
if (activeClientConnection == null) {
|
||||
log.warn("Unable to access and cache ClientConnection");
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("ClientConnection: {} successfully established", clientConnection);
|
||||
}
|
||||
} else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("ClientConnection: {} updated", clientConnection);
|
||||
}
|
||||
}
|
||||
|
||||
return updatedClientConnection;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<ClientConnection> closeConnection(final String connectionToken) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
public Result<ClientConnection> closeConnection(
|
||||
final String connectionToken,
|
||||
final Long institutionId,
|
||||
final String clientAddress) {
|
||||
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("SEB client connection: regular close attempt for "
|
||||
+ "instituion {} "
|
||||
+ "client address: {} "
|
||||
+ "connectionToken {} ",
|
||||
institutionId,
|
||||
clientAddress,
|
||||
connectionToken);
|
||||
}
|
||||
|
||||
final ClientConnection clientConnection = this.clientConnectionDAO
|
||||
.byConnectionToken(institutionId, connectionToken)
|
||||
.getOrThrow();
|
||||
|
||||
// evict ClientConnection from cache
|
||||
this.examSessionCacheService
|
||||
.evictClientConnection(clientConnection.connectionToken);
|
||||
|
||||
final ClientConnection updatedClientConnection = this.clientConnectionDAO.save(new ClientConnection(
|
||||
clientConnection.id,
|
||||
null,
|
||||
null,
|
||||
ClientConnection.ConnectionStatus.CLOSED,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null)).getOrThrow();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("SEB client connection: successfully closed ClientConnection: {}",
|
||||
clientConnection);
|
||||
}
|
||||
|
||||
return updatedClientConnection;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyPing(final Long connectionId, final long timestamp, final int pingNumber) {
|
||||
public void notifyPing(
|
||||
final String connectionToken,
|
||||
final long timestamp,
|
||||
final int pingNumber) {
|
||||
|
||||
final ClientConnectionDataInternal activeClientConnection =
|
||||
this.examSessionCacheService.getActiveClientConnection(connectionId);
|
||||
this.examSessionCacheService.getActiveClientConnection(connectionToken);
|
||||
|
||||
if (activeClientConnection != null) {
|
||||
activeClientConnection.pingMappings
|
||||
|
@ -180,11 +322,14 @@ public class SebClientConnectionServiceImpl implements SebClientConnectionServic
|
|||
}
|
||||
|
||||
@Override
|
||||
public void notifyClientEvent(final ClientEvent event, final Long connectionId) {
|
||||
public void notifyClientEvent(
|
||||
final String connectionToken,
|
||||
final ClientEvent event) {
|
||||
|
||||
this.eventHandlingStrategy.accept(event);
|
||||
|
||||
final ClientConnectionDataInternal activeClientConnection =
|
||||
this.examSessionCacheService.getActiveClientConnection(connectionId);
|
||||
this.examSessionCacheService.getActiveClientConnection(connectionToken);
|
||||
|
||||
if (activeClientConnection != null) {
|
||||
activeClientConnection.getindicatorMapping(event.eventType)
|
||||
|
@ -193,6 +338,30 @@ public class SebClientConnectionServiceImpl implements SebClientConnectionServic
|
|||
}
|
||||
}
|
||||
|
||||
private void checkExamRunning(final Long examId) {
|
||||
if (examId != null && !this.examSessionService.isExamRunning(examId)) {
|
||||
examNotRunningException(examId);
|
||||
}
|
||||
}
|
||||
|
||||
private ClientConnection getClientConnection(final String connectionToken, final Long institutionId) {
|
||||
final ClientConnection clientConnection = this.clientConnectionDAO
|
||||
.byConnectionToken(institutionId, connectionToken)
|
||||
.getOrThrow();
|
||||
return clientConnection;
|
||||
}
|
||||
|
||||
private void checkInstitutionalIntegrity(final Long institutionId, final ClientConnection clientConnection)
|
||||
throws IllegalAccessError {
|
||||
// Institutional integrity
|
||||
if (!institutionId.equals(clientConnection.institutionId)) {
|
||||
log.error("Instituion integrity violation with institution: {} on clientConnection: {}",
|
||||
institutionId,
|
||||
clientConnection);
|
||||
throw new IllegalAccessError("Instituion integrity violation");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO maybe we need a stronger connectionToken but for now a simple UUID is used
|
||||
private String createToken() {
|
||||
return UUID.randomUUID().toString();
|
||||
|
@ -203,4 +372,30 @@ public class SebClientConnectionServiceImpl implements SebClientConnectionServic
|
|||
throw new IllegalStateException("The exam " + examId + " is not running");
|
||||
}
|
||||
|
||||
private String getVirtualClientAddress(
|
||||
final Long examId,
|
||||
final String requestClientAddress,
|
||||
final String existingClientAddress) {
|
||||
|
||||
if (examId == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (requestClientAddress.equals(existingClientAddress)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!isVDI(examId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return requestClientAddress;
|
||||
}
|
||||
|
||||
private boolean isVDI(final Long examId) {
|
||||
return this.examSessionService.getRunningExam(examId)
|
||||
.getOrThrow()
|
||||
.getType() == ExamType.VDI;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import javax.servlet.ServletException;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.catalina.filters.RemoteIpFilter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -94,6 +95,15 @@ public class WebServiceSecurityConfig extends WebSecurityConfigurerAdapter {
|
|||
@Value("${sebserver.webservice.api.redirect.unauthorized}")
|
||||
private String unauthorizedRedirect;
|
||||
|
||||
/** Used to get real remote IP address by using "X-Forwarded-For" and "X-Forwarded-Proto" header.
|
||||
* https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/filters/RemoteIpFilter.html
|
||||
*
|
||||
* @return RemoteIpFilter instance */
|
||||
@Bean
|
||||
public RemoteIpFilter remoteIpFilter() {
|
||||
return new RemoteIpFilter();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AccessTokenConverter accessTokenConverter() {
|
||||
final DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
|
||||
|
|
|
@ -28,7 +28,6 @@ public class WebServiceUserDetails implements UserDetailsService {
|
|||
this.userDAO = userDAO;
|
||||
}
|
||||
|
||||
// TODO do we need an institution id here? otherwise username must be unique thought all institutions!
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {
|
||||
return this.userDAO.sebServerUserByUsername(username)
|
||||
|
|
|
@ -8,15 +8,22 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.webservice.weblayer.api;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
@ -24,43 +31,223 @@ import org.springframework.web.bind.annotation.RestController;
|
|||
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.PingResponse;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.RunningExam;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.SebClientConfigDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SebClientConnectionService;
|
||||
|
||||
@WebServiceProfile
|
||||
@RestController
|
||||
@RequestMapping("${sebserver.webservice.api.exam.endpoint.v1}")
|
||||
public class ExamAPI_V1_Controller {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ExamAPI_V1_Controller.class);
|
||||
|
||||
private final ExamDAO examDAO;
|
||||
private final ExamSessionService examSessionService;
|
||||
private final SebClientConnectionService sebClientConnectionService;
|
||||
private final SebClientConfigDAO sebClientConfigDAO;
|
||||
|
||||
protected ExamAPI_V1_Controller(
|
||||
final ExamDAO examDAO,
|
||||
final ExamSessionService examSessionService,
|
||||
final SebClientConnectionService sebClientConnectionService,
|
||||
final SebClientConfigDAO sebClientConfigDAO) {
|
||||
|
||||
this.examDAO = examDAO;
|
||||
this.examSessionService = examSessionService;
|
||||
this.sebClientConnectionService = sebClientConnectionService;
|
||||
this.sebClientConfigDAO = sebClientConfigDAO;
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
path = API.EXAM_API_HANDSHAKE_ENDPOINT,
|
||||
method = RequestMethod.GET,
|
||||
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
|
||||
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public Collection<RunningExam> handshake(
|
||||
@RequestParam(name = API.PARAM_INSTITUTION_ID, required = true) final Long institutionId,
|
||||
public Collection<RunningExam> handshakeCreate(
|
||||
@RequestParam(name = API.PARAM_INSTITUTION_ID, required = false) final Long instIdRequestParam,
|
||||
@RequestParam(name = API.EXAM_API_PARAM_EXAM_ID, required = false) final Long examIdRequestParam,
|
||||
@RequestBody final MultiValueMap<String, String> formParams,
|
||||
final Principal principal,
|
||||
final HttpServletRequest request,
|
||||
final HttpServletResponse response) {
|
||||
|
||||
// TODO
|
||||
return Arrays.asList(new RunningExam("1", "testExam", "TODO"));
|
||||
final POSTMapper mapper = new POSTMapper(formParams);
|
||||
|
||||
final String remoteAddr = request.getRemoteAddr();
|
||||
final Long institutionId = (instIdRequestParam != null)
|
||||
? instIdRequestParam
|
||||
: mapper.getLong(API.PARAM_INSTITUTION_ID);
|
||||
final Long examId = (examIdRequestParam != null)
|
||||
? examIdRequestParam
|
||||
: mapper.getLong(API.EXAM_API_PARAM_EXAM_ID);
|
||||
final Long clientsInstitution = getInstitutionId(principal);
|
||||
|
||||
if (!clientsInstitution.equals(institutionId)) {
|
||||
log.error("Institutional integrity violation: requested institution: {} authenticated institution: {}",
|
||||
institutionId,
|
||||
clientsInstitution);
|
||||
throw new APIConstraintViolationException("Institutional integrity violation");
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Request received on Exam Client Connection create endpoint: "
|
||||
+ "institution: {} "
|
||||
+ "exam: {} "
|
||||
+ "client-address: {}",
|
||||
institutionId,
|
||||
examId,
|
||||
remoteAddr);
|
||||
}
|
||||
|
||||
List<RunningExam> result;
|
||||
if (examId == null) {
|
||||
result = this.examSessionService.getRunningExamsForInstitution(institutionId)
|
||||
.getOrThrow()
|
||||
.stream()
|
||||
.map(exam -> new RunningExam(exam))
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
final Exam exam = this.examDAO.byPK(examId)
|
||||
.getOrThrow();
|
||||
|
||||
result = Arrays.asList(new RunningExam(exam));
|
||||
}
|
||||
|
||||
if (result.isEmpty()) {
|
||||
log.warn("There are no currently running exams for institution: {}. SEB connection creation denied");
|
||||
throw new IllegalStateException("There are no currently running exams");
|
||||
}
|
||||
|
||||
final ClientConnection clientConnection = this.sebClientConnectionService
|
||||
.createClientConnection(institutionId, remoteAddr, examId)
|
||||
.getOrThrow();
|
||||
|
||||
response.setHeader(
|
||||
API.EXAM_API_SEB_CONNECTION_TOKEN,
|
||||
clientConnection.connectionToken);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
path = API.EXAM_API_HANDSHAKE_ENDPOINT,
|
||||
method = RequestMethod.PATCH,
|
||||
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
public void handshakeUpdate(
|
||||
@RequestParam(name = API.EXAM_API_PARAM_EXAM_ID, required = false) final Long examId,
|
||||
@RequestParam(name = API.EXAM_API_SEB_CONNECTION_TOKEN, required = true) final String connectionToken,
|
||||
@RequestParam(name = API.EXAM_API_USER_SESSION_ID, required = false) final String userSessionId,
|
||||
final Principal principal,
|
||||
final HttpServletRequest request) {
|
||||
|
||||
final String remoteAddr = request.getRemoteAddr();
|
||||
final Long institutionId = getInstitutionId(principal);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Request received on SEB Client Connection update endpoint: "
|
||||
+ "institution: {} "
|
||||
+ "exam: {} "
|
||||
+ "userSessionId: {} "
|
||||
+ "client-address: {}",
|
||||
institutionId,
|
||||
examId,
|
||||
userSessionId,
|
||||
remoteAddr);
|
||||
}
|
||||
|
||||
this.sebClientConnectionService.establishClientConnection(
|
||||
connectionToken,
|
||||
institutionId,
|
||||
examId,
|
||||
remoteAddr,
|
||||
userSessionId)
|
||||
.getOrThrow();
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
path = API.EXAM_API_HANDSHAKE_ENDPOINT,
|
||||
method = RequestMethod.PUT,
|
||||
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
public void handshakeEstablish(
|
||||
@RequestParam(name = API.EXAM_API_PARAM_EXAM_ID, required = false) final Long examId,
|
||||
@RequestParam(name = API.EXAM_API_SEB_CONNECTION_TOKEN, required = true) final String connectionToken,
|
||||
@RequestParam(name = API.EXAM_API_USER_SESSION_ID, required = false) final String userSessionId,
|
||||
final Principal principal,
|
||||
final HttpServletRequest request) {
|
||||
|
||||
final String remoteAddr = request.getRemoteAddr();
|
||||
final Long institutionId = getInstitutionId(principal);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Request received on SEB Client Connection establish endpoint: "
|
||||
+ "institution: {} "
|
||||
+ "exam: {} "
|
||||
+ "client-address: {}",
|
||||
institutionId,
|
||||
examId,
|
||||
remoteAddr);
|
||||
}
|
||||
|
||||
this.sebClientConnectionService.establishClientConnection(
|
||||
connectionToken,
|
||||
institutionId,
|
||||
examId,
|
||||
remoteAddr,
|
||||
userSessionId)
|
||||
.getOrThrow();
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
path = API.EXAM_API_HANDSHAKE_ENDPOINT,
|
||||
method = RequestMethod.DELETE,
|
||||
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
public void handshakeEstablish(
|
||||
@RequestParam(name = API.EXAM_API_SEB_CONNECTION_TOKEN, required = true) final String connectionToken,
|
||||
final Principal principal,
|
||||
final HttpServletRequest request) {
|
||||
|
||||
final String remoteAddr = request.getRemoteAddr();
|
||||
final Long institutionId = getInstitutionId(principal);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Request received on SEB Client Connection close endpoint: "
|
||||
+ "institution: {} "
|
||||
+ "client-address: {}",
|
||||
institutionId,
|
||||
remoteAddr);
|
||||
}
|
||||
|
||||
this.sebClientConnectionService.closeConnection(
|
||||
connectionToken,
|
||||
institutionId,
|
||||
remoteAddr)
|
||||
.getOrThrow();
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
path = API.EXAM_API_CONFIGURATION_REQUEST_ENDPOINT,
|
||||
method = RequestMethod.GET,
|
||||
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
|
||||
produces = MediaType.TEXT_XML_VALUE)
|
||||
produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
public ResponseEntity<StreamingResponseBody> getConfig(
|
||||
@RequestParam(name = API.EXAM_API_SEB_CONNECTION_TOKEN, required = true) final String connectionToken,
|
||||
@RequestParam(name = API.EXAM_API_PARAM_EXAM_ID, required = true) final String examId) {
|
||||
final Principal principal) {
|
||||
|
||||
final Long institutionId = getInstitutionId(principal);
|
||||
final StreamingResponseBody stream = out -> this.examSessionService.streamDefaultExamConfig(
|
||||
institutionId,
|
||||
connectionToken,
|
||||
out);
|
||||
|
||||
// TODO
|
||||
// 1. check connection validity (connection token)
|
||||
// 2. get and stream SEB Exam configuration for specified exam (Id)
|
||||
final StreamingResponseBody stream = out -> out.write(Utils.toByteArray("TODO SEB Config"));
|
||||
return new ResponseEntity<>(stream, HttpStatus.OK);
|
||||
}
|
||||
|
||||
|
@ -68,13 +255,17 @@ public class ExamAPI_V1_Controller {
|
|||
path = API.EXAM_API_PING_ENDPOINT,
|
||||
method = RequestMethod.PUT,
|
||||
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
|
||||
produces = MediaType.TEXT_XML_VALUE)
|
||||
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public PingResponse ping(
|
||||
@RequestParam(name = API.EXAM_API_SEB_CONNECTION_TOKEN, required = true) final String connectionToken,
|
||||
final HttpServletRequest request,
|
||||
final HttpServletResponse response) {
|
||||
@RequestParam(name = API.EXAM_API_PING_TIMESTAMP, required = true) final long timestamp,
|
||||
@RequestParam(name = API.EXAM_API_PING_NUMBER, required = false) final int pingNumber) {
|
||||
|
||||
this.sebClientConnectionService
|
||||
.notifyPing(connectionToken, timestamp, pingNumber);
|
||||
|
||||
// TODO ping response (issue SEBSERV-74)
|
||||
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -84,11 +275,15 @@ public class ExamAPI_V1_Controller {
|
|||
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
public void event(
|
||||
@RequestParam(name = API.EXAM_API_SEB_CONNECTION_TOKEN, required = true) final String connectionToken,
|
||||
final HttpServletRequest request,
|
||||
final HttpServletResponse response) {
|
||||
@RequestBody(required = true) final ClientEvent event) {
|
||||
|
||||
// TODO
|
||||
this.sebClientConnectionService.notifyClientEvent(connectionToken, event);
|
||||
}
|
||||
|
||||
private Long getInstitutionId(final Principal principal) {
|
||||
final String clientId = principal.getName();
|
||||
return this.sebClientConfigDAO.byClientId(clientId)
|
||||
.getOrThrow().institutionId;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ public class WebClientDetailsService implements ClientDetailsService {
|
|||
"");
|
||||
|
||||
baseClientDetails.setScope(Collections.emptySet());
|
||||
baseClientDetails.setClientSecret(pwd);
|
||||
baseClientDetails.setClientSecret(Utils.toString(pwd));
|
||||
return baseClientDetails;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ sebserver.webservice.api.exam.refreshTokenValiditySeconds=-1
|
|||
sebserver.webservice.api.redirect.unauthorized=http://0.0.0.0:8080/gui
|
||||
sebserver.webservice.api.pagination.maxPageSize=500
|
||||
# comma separated list of known possible OpenEdX API access token request endpoints
|
||||
sebserver.lms.openedix.api.token.request.paths=/oauth2/access_token
|
||||
sebserver.webservice.lms.openedx.api.token.request.paths=/oauth2/access_token
|
||||
|
||||
sebserver.gui.entrypoint=/gui
|
||||
sebserver.gui.webservice.protocol=http
|
||||
|
|
|
@ -2,6 +2,9 @@ server.address=localhost
|
|||
server.port=8090
|
||||
server.servlet.context-path=/
|
||||
|
||||
logging.file=log/sebserver.log
|
||||
|
||||
#
|
||||
spring.datasource.initialize=true
|
||||
spring.datasource.initialization-mode=always
|
||||
spring.datasource.url=jdbc:mariadb://localhost:6603/SEBServer?useSSL=false
|
||||
|
@ -9,6 +12,7 @@ spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
|
|||
spring.datasource.platform=dev
|
||||
spring.datasource.hikari.max-lifetime=600000
|
||||
|
||||
# webservice configuration
|
||||
sebserver.webservice.http.scheme=http
|
||||
sebserver.webservice.http.server.name=localhost
|
||||
sebserver.webservice.api.admin.endpoint=/admin-api/v1
|
||||
|
@ -20,7 +24,11 @@ sebserver.webservice.api.exam.endpoint.v1=${sebserver.webservice.api.exam.endpoi
|
|||
sebserver.webservice.api.exam.accessTokenValiditySeconds=1800
|
||||
sebserver.webservice.api.exam.refreshTokenValiditySeconds=-1
|
||||
sebserver.webservice.api.exam.event-handling-strategy=ASYNC_BATCH_STORE_STRATEGY
|
||||
sebserver.webservice.api.exam.enable-indicator-cache=true
|
||||
sebserver.webservice.api.pagination.maxPageSize=500
|
||||
# comma separated list of known possible OpenEdX API access token request endpoints
|
||||
sebserver.webservice.lms.openedx.api.token.request.paths=/oauth2/access_token
|
||||
|
||||
# actuator configuration
|
||||
management.endpoints.web.base-path=/actuator
|
||||
|
||||
management.endpoints.web.exposure.include=logfile,loggers
|
|
@ -8,5 +8,3 @@ spring.http.encoding.enabled=true
|
|||
sebserver.version=0.3.0 pre-beta
|
||||
sebserver.supported.languages=en,de
|
||||
|
||||
# comma separated list of known possible OpenEdX API access token request endpoints
|
||||
sebserver.lms.openedix.api.token.request.paths=/oauth2/access_token
|
|
@ -7,8 +7,8 @@
|
|||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="DEMO" class="ch.qos.logback.core.FileAppender">
|
||||
<file> log-${byDay}.txt </file>
|
||||
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
|
||||
<file>log/sebserver.log</file>
|
||||
<append>true</append>
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} %-5level [%thread]:[%logger] %msg%n</pattern>
|
||||
|
@ -19,6 +19,7 @@
|
|||
|
||||
<root level="INFO" additivity="true">
|
||||
<appender-ref ref="STDOUT" />
|
||||
<appender-ref ref="FILE" />
|
||||
</root>
|
||||
|
||||
<Logger name="ch.ethz.seb.sebserver" level="DEBUG" additivity="true" />
|
||||
|
|
|
@ -79,18 +79,25 @@ DROP TABLE IF EXISTS `client_connection` ;
|
|||
|
||||
CREATE TABLE IF NOT EXISTS `client_connection` (
|
||||
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`institution_id` BIGINT UNSIGNED NOT NULL,
|
||||
`exam_id` BIGINT UNSIGNED NULL,
|
||||
`status` VARCHAR(45) NOT NULL,
|
||||
`connection_token` VARCHAR(255) NOT NULL,
|
||||
`exam_user_session_identifer` VARCHAR(255) NOT NULL,
|
||||
`exam_user_session_identifer` VARCHAR(255) NULL,
|
||||
`client_address` VARCHAR(45) NOT NULL,
|
||||
`virtual_client_address` VARCHAR(45) NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `connection_exam_ref_idx` (`exam_id` ASC),
|
||||
INDEX `clientConnectionInstitutionRef_idx` (`institution_id` ASC),
|
||||
CONSTRAINT `clientConnectionExamRef`
|
||||
FOREIGN KEY (`exam_id`)
|
||||
REFERENCES `exam` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION,
|
||||
CONSTRAINT `clientConnectionInstitutionRef`
|
||||
FOREIGN KEY (`institution_id`)
|
||||
REFERENCES `institution` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION)
|
||||
;
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ CREATE TABLE IF NOT EXISTS `client_connection` (
|
|||
`exam_id` BIGINT UNSIGNED NULL,
|
||||
`status` VARCHAR(45) NOT NULL,
|
||||
`connection_token` VARCHAR(255) NOT NULL,
|
||||
`exam_user_session_identifer` VARCHAR(255) NOT NULL,
|
||||
`exam_user_session_identifer` VARCHAR(255) NULL,
|
||||
`client_address` VARCHAR(45) NOT NULL,
|
||||
`virtual_client_address` VARCHAR(45) NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
|
|
|
@ -20,13 +20,12 @@ public class ClientCredentialServiceTest {
|
|||
// @Test
|
||||
// public void testEncryptSimpleSecret() {
|
||||
// final Environment envMock = mock(Environment.class);
|
||||
// when(envMock.getRequiredProperty(ClientCredentialService.SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY))
|
||||
// .thenReturn("secret1");
|
||||
// when(envMock.getRequiredProperty(ClientCredentialServiceImpl.SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY))
|
||||
// .thenReturn("internalSecret");
|
||||
//
|
||||
// final ClientCredentialService service = new ClientCredentialService(envMock);
|
||||
// final String encrypt = service.encrypt("text1");
|
||||
// final String decrypt = service.decrypt(encrypt);
|
||||
// assertEquals("text1", decrypt);
|
||||
// final ClientCredentialService service = new ClientCredentialServiceImpl(envMock);
|
||||
// final CharSequence encrypt = service.encrypt("test");
|
||||
// assertEquals("", encrypt.toString());
|
||||
// }
|
||||
|
||||
@Test
|
||||
|
|
|
@ -23,5 +23,7 @@ sebserver.webservice.api.exam.accessTokenValiditySeconds=1800
|
|||
sebserver.webservice.api.exam.refreshTokenValiditySeconds=-1
|
||||
sebserver.webservice.internalSecret=TO_SET
|
||||
sebserver.webservice.api.redirect.unauthorized=none
|
||||
# comma separated list of known possible OpenEdX API access token request endpoints
|
||||
sebserver.webservice.lms.openedx.api.token.request.paths=/oauth2/access_token
|
||||
|
||||
management.endpoints.web.base-path=/actuator
|
813
src/test/resources/data-test-additional.sql
Normal file
813
src/test/resources/data-test-additional.sql
Normal file
|
@ -0,0 +1,813 @@
|
|||
INSERT IGNORE INTO lms_setup VALUES
|
||||
(1, 1, 'test', 'MOCKUP', 'http://', 'ccdfa2330533ed6c316a8ffbd64a3197d4a79956ac7ee4c1162f7bdb1a27234fe8793615a51074351e', '8d14b78ecdcbec1d010d414a7208dbe5c411f1fa735c35c7427d840453093a3730d1bc0abe13b9b1a8', null, 1)
|
||||
;
|
||||
|
||||
INSERT IGNORE INTO seb_client_configuration VALUES
|
||||
(1, 1, 'test', '2019-07-02 09:22:50', 'test', '98ac3c953abf5948d9d13c81cab580819ee2624c76d6d4147d4896a5b79f49956d382c08c93cb3b9ae350b32', null, 1)
|
||||
;
|
||||
|
||||
INSERT IGNORE INTO exam VALUES
|
||||
(1, 1, 1, 'quiz1', 'super-admin', 'super-admin', 'MANAGED', null, null, 1),
|
||||
(2, 1, 1, 'quiz6', 'super-admin', 'super-admin', 'MANAGED', null, null, 1)
|
||||
;
|
||||
|
||||
INSERT IGNORE INTO indicator VALUES
|
||||
(1, 2, 'LAST_PING', 'Ping', 'dcdcdc')
|
||||
;
|
||||
|
||||
INSERT IGNORE INTO threshold VALUES
|
||||
(1, 1, 1000.0000, '22b14c'),
|
||||
(2, 1, 2000.0000, 'ff7e00'),
|
||||
(3, 1, 5000.0000, 'ed1c24')
|
||||
;
|
||||
|
||||
INSERT IGNORE INTO view VALUES
|
||||
(1, 'general', 4, 1),
|
||||
(2, 'user_interface', 12, 2),
|
||||
(3, 'browser', 12, 3),
|
||||
(4, 'down_upload', 12, 4),
|
||||
(5, 'exam', 12, 5),
|
||||
(6, 'applications', 12, 6),
|
||||
(7, 'resources', 12, 7),
|
||||
(8, 'network', 12, 8),
|
||||
(9, 'security', 12, 9),
|
||||
(10, 'registry', 12, 10),
|
||||
(11, 'hooked_keys', 12, 11);
|
||||
|
||||
INSERT IGNORE INTO configuration_attribute VALUES
|
||||
(1, 'hashedAdminPassword', 'PASSWORD_FIELD', null, null, null, null, null),
|
||||
(2, 'allowQuit', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(3, 'ignoreExitKeys', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(4, 'hashedQuitPassword', 'PASSWORD_FIELD', null, null, null, null, null),
|
||||
(5, 'exitKey1', 'SINGLE_SELECTION', null, '0,1,2,3,4,5,6,7,8,9,10,11', 'ExitKeySequenceValidator', 'resourceLocTextKey=sebserver.examconfig.props.label.exitKey', '2'),
|
||||
(6, 'exitKey2', 'SINGLE_SELECTION', null, '0,1,2,3,4,5,6,7,8,9,10,11', 'ExitKeySequenceValidator', 'resourceLocTextKey=sebserver.examconfig.props.label.exitKey', '10'),
|
||||
(7, 'exitKey3', 'SINGLE_SELECTION', null, '0,1,2,3,4,5,6,7,8,9,10,11', 'ExitKeySequenceValidator', 'resourceLocTextKey=sebserver.examconfig.props.label.exitKey', '5'),
|
||||
|
||||
(8, 'browserViewMode', 'RADIO_SELECTION', null, '0,1,2', null, null, '0'),
|
||||
(9, 'enableTouchExit', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(10, 'mainBrowserWindowWidth', 'COMBO_SELECTION', null, '50%,100%,800,1000', 'WindowsSizeValidator', null, '100%'),
|
||||
(11, 'mainBrowserWindowHeight', 'COMBO_SELECTION', null, '80%,100%,600,800', 'WindowsSizeValidator', null, '100%'),
|
||||
(12, 'mainBrowserWindowPositioning', 'SINGLE_SELECTION', null, '0,1,2', null, null, '1'),
|
||||
(13, 'enableBrowserWindowToolbar', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(14, 'hideBrowserWindowToolbar', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(15, 'showMenuBar', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(16, 'showTaskBar', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(17, 'taskBarHeight', 'COMBO_SELECTION', null, '40,60,80', 'IntegerTypeValidator', null, '40'),
|
||||
(18, 'showReloadButton', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(19, 'showTime', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(20, 'showInputLanguage', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(21, 'enableZoomPage', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(22, 'enableZoomText', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(23, 'zoomMode', 'RADIO_SELECTION', null, '0,1', null, null, '0'),
|
||||
(24, 'audioControlEnabled', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(25, 'audioMute', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(26, 'audioSetVolumeLevel', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(27, 'audioVolumeLevel', 'SLIDER', null, '0,100', null, null, '25'),
|
||||
(28, 'allowSpellCheck', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(29, 'allowDictionaryLookup', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(30, 'allowSpellCheckDictionary', 'MULTI_CHECKBOX_SELECTION', null, 'da-DK,en-AU,en-GB,en-US,es-ES,fr-FR,pt-PT,sv-SE,sv-FI', null, null, 'da-DK,en-AU,en-GB,en-US,es-ES,fr-FR,pt-PT,sv-SE,sv-FI'),
|
||||
|
||||
(31, 'newBrowserWindowByLinkPolicy', 'RADIO_SELECTION', null, '0,1,2', null, null, '2'),
|
||||
(32, 'newBrowserWindowByLinkBlockForeign', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(33, 'newBrowserWindowByLinkWidth', 'COMBO_SELECTION', null, '50%,100%,800,1000', 'WindowsSizeValidator', null, '100%'),
|
||||
(34, 'newBrowserWindowByLinkHeight', 'COMBO_SELECTION', null, '80%,100%,600,800', 'WindowsSizeValidator', null, '100%'),
|
||||
(35, 'newBrowserWindowByLinkPositioning', 'SINGLE_SELECTION', null, '0,1,2', null, null, '2'),
|
||||
(36, 'enablePlugIns', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(37, 'enableJavaScript', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(38, 'enableJava', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(39, 'blockPopUpWindows', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(40, 'allowVideoCapture', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(41, 'allowAudioCapture', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(42, 'allowBrowsingBackForward', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(43, 'newBrowserWindowNavigation', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(44, 'browserWindowAllowReload', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(45, 'newBrowserWindowAllowReload', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(46, 'showReloadWarning', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(47, 'newBrowserWindowShowReloadWarning', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(48, 'removeBrowserProfile', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(49, 'removeLocalStorage', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(50, 'browserUserAgent', 'TEXT_FIELD', null, null, null, null, null),
|
||||
(51, 'browserUserAgentWinDesktopMode', 'RADIO_SELECTION', null, '0,1', null, null, '0'),
|
||||
(52, 'browserUserAgentWinDesktopModeCustom', 'TEXT_FIELD', null, null, null, null, null),
|
||||
(53, 'browserUserAgentWinTouchMode', 'RADIO_SELECTION', null, '0,1,2', null, null, '0'),
|
||||
(54, 'browserUserAgentWinTouchModeCustom', 'TEXT_FIELD', null, null, null, null, null),
|
||||
(55, 'browserUserAgentMac', 'RADIO_SELECTION', null, '0,1', null, null, '0'),
|
||||
(56, 'browserUserAgentMacCustom', 'TEXT_FIELD', null, null, null, null, null),
|
||||
(57, 'enableSebBrowser', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(58, 'browserWindowTitleSuffix', 'TEXT_FIELD', null, null, null, null, null),
|
||||
|
||||
(59, 'allowDownUploads', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(60, 'downloadDirectoryWin', 'TEXT_FIELD', null, null, null, null, null),
|
||||
(61, 'downloadDirectoryOSX', 'TEXT_FIELD', null, null, null, null, null),
|
||||
(62, 'openDownloads', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(63, 'chooseFileToUploadPolicy', 'RADIO_SELECTION', null, '0,1,2', null, null, '0'),
|
||||
(64, 'downloadPDFFiles', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(65, 'allowPDFPlugIn', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(66, 'downloadAndOpenSebConfig', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
|
||||
(67, 'quitURL', 'TEXT_FIELD', null, null, null, null, null),
|
||||
(68, 'quitURLConfirm', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(69, 'restartExamUseStartURL', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(70, 'restartExamURL', 'TEXT_FIELD', null, null, null, null, null),
|
||||
(71, 'restartExamText', 'TEXT_FIELD', null, null, null, null, null),
|
||||
(72, 'restartExamPasswordProtected', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
|
||||
(73, 'permittedProcesses', 'TABLE', null, null, null, null, null),
|
||||
(74, 'permittedProcesses.active', 'CHECKBOX', 73, null, null, null, 'true'),
|
||||
(75, 'permittedProcesses.os', 'SINGLE_SELECTION', 73, '0,1', null, null, '0'),
|
||||
(76, 'permittedProcesses.title', 'TEXT_FIELD', 73, null, null, null, ''),
|
||||
(77, 'permittedProcesses.description', 'TEXT_FIELD', 73, null, null, null, ''),
|
||||
(78, 'permittedProcesses.executable', 'TEXT_FIELD', 73, null, null, null, ''),
|
||||
(79, 'permittedProcesses.originalName', 'TEXT_FIELD', 73, null, null, null, ''),
|
||||
(80, 'permittedProcesses.allowedExecutables', 'TEXT_FIELD', 73, null, null, null, ''),
|
||||
(81, 'permittedProcesses.path', 'TEXT_FIELD', 73, null, null, null, ''),
|
||||
(82, 'permittedProcesses.arguments', 'INLINE_TABLE', 73, '1:active:CHECKBOX|4:argument:TEXT_FIELD', null, null, null),
|
||||
(85, 'permittedProcesses.identifier', 'TEXT_FIELD', 73, null, null, null, ''),
|
||||
(86, 'permittedProcesses.iconInTaskbar', 'CHECKBOX', 73, null, null, null, 'true'),
|
||||
(87, 'permittedProcesses.autostart', 'CHECKBOX', 73, null, null, null, 'false'),
|
||||
(88, 'permittedProcesses.runInBackground', 'CHECKBOX', 73, null, null, null, 'false'),
|
||||
(89, 'permittedProcesses.allowUserToChooseApp', 'CHECKBOX', 73, null, null, null, 'false'),
|
||||
(90, 'permittedProcesses.strongKill', 'CHECKBOX', 73, null, null, null, 'false'),
|
||||
(91, 'allowSwitchToApplications', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(92, 'allowFlashFullscreen', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
|
||||
(93, 'prohibitedProcesses', 'TABLE', null, null, null, null, null),
|
||||
(94, 'prohibitedProcesses.active', 'CHECKBOX', 93, null, null, null, 'true'),
|
||||
(95, 'prohibitedProcesses.os', 'SINGLE_SELECTION', 93, '0,1', null, null, '0'),
|
||||
(96, 'prohibitedProcesses.executable', 'TEXT_FIELD', 93, null, null, null, ''),
|
||||
(97, 'prohibitedProcesses.description', 'TEXT_FIELD', 93, null, null, null, ''),
|
||||
(98, 'prohibitedProcesses.originalName', 'TEXT_FIELD', 93, null, null, null, ''),
|
||||
(99, 'prohibitedProcesses.identifier', 'TEXT_FIELD', 93, null, null, null, ''),
|
||||
(100, 'prohibitedProcesses.strongKill', 'CHECKBOX', 93, null, null, null, 'false'),
|
||||
|
||||
(200, 'URLFilterEnable', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(201, 'URLFilterEnableContentFilter', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(202, 'URLFilterRules', 'TABLE', null, null, null, null, null),
|
||||
(203, 'URLFilterRules.active', 'CHECKBOX', 202, null, null, null, 'true'),
|
||||
(204, 'URLFilterRules.regex', 'CHECKBOX', 202, null, null, null, 'false'),
|
||||
(205, 'URLFilterRules.expression', 'TEXT_FIELD', 202, null, null, null, ''),
|
||||
(206, 'URLFilterRules.action', 'SINGLE_SELECTION', 202, '0,1', null, null, ''),
|
||||
|
||||
(210, 'proxySettingsPolicy', 'RADIO_SELECTION', null, '0,1', null, null, '0'),
|
||||
(220, 'proxies', 'COMPOSITE_TABLE', null, 'active,TABLE_ENTRY|autoDiscovery,autoConfiguration,http,https,ftp,socks,rtsp', null, null, null),
|
||||
(221, 'ExcludeSimpleHostnames', 'CHECKBOX', 220, null, null, 'showInView=true,createDefaultValue=true', 'false'),
|
||||
(222, 'ExceptionsList', 'TEXT_AREA', 220, null, null, 'showInView=true,createDefaultValue=true', null),
|
||||
(223, 'FTPPassive', 'CHECKBOX', 220, null, null, 'showInView=true,createDefaultValue=true', 'true'),
|
||||
(231, 'AutoDiscoveryEnabled', 'CHECKBOX', 220, null, null, 'groupId=autoDiscovery,createDefaultValue=true', 'false'),
|
||||
(233, 'AutoConfigurationEnabled', 'CHECKBOX', 220, null, null, 'groupId=autoConfiguration,createDefaultValue=true', 'false'),
|
||||
(234, 'AutoConfigurationURL', 'TEXT_FIELD', 220, null, null, 'groupId=autoConfiguration,createDefaultValue=true', null),
|
||||
(235, 'AutoConfigurationJavaScript', 'TEXT_AREA', 220, null, null, 'groupId=autoConfiguration,createDefaultValue=true', null),
|
||||
(236, 'HTTPEnable', 'CHECKBOX', 220, null, null, 'groupId=http,createDefaultValue=true', 'false'),
|
||||
(237, 'HTTPProxy', 'TEXT_FIELD', 220, null, null, 'groupId=http,createDefaultValue=true', null),
|
||||
(238, 'HTTPPort', 'INTEGER', 220, null, null, 'groupId=http,createDefaultValue=true', '80'),
|
||||
(239, 'HTTPRequiresPassword', 'CHECKBOX', 220, null, null, 'groupId=http,createDefaultValue=true', 'false'),
|
||||
(240, 'HTTPUsername', 'TEXT_FIELD', 220, null, null, 'groupId=http,createDefaultValue=true', null),
|
||||
(241, 'HTTPPassword', 'TEXT_FIELD', 220, null, null, 'groupId=http,createDefaultValue=true', null),
|
||||
(242, 'HTTPSEnable', 'CHECKBOX', 220, null, null, 'groupId=https,createDefaultValue=true', 'false'),
|
||||
(243, 'HTTPSProxy', 'TEXT_FIELD', 220, null, null, 'groupId=https,createDefaultValue=true', null),
|
||||
(244, 'HTTPSPort', 'INTEGER', 220, null, null, 'groupId=https,createDefaultValue=true', '443'),
|
||||
(245, 'HTTPSRequiresPassword', 'CHECKBOX', 220, null, null, 'groupId=https,createDefaultValue=true', 'false'),
|
||||
(246, 'HTTPSUsername', 'TEXT_FIELD', 220, null, null, 'groupId=https,createDefaultValue=true', null),
|
||||
(247, 'HTTPSPassword', 'TEXT_FIELD', 220, null, null, 'groupId=https,createDefaultValue=true', null),
|
||||
(248, 'FTPEnable', 'CHECKBOX', 220, null, null, 'groupId=ftp,createDefaultValue=true', 'false'),
|
||||
(249, 'FTPProxy', 'TEXT_FIELD', 220, null, null, 'groupId=ftp,createDefaultValue=true', null),
|
||||
(250, 'FTPPort', 'INTEGER', 220, null, null, 'groupId=ftp,createDefaultValue=true', '21'),
|
||||
(251, 'FTPRequiresPassword', 'CHECKBOX', 220, null, null, 'groupId=ftp,createDefaultValue=true', 'false'),
|
||||
(252, 'FTPUsername', 'TEXT_FIELD', 220, null, null, 'groupId=ftp,createDefaultValue=true', null),
|
||||
(253, 'FTPPassword', 'TEXT_FIELD', 220, null, null, 'groupId=ftp,createDefaultValue=true', null),
|
||||
(254, 'SOCKSEnable', 'CHECKBOX', 220, null, null, 'groupId=socks,createDefaultValue=true', 'false'),
|
||||
(255, 'SOCKSProxy', 'TEXT_FIELD', 220, null, null, 'groupId=socks,createDefaultValue=true', null),
|
||||
(256, 'SOCKSPort', 'INTEGER', 220, null, null, 'groupId=socks,createDefaultValue=true', '1080'),
|
||||
(257, 'SOCKSRequiresPassword', 'CHECKBOX', 220, null, null, 'groupId=socks,createDefaultValue=true', 'false'),
|
||||
(258, 'SOCKSUsername', 'TEXT_FIELD', 220, null, null, 'groupId=socks,createDefaultValue=true', null),
|
||||
(259, 'SOCKSPassword', 'TEXT_FIELD', 220, null, null, 'groupId=socks,createDefaultValue=true', null),
|
||||
(260, 'RTSPEnable', 'CHECKBOX', 220, null, null, 'groupId=rtsp,createDefaultValue=true', 'false'),
|
||||
(261, 'RTSPProxy', 'TEXT_FIELD', 220, null, null, 'groupId=rtsp,createDefaultValue=true', null),
|
||||
(262, 'RTSPPort', 'INTEGER', 220, null, null, 'groupId=rtsp,createDefaultValue=true', '1080'),
|
||||
(263, 'RTSPRequiresPassword', 'CHECKBOX', 220, null, null, 'groupId=rtsp,createDefaultValue=true', 'false'),
|
||||
(264, 'RTSPUsername', 'TEXT_FIELD', 220, null, null, 'groupId=rtsp,createDefaultValue=true', null),
|
||||
(265, 'RTSPPassword', 'TEXT_FIELD', 220, null, null, 'groupId=rtsp,createDefaultValue=true', null),
|
||||
|
||||
|
||||
(300, 'sebServicePolicy', 'RADIO_SELECTION', null, '0,1,2', null, null, '2'),
|
||||
(301, 'kioskMode', 'RADIO_SELECTION', null, '0,1,2', null, null, '0'),
|
||||
(302, 'allowVirtualMachine', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(303, 'allowScreenSharing', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(304, 'enablePrivateClipboard', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(305, 'enableLogging', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(306, 'logDirectoryWin', 'TEXT_FIELD', null, null, null, null, ''),
|
||||
(307, 'logDirectoryOSX', 'TEXT_FIELD', null, null, null, null, '~/Documents'),
|
||||
(308, 'minMacOSVersion', 'SINGLE_SELECTION', null, '0,1,2,3,4,5,6,7', null, null, '0'),
|
||||
(309, 'enableAppSwitcherCheck', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(310, 'forceAppFolderInstall', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(311, 'allowUserAppFolderInstall', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(312, 'allowSiri', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(313, 'detectStoppedProcess', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(314, 'allowDisplayMirroring', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(315, 'allowedDisplaysMaxNumber', 'COMBO_SELECTION', null, '1,2,3', null, null, '1'),
|
||||
(316, 'allowedDisplayBuiltin', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
|
||||
(400, 'insideSebEnableSwitchUser', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(401, 'insideSebEnableLockThisComputer', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(402, 'insideSebEnableChangeAPassword', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(403, 'insideSebEnableStartTaskManager', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(404, 'insideSebEnableLogOff', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(405, 'insideSebEnableShutDown', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(406, 'insideSebEnableEaseOfAccess', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(407, 'insideSebEnableVmWareClientShade', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(408, 'insideSebEnableNetworkConnectionSelector', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
|
||||
(500, 'enableEsc', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(501, 'enablePrintScreen', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(502, 'enableCtrlEsc', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(503, 'enableAltEsc', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(504, 'enableAltTab', 'CHECKBOX', null, null, null, null, 'true'),
|
||||
(505, 'enableAltF4', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(506, 'enableStartMenu', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(507, 'enableRightMouse', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(508, 'enableAltMouseWheel', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
|
||||
(509, 'enableF1', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(510, 'enableF2', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(511, 'enableF3', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(512, 'enableF4', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(513, 'enableF5', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(514, 'enableF6', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(515, 'enableF7', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(516, 'enableF8', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(517, 'enableF9', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(518, 'enableF10', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(519, 'enableF11', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
(520, 'enableF12', 'CHECKBOX', null, null, null, null, 'false'),
|
||||
|
||||
(1000, 'originatorVersion', 'TEXT_FIELD', null, null, null, null, 'SEB_Server_0.3.0'),
|
||||
(1001, 'sebConfigPurpose', 'RADIO_SELECTION', null, '0,1', null, null, '0')
|
||||
|
||||
;
|
||||
INSERT IGNORE INTO orientation VALUES
|
||||
(1, 1, 0, 1, null, 1, 1, 1, 2, 'LEFT'),
|
||||
(2, 2, 0, 1, null, 1, 3, 1, 1, 'LEFT'),
|
||||
(3, 3, 0, 1, null, 1, 4, 1, 1, 'LEFT'),
|
||||
(4, 4, 0, 1, null, 1, 5, 1, 2, 'LEFT'),
|
||||
(5, 5, 0, 1, 'exitSequence', 2, 1, 1, 1, 'NONE'),
|
||||
(6, 6, 0, 1, 'exitSequence', 2, 2, 1, 1, 'NONE'),
|
||||
(7, 7, 0, 1, 'exitSequence', 2, 3, 1, 1, 'NONE'),
|
||||
|
||||
(8, 8, 0, 2, 'browserViewMode', 0, 0, 3, 3, 'NONE'),
|
||||
(9, 9, 0, 2, 'browserViewMode', 3, 2, 4, 1, 'NONE'),
|
||||
(10, 10, 0, 2, 'winsize', 1, 4, 2, 1, 'LEFT'),
|
||||
(11, 11, 0, 2, 'winsize', 1, 5, 2, 1, 'LEFT'),
|
||||
(12, 12, 0, 2, 'winsize', 5, 4, 2, 1, 'LEFT_SPAN'),
|
||||
(13, 13, 0, 2, 'wintoolbar', 0, 6, 3, 1, 'NONE'),
|
||||
(14, 14, 0, 2, 'wintoolbar', 3, 6, 4, 1, 'NONE'),
|
||||
(15, 15, 0, 2, 'wintoolbar', 0, 7, 3, 1, 'NONE'),
|
||||
(16, 16, 0, 2, 'taskbar', 0, 9, 3, 1, 'NONE'),
|
||||
(17, 17, 0, 2, 'taskbar', 5, 9, 2, 1, 'LEFT_SPAN'),
|
||||
(18, 18, 0, 2, 'taskbar', 0, 10, 3, 1, 'NONE'),
|
||||
(19, 19, 0, 2, 'taskbar', 0, 11, 3, 1, 'NONE'),
|
||||
(20, 20, 0, 2, 'taskbar', 0, 12, 3, 1, 'NONE'),
|
||||
(21, 21, 0, 2, 'zoom', 0, 14, 3, 1, 'NONE'),
|
||||
(22, 22, 0, 2, 'zoom', 0, 15, 3, 1, 'NONE'),
|
||||
(23, 23, 0, 2, 'zoomMode', 3, 14, 4, 1, 'NONE'),
|
||||
(24, 24, 0, 2, 'audio', 7, 0, 5, 1, 'NONE'),
|
||||
(25, 25, 0, 2, 'audio', 7, 1, 5, 1, 'NONE'),
|
||||
(26, 26, 0, 2, 'audio', 7, 2, 5, 1, 'NONE'),
|
||||
(27, 27, 0, 2, 'audio', 7, 3, 5, 1, 'NONE'),
|
||||
(28, 28, 0, 2, 'spellcheck', 7, 4, 5, 1, 'NONE'),
|
||||
(29, 29, 0, 2, 'spellcheck', 7, 5, 5, 1, 'NONE'),
|
||||
(30, 30, 0, 2, 'spellcheck', 7, 7, 5, 9, 'TOP'),
|
||||
|
||||
(31, 31, 0, 3, 'newBrowserWindow', 0, 0, 3, 3, 'NONE'),
|
||||
(32, 32, 0, 3, 'newBrowserWindow', 4, 0, 3, 1, 'NONE'),
|
||||
(33, 33, 0, 3, 'newwinsize', 1, 4, 2, 1, 'LEFT'),
|
||||
(34, 34, 0, 3, 'newwinsize', 1, 5, 2, 1, 'LEFT'),
|
||||
(35, 35, 0, 3, 'newwinsize', 5, 4, 2, 1, 'LEFT_SPAN'),
|
||||
(36, 36, 0, 3, 'browserSecurity', 0, 5, 4, 1, 'NONE'),
|
||||
(37, 37, 0, 3, 'browserSecurity', 4, 5, 3, 1, 'NONE'),
|
||||
(38, 38, 0, 3, 'browserSecurity', 0, 6, 4, 1, 'NONE'),
|
||||
(39, 39, 0, 3, 'browserSecurity', 4, 6, 3, 1, 'NONE'),
|
||||
(40, 40, 0, 3, 'browserSecurity', 0, 7, 4, 1, 'NONE'),
|
||||
(41, 41, 0, 3, 'browserSecurity', 4, 7, 3, 1, 'NONE'),
|
||||
(42, 42, 0, 3, 'browserSecurity', 0, 8, 4, 1, 'NONE'),
|
||||
(43, 43, 0, 3, 'browserSecurity', 4, 8, 3, 1, 'NONE'),
|
||||
(44, 44, 0, 3, 'browserSecurity', 0, 9, 4, 1, 'NONE'),
|
||||
(45, 45, 0, 3, 'browserSecurity', 4, 9, 3, 1, 'NONE'),
|
||||
(46, 46, 0, 3, 'browserSecurity', 0, 10, 4, 1, 'NONE'),
|
||||
(47, 47, 0, 3, 'browserSecurity', 4, 10, 3, 1, 'NONE'),
|
||||
(48, 48, 0, 3, 'browserSecurity', 0, 11, 4, 1, 'NONE'),
|
||||
(49, 49, 0, 3, 'browserSecurity', 4, 11, 3, 1, 'NONE'),
|
||||
|
||||
(50, 50, 0, 3, null, 7, 1, 5, 1, 'TOP'),
|
||||
(51, 51, 0, 3, 'userAgentDesktop', 7, 2, 5, 2, 'NONE'),
|
||||
(52, 52, 0, 3, 'userAgentDesktop', 7, 3, 5, 1, 'NONE'),
|
||||
(53, 53, 0, 3, 'userAgentTouch', 7, 4, 5, 3, 'NONE'),
|
||||
(54, 54, 0, 3, 'userAgentTouch', 7, 8, 5, 1, 'NONE'),
|
||||
(55, 55, 0, 3, 'userAgentMac', 7, 9, 5, 2, 'NONE'),
|
||||
(56, 56, 0, 3, 'userAgentMac', 7, 11, 5, 1, 'NONE'),
|
||||
(57, 57, 0, 3, null, 0, 14, 6, 1, 'NONE'),
|
||||
(58, 58, 0, 3, null, 7, 14, 5, 1, 'TOP'),
|
||||
|
||||
(59, 59, 0, 4, null, 0, 0, 8, 1, 'NONE'),
|
||||
(60, 60, 0, 4, null, 3, 1, 5, 1, 'LEFT_SPAN'),
|
||||
(61, 61, 0, 4, null, 3, 2, 5, 1, 'LEFT_SPAN'),
|
||||
(62, 62, 0, 4, null, 0, 3, 8, 1, 'NONE'),
|
||||
(63, 63, 0, 4, null, 0, 5, 8, 2, 'TOP'),
|
||||
(64, 64, 0, 4, null, 0, 8, 8, 1, 'NONE'),
|
||||
(65, 65, 0, 4, null, 0, 9, 8, 1, 'NONE'),
|
||||
(66, 66, 0, 4, null, 0, 10, 8, 1, 'NONE'),
|
||||
|
||||
(67, 67, 0, 5, 'quitLink', 0, 1, 8, 1, 'TOP'),
|
||||
(68, 68, 0, 5, 'quitLink', 0, 2, 8, 1, 'NONE'),
|
||||
(69, 69, 0, 5, 'backToStart', 0, 4, 8, 1, 'NONE'),
|
||||
(70, 70, 0, 5, 'backToStart', 0, 6, 8, 2, 'TOP'),
|
||||
(71, 71, 0, 5, 'backToStart', 0, 8, 8, 2, 'TOP'),
|
||||
(72, 72, 0, 5, 'backToStart', 0, 10, 8, 1, 'NONE'),
|
||||
|
||||
(73, 73, 0, 6, null, 0, 2, 10, 6, 'TOP'),
|
||||
(74, 74, 0, 6, null, 1, 1, 1, 1, 'LEFT'),
|
||||
(75, 75, 0, 6, null, 2, 2, 1, 1, 'LEFT'),
|
||||
(76, 76, 0, 6, null, 4, 4, 2, 1, 'LEFT'),
|
||||
(77, 77, 0, 6, null, 0, 3, 1, 1, 'LEFT'),
|
||||
(78, 78, 0, 6, null, 3, 4, 4, 1, 'LEFT'),
|
||||
(79, 79, 0, 6, null, 0, 5, 1, 1, 'LEFT'),
|
||||
(80, 80, 0, 6, null, 0, 6, 1, 1, 'LEFT'),
|
||||
(81, 81, 0, 6, null, 0, 7, 1, 1, 'LEFT'),
|
||||
|
||||
(82, 82, 0, 6, null, 0, 8, 1, 3, 'LEFT'),
|
||||
|
||||
(85, 85, 0, 6, null, 0, 8, 1, 1, 'LEFT'),
|
||||
(86, 86, 0, 6, null, 0, 7, 1, 1, 'LEFT'),
|
||||
(87, 87, 0, 6, null, 0, 9, 1, 1, 'LEFT'),
|
||||
(88, 88, 0, 6, null, 0, 10, 1, 1, 'LEFT'),
|
||||
(89, 89, 0, 6, null, 0, 11, 1, 1, 'LEFT'),
|
||||
(90, 90, 0, 6, null, 0, 12, 1, 1, 'LEFT'),
|
||||
(91, 91, 0, 6, null, 0, 0, 5, 1, 'NONE'),
|
||||
(92, 92, 0, 6, null, 5, 0, 5, 1, 'NONE'),
|
||||
(93, 93, 0, 6, null, 0, 10, 10, 6, 'TOP'),
|
||||
(94, 94, 0, 6, null, 1, 1, 1, 1, 'LEFT'),
|
||||
(95, 95, 0, 6, null, 2, 2, 1, 1, 'LEFT'),
|
||||
(96, 96, 0, 6, null, 3, 3, 4, 1, 'LEFT'),
|
||||
(97, 97, 0, 6, null, 4, 5, 2, 1, 'LEFT'),
|
||||
(98, 98, 0, 6, null, 0, 4, 1, 1, 'LEFT'),
|
||||
(99, 99, 0, 6, null, 0, 6, 1, 1, 'LEFT'),
|
||||
(100, 100, 0, 6, null, 0, 7, 1, 1, 'LEFT'),
|
||||
|
||||
(200, 200, 0, 8, 'urlFilter', 0, 0, 3, 1, 'NONE'),
|
||||
(201, 201, 0, 8, 'urlFilter', 3, 0, 4, 1, 'NONE'),
|
||||
(202, 202, 0, 8, 'urlFilter', 0, 1, 12, 6, 'NONE'),
|
||||
(203, 203, 0, 8, 'urlFilter', 1, 1, 1, 1, 'LEFT'),
|
||||
(204, 204, 0, 8, 'urlFilter', 2, 2, 1, 1, 'LEFT'),
|
||||
(205, 205, 0, 8, 'urlFilter', 3, 3, 4, 1, 'LEFT'),
|
||||
(206, 206, 0, 8, 'urlFilter', 4, 4, 2, 1, 'LEFT'),
|
||||
|
||||
(210, 210, 0, 8, 'proxies', 0, 6, 5, 2, 'NONE'),
|
||||
(220, 220, 0, 8, 'proxies', 7, 7, 5, 7, 'TOP'),
|
||||
(221, 221, 0, 8, 'proxies', 0, 8, 6, 1, 'NONE'),
|
||||
(222, 222, 0, 8, 'proxies', 0, 10, 6, 2, 'TOP'),
|
||||
(223, 223, 0, 8, 'proxies', 0, 11, 6, 1, 'NONE'),
|
||||
|
||||
(231, 231, 0, 8, 'active', 0, 0, 1, 1, 'LEFT'),
|
||||
|
||||
(233, 233, 0, 8, 'active', 0, 0, 1, 1, 'LEFT'),
|
||||
(234, 234, 0, 8, null, 0, 1, 1, 1, 'LEFT'),
|
||||
(235, 235, 0, 8, null, 0, 2, 1, 1, 'LEFT'),
|
||||
(236, 236, 0, 8, 'active', 0, 0, 1, 1, 'LEFT'),
|
||||
(237, 237, 0, 8, null, 0, 1, 1, 1, 'LEFT'),
|
||||
(238, 238, 0, 8, null, 0, 2, 1, 1, 'LEFT'),
|
||||
(239, 239, 0, 8, null, 0, 3, 1, 1, 'LEFT'),
|
||||
(240, 240, 0, 8, null, 0, 4, 1, 1, 'LEFT'),
|
||||
(241, 241, 0, 8, null, 0, 5, 1, 1, 'LEFT'),
|
||||
(242, 242, 0, 8, 'active', 0, 0, 1, 1, 'LEFT'),
|
||||
(243, 243, 0, 8, null, 0, 1, 1, 1, 'LEFT'),
|
||||
(244, 244, 0, 8, null, 0, 2, 1, 1, 'LEFT'),
|
||||
(245, 245, 0, 8, null, 0, 3, 1, 1, 'LEFT'),
|
||||
(246, 246, 0, 8, null, 0, 4, 1, 1, 'LEFT'),
|
||||
(247, 247, 0, 8, null, 0, 5, 1, 1, 'LEFT'),
|
||||
(248, 248, 0, 8, 'active', 0, 0, 1, 1, 'LEFT'),
|
||||
(249, 249, 0, 8, null, 0, 1, 1, 1, 'LEFT'),
|
||||
(250, 250, 0, 8, null, 0, 2, 1, 1, 'LEFT'),
|
||||
(251, 251, 0, 8, null, 0, 3, 1, 1, 'LEFT'),
|
||||
(252, 252, 0, 8, null, 0, 4, 1, 1, 'LEFT'),
|
||||
(253, 253, 0, 8, null, 0, 5, 1, 1, 'LEFT'),
|
||||
(254, 254, 0, 8, 'active', 0, 0, 1, 1, 'LEFT'),
|
||||
(255, 255, 0, 8, null, 0, 1, 1, 1, 'LEFT'),
|
||||
(256, 256, 0, 8, null, 0, 2, 1, 1, 'LEFT'),
|
||||
(257, 257, 0, 8, null, 0, 3, 1, 1, 'LEFT'),
|
||||
(258, 258, 0, 8, null, 0, 4, 1, 1, 'LEFT'),
|
||||
(259, 259, 0, 8, null, 0, 5, 1, 1, 'LEFT'),
|
||||
(260, 260, 0, 8, 'active', 0, 0, 1, 1, 'LEFT'),
|
||||
(261, 261, 0, 8, null, 0, 1, 1, 1, 'LEFT'),
|
||||
(262, 262, 0, 8, null, 0, 2, 1, 1, 'LEFT'),
|
||||
(263, 263, 0, 8, null, 0, 3, 1, 1, 'LEFT'),
|
||||
(264, 264, 0, 8, null, 0, 4, 1, 1, 'LEFT'),
|
||||
(265, 265, 0, 8, null, 0, 5, 1, 1, 'LEFT'),
|
||||
|
||||
|
||||
(300, 300, 0, 9, 'servicePolicy', 0, 0, 4, 3, 'NONE'),
|
||||
(301, 301, 0, 9, 'kioskMode', 4, 0, 3, 3, 'NONE'),
|
||||
(302, 302, 0, 9, null, 0, 5, 4, 1, 'NONE'),
|
||||
(303, 303, 0, 9, null, 0, 6, 4, 1, 'NONE'),
|
||||
(304, 304, 0, 9, null, 4, 5, 3, 1, 'NONE'),
|
||||
(305, 305, 0, 9, 'logging', 0, 8, 6, 1, 'NONE'),
|
||||
(306, 306, 0, 9, 'logging', 3, 9, 4, 1, 'LEFT_SPAN'),
|
||||
(307, 307, 0, 9, 'logging', 3, 10, 4, 1, 'LEFT_SPAN'),
|
||||
(308, 308, 0, 9, 'macSettings', 7, 1, 5, 1, 'TOP'),
|
||||
(309, 309, 0, 9, 'macSettings', 7, 2, 5, 1, 'NONE'),
|
||||
(310, 310, 0, 9, 'macSettings', 7, 3, 5, 1, 'NONE'),
|
||||
(311, 311, 0, 9, 'macSettings', 7, 4, 5, 1, 'NONE'),
|
||||
(312, 312, 0, 9, 'macSettings', 7, 5, 5, 1, 'NONE'),
|
||||
(313, 313, 0, 9, 'macSettings', 7, 6, 5, 1, 'NONE'),
|
||||
(314, 314, 0, 9, 'macSettings', 7, 7, 5, 1, 'NONE'),
|
||||
(315, 315, 0, 9, 'macSettings', 7, 9, 5, 1, 'TOP'),
|
||||
(316, 316, 0, 9, 'macSettings', 7, 10, 5, 1, 'NONE'),
|
||||
|
||||
(400, 400, 0, 10, 'registry', 0, 1, 4, 1, 'NONE'),
|
||||
(401, 401, 0, 10, 'registry', 0, 2, 4, 1, 'NONE'),
|
||||
(402, 402, 0, 10, 'registry', 0, 3, 4, 1, 'NONE'),
|
||||
(403, 403, 0, 10, 'registry', 0, 4, 4, 1, 'NONE'),
|
||||
(404, 404, 0, 10, 'registry', 0, 5, 4, 1, 'NONE'),
|
||||
(405, 405, 0, 10, 'registry', 0, 6, 4, 1, 'NONE'),
|
||||
(406, 406, 0, 10, 'registry', 0, 7, 4, 1, 'NONE'),
|
||||
(407, 407, 0, 10, 'registry', 0, 8, 4, 1, 'NONE'),
|
||||
(408, 408, 0, 10, 'registry', 0, 9, 4, 1, 'NONE'),
|
||||
|
||||
(500, 500, 0, 11, 'specialKeys', 0, 1, 3, 1, 'NONE'),
|
||||
(501, 501, 0, 11, 'specialKeys', 0, 2, 3, 1, 'NONE'),
|
||||
(502, 502, 0, 11, 'specialKeys', 0, 3, 3, 1, 'NONE'),
|
||||
(503, 503, 0, 11, 'specialKeys', 0, 4, 3, 1, 'NONE'),
|
||||
(504, 504, 0, 11, 'specialKeys', 0, 5, 3, 1, 'NONE'),
|
||||
(505, 505, 0, 11, 'specialKeys', 0, 6, 3, 1, 'NONE'),
|
||||
(506, 506, 0, 11, 'specialKeys', 0, 7, 3, 1, 'NONE'),
|
||||
(507, 507, 0, 11, 'specialKeys', 0, 8, 3, 1, 'NONE'),
|
||||
(508, 508, 0, 11, 'specialKeys', 0, 9, 3, 1, 'NONE'),
|
||||
|
||||
(509, 509, 0, 11, 'functionKeys', 3, 1, 3, 1, 'NONE'),
|
||||
(510, 510, 0, 11, 'functionKeys', 3, 2, 3, 1, 'NONE'),
|
||||
(511, 511, 0, 11, 'functionKeys', 3, 3, 3, 1, 'NONE'),
|
||||
(512, 512, 0, 11, 'functionKeys', 3, 4, 3, 1, 'NONE'),
|
||||
(513, 513, 0, 11, 'functionKeys', 3, 5, 3, 1, 'NONE'),
|
||||
(514, 514, 0, 11, 'functionKeys', 3, 6, 3, 1, 'NONE'),
|
||||
(515, 515, 0, 11, 'functionKeys', 3, 7, 3, 1, 'NONE'),
|
||||
(516, 516, 0, 11, 'functionKeys', 3, 8, 3, 1, 'NONE'),
|
||||
(517, 517, 0, 11, 'functionKeys', 3, 9, 3, 1, 'NONE'),
|
||||
(518, 518, 0, 11, 'functionKeys', 3, 10, 3, 1, 'NONE'),
|
||||
(519, 519, 0, 11, 'functionKeys', 3, 11, 3, 1, 'NONE'),
|
||||
(520, 520, 0, 11, 'functionKeys', 3, 12, 3, 1, 'NONE')
|
||||
|
||||
;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
INSERT IGNORE INTO configuration_node VALUES
|
||||
(1, 1, 0, 'super-admin', 'test', null, 'EXAM_CONFIG', 'READY_TO_USE')
|
||||
;
|
||||
|
||||
INSERT IGNORE INTO configuration VALUES
|
||||
(1, 1, 1, 'v0', '2019-07-02 12:59:32', 0),
|
||||
(2, 1, 1, null, null, 1)
|
||||
;
|
||||
|
||||
INSERT IGNORE INTO configuration_value VALUES
|
||||
(1,1,1,1,0,NULL),
|
||||
(2,1,1,2,0,'true'),
|
||||
(3,1,1,3,0,'false'),
|
||||
(4,1,1,4,0,NULL),
|
||||
(5,1,1,5,0,'2'),
|
||||
(6,1,1,6,0,'10'),
|
||||
(7,1,1,7,0,'5'),
|
||||
(8,1,1,8,0,'0'),
|
||||
(9,1,1,9,0,'false'),
|
||||
(10,1,1,10,0,'100%'),
|
||||
(11,1,1,11,0,'100%'),
|
||||
(12,1,1,12,0,'1'),
|
||||
(13,1,1,13,0,'false'),
|
||||
(14,1,1,14,0,'false'),
|
||||
(15,1,1,15,0,'false'),
|
||||
(16,1,1,16,0,'true'),
|
||||
(17,1,1,17,0,'40'),
|
||||
(18,1,1,18,0,'true'),
|
||||
(19,1,1,19,0,'true'),
|
||||
(20,1,1,20,0,'false'),
|
||||
(21,1,1,21,0,'true'),
|
||||
(22,1,1,22,0,'true'),
|
||||
(23,1,1,23,0,'0'),
|
||||
(24,1,1,24,0,'false'),
|
||||
(25,1,1,25,0,'false'),
|
||||
(26,1,1,26,0,'false'),
|
||||
(27,1,1,27,0,'25'),
|
||||
(28,1,1,28,0,'false'),
|
||||
(29,1,1,29,0,'false'),
|
||||
(30,1,1,30,0,'da-DK,en-AU,en-GB,en-US,es-ES,fr-FR,pt-PT,sv-SE,sv-FI'),
|
||||
(31,1,1,31,0,'2'),
|
||||
(32,1,1,32,0,'false'),
|
||||
(33,1,1,33,0,'100%'),
|
||||
(34,1,1,34,0,'100%'),
|
||||
(35,1,1,35,0,'2'),
|
||||
(36,1,1,36,0,'true'),
|
||||
(37,1,1,37,0,'true'),
|
||||
(38,1,1,38,0,'false'),
|
||||
(39,1,1,39,0,'false'),
|
||||
(40,1,1,40,0,'false'),
|
||||
(41,1,1,41,0,'false'),
|
||||
(42,1,1,42,0,'false'),
|
||||
(43,1,1,43,0,'true'),
|
||||
(44,1,1,44,0,'true'),
|
||||
(45,1,1,45,0,'true'),
|
||||
(46,1,1,46,0,'true'),
|
||||
(47,1,1,47,0,'false'),
|
||||
(48,1,1,48,0,'false'),
|
||||
(49,1,1,49,0,'false'),
|
||||
(50,1,1,50,0,NULL),
|
||||
(51,1,1,51,0,'0'),
|
||||
(52,1,1,52,0,NULL),
|
||||
(53,1,1,53,0,'0'),
|
||||
(54,1,1,54,0,NULL),
|
||||
(55,1,1,55,0,'0'),
|
||||
(56,1,1,56,0,NULL),
|
||||
(57,1,1,57,0,'true'),
|
||||
(58,1,1,58,0,NULL),
|
||||
(59,1,1,59,0,'true'),
|
||||
(60,1,1,60,0,NULL),
|
||||
(61,1,1,61,0,NULL),
|
||||
(62,1,1,62,0,'false'),
|
||||
(63,1,1,63,0,'0'),
|
||||
(64,1,1,64,0,'true'),
|
||||
(65,1,1,65,0,'true'),
|
||||
(66,1,1,66,0,'true'),
|
||||
(67,1,1,67,0,NULL),
|
||||
(68,1,1,68,0,'true'),
|
||||
(69,1,1,69,0,'false'),
|
||||
(70,1,1,70,0,NULL),
|
||||
(71,1,1,71,0,NULL),
|
||||
(72,1,1,72,0,'true'),
|
||||
(73,1,1,73,0,NULL),
|
||||
(74,1,1,91,0,'false'),
|
||||
(75,1,1,92,0,'false'),
|
||||
(76,1,1,93,0,NULL),
|
||||
(77,1,1,200,0,'false'),
|
||||
(78,1,1,201,0,'false'),
|
||||
(79,1,1,202,0,NULL),
|
||||
(80,1,1,210,0,'0'),
|
||||
(81,1,1,220,0,NULL),
|
||||
(82,1,1,221,0,'false'),
|
||||
(83,1,1,222,0,NULL),
|
||||
(84,1,1,223,0,'true'),
|
||||
(85,1,1,231,0,'false'),
|
||||
(86,1,1,233,0,'false'),
|
||||
(87,1,1,234,0,NULL),
|
||||
(88,1,1,235,0,NULL),
|
||||
(89,1,1,236,0,'false'),
|
||||
(90,1,1,237,0,NULL),
|
||||
(91,1,1,238,0,'80'),
|
||||
(92,1,1,239,0,'false'),
|
||||
(93,1,1,240,0,NULL),
|
||||
(94,1,1,241,0,NULL),
|
||||
(95,1,1,242,0,'false'),
|
||||
(96,1,1,243,0,NULL),
|
||||
(97,1,1,244,0,'443'),
|
||||
(98,1,1,245,0,'false'),
|
||||
(99,1,1,246,0,NULL),
|
||||
(100,1,1,247,0,NULL),
|
||||
(101,1,1,248,0,'false'),
|
||||
(102,1,1,249,0,NULL),
|
||||
(103,1,1,250,0,'21'),
|
||||
(104,1,1,251,0,'false'),
|
||||
(105,1,1,252,0,NULL),
|
||||
(106,1,1,253,0,NULL),
|
||||
(107,1,1,254,0,'false'),
|
||||
(108,1,1,255,0,NULL),
|
||||
(109,1,1,256,0,'1080'),
|
||||
(110,1,1,257,0,'false'),
|
||||
(111,1,1,258,0,NULL),
|
||||
(112,1,1,259,0,NULL),
|
||||
(113,1,1,260,0,'false'),
|
||||
(114,1,1,261,0,NULL),
|
||||
(115,1,1,262,0,'1080'),
|
||||
(116,1,1,263,0,'false'),
|
||||
(117,1,1,264,0,NULL),
|
||||
(118,1,1,265,0,NULL),
|
||||
(119,1,1,300,0,'2'),
|
||||
(120,1,1,301,0,'0'),
|
||||
(121,1,1,302,0,'false'),
|
||||
(122,1,1,303,0,'false'),
|
||||
(123,1,1,304,0,'true'),
|
||||
(124,1,1,305,0,'false'),
|
||||
(125,1,1,306,0,''),
|
||||
(126,1,1,307,0,'~/Documents'),
|
||||
(127,1,1,308,0,'0'),
|
||||
(128,1,1,309,0,'true'),
|
||||
(129,1,1,310,0,'true'),
|
||||
(130,1,1,311,0,'false'),
|
||||
(131,1,1,312,0,'false'),
|
||||
(132,1,1,313,0,'true'),
|
||||
(133,1,1,314,0,'false'),
|
||||
(134,1,1,315,0,'1'),
|
||||
(135,1,1,316,0,'true'),
|
||||
(136,1,1,400,0,'false'),
|
||||
(137,1,1,401,0,'false'),
|
||||
(138,1,1,402,0,'false'),
|
||||
(139,1,1,403,0,'false'),
|
||||
(140,1,1,404,0,'false'),
|
||||
(141,1,1,405,0,'false'),
|
||||
(142,1,1,406,0,'false'),
|
||||
(143,1,1,407,0,'false'),
|
||||
(144,1,1,408,0,'false'),
|
||||
(145,1,1,500,0,'false'),
|
||||
(146,1,1,501,0,'false'),
|
||||
(147,1,1,502,0,'false'),
|
||||
(148,1,1,503,0,'false'),
|
||||
(149,1,1,504,0,'true'),
|
||||
(150,1,1,505,0,'false'),
|
||||
(151,1,1,506,0,'false'),
|
||||
(152,1,1,507,0,'false'),
|
||||
(153,1,1,508,0,'false'),
|
||||
(154,1,1,509,0,'false'),
|
||||
(155,1,1,510,0,'false'),
|
||||
(156,1,1,511,0,'false'),
|
||||
(157,1,1,512,0,'false'),
|
||||
(158,1,1,513,0,'false'),
|
||||
(159,1,1,514,0,'false'),
|
||||
(160,1,1,515,0,'false'),
|
||||
(161,1,1,516,0,'false'),
|
||||
(162,1,1,517,0,'false'),
|
||||
(163,1,1,518,0,'false'),
|
||||
(164,1,1,519,0,'false'),
|
||||
(165,1,1,520,0,'false'),
|
||||
(166,1,1,1000,0,'SEB_Server_0.3.0'),
|
||||
(167,1,1,1001,0,'0'),
|
||||
(168,1,2,1,0,NULL),
|
||||
(169,1,2,2,0,'true'),
|
||||
(170,1,2,3,0,'false'),
|
||||
(171,1,2,4,0,NULL),
|
||||
(172,1,2,5,0,'2'),
|
||||
(173,1,2,6,0,'10'),
|
||||
(174,1,2,7,0,'5'),
|
||||
(175,1,2,8,0,'0'),
|
||||
(176,1,2,9,0,'false'),
|
||||
(177,1,2,10,0,'100%'),
|
||||
(178,1,2,11,0,'100%'),
|
||||
(179,1,2,12,0,'1'),
|
||||
(180,1,2,13,0,'false'),
|
||||
(181,1,2,14,0,'false'),
|
||||
(182,1,2,15,0,'false'),
|
||||
(183,1,2,16,0,'true'),
|
||||
(184,1,2,17,0,'40'),
|
||||
(185,1,2,18,0,'true'),
|
||||
(186,1,2,19,0,'true'),
|
||||
(187,1,2,20,0,'false'),
|
||||
(188,1,2,21,0,'true'),
|
||||
(189,1,2,22,0,'true'),
|
||||
(190,1,2,23,0,'0'),
|
||||
(191,1,2,24,0,'false'),
|
||||
(192,1,2,25,0,'false'),
|
||||
(193,1,2,26,0,'false'),
|
||||
(194,1,2,27,0,'25'),
|
||||
(195,1,2,28,0,'false'),
|
||||
(196,1,2,29,0,'false'),
|
||||
(197,1,2,30,0,'da-DK,en-AU,en-GB,en-US,es-ES,fr-FR,pt-PT,sv-SE,sv-FI'),
|
||||
(198,1,2,31,0,'2'),
|
||||
(199,1,2,32,0,'false'),
|
||||
(200,1,2,33,0,'100%'),
|
||||
(201,1,2,34,0,'100%'),
|
||||
(202,1,2,35,0,'2'),
|
||||
(203,1,2,36,0,'true'),
|
||||
(204,1,2,37,0,'true'),
|
||||
(205,1,2,38,0,'false'),
|
||||
(206,1,2,39,0,'false'),
|
||||
(207,1,2,40,0,'false'),
|
||||
(208,1,2,41,0,'false'),
|
||||
(209,1,2,42,0,'false'),
|
||||
(210,1,2,43,0,'true'),
|
||||
(211,1,2,44,0,'true'),
|
||||
(212,1,2,45,0,'true'),
|
||||
(213,1,2,46,0,'true'),
|
||||
(214,1,2,47,0,'false'),
|
||||
(215,1,2,48,0,'false'),
|
||||
(216,1,2,49,0,'false'),
|
||||
(217,1,2,50,0,NULL),
|
||||
(218,1,2,51,0,'0'),
|
||||
(219,1,2,52,0,NULL),
|
||||
(220,1,2,53,0,'0'),
|
||||
(221,1,2,54,0,NULL),
|
||||
(222,1,2,55,0,'0'),
|
||||
(223,1,2,56,0,NULL),
|
||||
(224,1,2,57,0,'true'),
|
||||
(225,1,2,58,0,NULL),
|
||||
(226,1,2,59,0,'true'),
|
||||
(227,1,2,60,0,NULL),
|
||||
(228,1,2,61,0,NULL),
|
||||
(229,1,2,62,0,'false'),
|
||||
(230,1,2,63,0,'0'),
|
||||
(231,1,2,64,0,'true'),
|
||||
(232,1,2,65,0,'true'),
|
||||
(233,1,2,66,0,'true'),
|
||||
(234,1,2,67,0,NULL),
|
||||
(235,1,2,68,0,'true'),
|
||||
(236,1,2,69,0,'false'),
|
||||
(237,1,2,70,0,NULL),
|
||||
(238,1,2,71,0,NULL),
|
||||
(239,1,2,72,0,'true'),
|
||||
(240,1,2,73,0,NULL),
|
||||
(241,1,2,91,0,'false'),
|
||||
(242,1,2,92,0,'false'),
|
||||
(243,1,2,93,0,NULL),
|
||||
(244,1,2,200,0,'false'),
|
||||
(245,1,2,201,0,'false'),
|
||||
(246,1,2,202,0,NULL),
|
||||
(247,1,2,210,0,'0'),
|
||||
(248,1,2,220,0,NULL),
|
||||
(249,1,2,221,0,'false'),
|
||||
(250,1,2,222,0,NULL),
|
||||
(251,1,2,223,0,'true'),
|
||||
(252,1,2,231,0,'false'),
|
||||
(253,1,2,233,0,'false'),
|
||||
(254,1,2,234,0,NULL),
|
||||
(255,1,2,235,0,NULL),
|
||||
(256,1,2,236,0,'false'),
|
||||
(257,1,2,237,0,NULL),
|
||||
(258,1,2,238,0,'80'),
|
||||
(259,1,2,239,0,'false'),
|
||||
(260,1,2,240,0,NULL),
|
||||
(261,1,2,241,0,NULL),
|
||||
(262,1,2,242,0,'false'),
|
||||
(263,1,2,243,0,NULL),
|
||||
(264,1,2,244,0,'443'),
|
||||
(265,1,2,245,0,'false'),
|
||||
(266,1,2,246,0,NULL),
|
||||
(267,1,2,247,0,NULL),
|
||||
(268,1,2,248,0,'false'),
|
||||
(269,1,2,249,0,NULL),
|
||||
(270,1,2,250,0,'21'),
|
||||
(271,1,2,251,0,'false'),
|
||||
(272,1,2,252,0,NULL),
|
||||
(273,1,2,253,0,NULL),
|
||||
(274,1,2,254,0,'false'),
|
||||
(275,1,2,255,0,NULL),
|
||||
(276,1,2,256,0,'1080'),
|
||||
(277,1,2,257,0,'false'),
|
||||
(278,1,2,258,0,NULL),
|
||||
(279,1,2,259,0,NULL),
|
||||
(280,1,2,260,0,'false'),
|
||||
(281,1,2,261,0,NULL),
|
||||
(282,1,2,262,0,'1080'),
|
||||
(283,1,2,263,0,'false'),
|
||||
(284,1,2,264,0,NULL),
|
||||
(285,1,2,265,0,NULL),
|
||||
(286,1,2,300,0,'2'),
|
||||
(287,1,2,301,0,'0'),
|
||||
(288,1,2,302,0,'false'),
|
||||
(289,1,2,303,0,'false'),
|
||||
(290,1,2,304,0,'true'),
|
||||
(291,1,2,305,0,'false'),
|
||||
(292,1,2,306,0,''),
|
||||
(293,1,2,307,0,'~/Documents'),
|
||||
(294,1,2,308,0,'0'),
|
||||
(295,1,2,309,0,'true'),
|
||||
(296,1,2,310,0,'true'),
|
||||
(297,1,2,311,0,'false'),
|
||||
(298,1,2,312,0,'false'),
|
||||
(299,1,2,313,0,'true'),
|
||||
(300,1,2,314,0,'false'),
|
||||
(301,1,2,315,0,'1'),
|
||||
(302,1,2,316,0,'true'),
|
||||
(303,1,2,400,0,'false'),
|
||||
(304,1,2,401,0,'false'),
|
||||
(305,1,2,402,0,'false'),
|
||||
(306,1,2,403,0,'false'),
|
||||
(307,1,2,404,0,'false'),
|
||||
(308,1,2,405,0,'false'),
|
||||
(309,1,2,406,0,'false'),
|
||||
(310,1,2,407,0,'false'),
|
||||
(311,1,2,408,0,'false'),
|
||||
(312,1,2,500,0,'false'),
|
||||
(313,1,2,501,0,'false'),
|
||||
(314,1,2,502,0,'false'),
|
||||
(315,1,2,503,0,'false'),
|
||||
(316,1,2,504,0,'true'),
|
||||
(317,1,2,505,0,'false'),
|
||||
(318,1,2,506,0,'false'),
|
||||
(319,1,2,507,0,'false'),
|
||||
(320,1,2,508,0,'false'),
|
||||
(321,1,2,509,0,'false'),
|
||||
(322,1,2,510,0,'false'),
|
||||
(323,1,2,511,0,'false'),
|
||||
(324,1,2,512,0,'false'),
|
||||
(325,1,2,513,0,'false'),
|
||||
(326,1,2,514,0,'false'),
|
||||
(327,1,2,515,0,'false'),
|
||||
(328,1,2,516,0,'false'),
|
||||
(329,1,2,517,0,'false'),
|
||||
(330,1,2,518,0,'false'),
|
||||
(331,1,2,519,0,'false'),
|
||||
(332,1,2,520,0,'false'),
|
||||
(333,1,2,1000,0,'SEB_Server_0.3.0'),
|
||||
(334,1,2,1001,0,'0')
|
||||
;
|
||||
|
||||
INSERT IGNORE INTO exam_configuration_map VALUES
|
||||
(1, 1, 2, 1, null, null)
|
||||
;
|
||||
|
|
@ -84,21 +84,26 @@ DROP TABLE IF EXISTS `client_connection` ;
|
|||
|
||||
CREATE TABLE IF NOT EXISTS `client_connection` (
|
||||
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`institution_id` BIGINT UNSIGNED NOT NULL,
|
||||
`exam_id` BIGINT UNSIGNED NULL,
|
||||
`status` VARCHAR(45) NOT NULL,
|
||||
`connection_token` VARCHAR(255) NOT NULL,
|
||||
`user_name` VARCHAR(255) NOT NULL,
|
||||
`VDI` BIT(1) NOT NULL,
|
||||
`exam_user_session_identifer` VARCHAR(255) NULL,
|
||||
`client_address` VARCHAR(45) NOT NULL,
|
||||
`virtual_client_address` VARCHAR(45) NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `connection_exam_ref_idx` (`exam_id` ASC),
|
||||
INDEX `clientConnectionInstitutionRef_idx` (`institution_id` ASC),
|
||||
CONSTRAINT `clientConnectionExamRef`
|
||||
FOREIGN KEY (`exam_id`)
|
||||
REFERENCES `exam` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION)
|
||||
;
|
||||
ON UPDATE NO ACTION,
|
||||
CONSTRAINT `clientConnectionInstitutionRef`
|
||||
FOREIGN KEY (`institution_id`)
|
||||
REFERENCES `institution` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION);
|
||||
|
||||
|
||||
-- -----------------------------------------------------
|
||||
|
|
Loading…
Reference in a new issue