Merge branch 'downgrade_exam_config' into dev-1.5
This commit is contained in:
commit
b1bd21c424
7 changed files with 180 additions and 14 deletions
|
@ -8,14 +8,13 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui.service.examconfig.impl;
|
package ch.ethz.seb.sebserver.gui.service.examconfig.impl;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -23,6 +22,7 @@ import org.slf4j.LoggerFactory;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
|
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
|
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
|
||||||
public class AttributeMapping {
|
public class AttributeMapping {
|
||||||
|
|
||||||
|
@ -49,7 +49,6 @@ public class AttributeMapping {
|
||||||
Objects.requireNonNull(orientations);
|
Objects.requireNonNull(orientations);
|
||||||
|
|
||||||
this.templateId = templateId;
|
this.templateId = templateId;
|
||||||
|
|
||||||
this.orientationAttributeMapping = Utils.immutableMapOf(orientations
|
this.orientationAttributeMapping = Utils.immutableMapOf(orientations
|
||||||
.stream()
|
.stream()
|
||||||
.collect(Collectors.toMap(
|
.collect(Collectors.toMap(
|
||||||
|
|
|
@ -60,11 +60,16 @@ public class DBIntegrityChecker {
|
||||||
|
|
||||||
final Result<String> applyCheck = dbIntegrityCheck.applyCheck(this.tryFix);
|
final Result<String> applyCheck = dbIntegrityCheck.applyCheck(this.tryFix);
|
||||||
if (applyCheck.hasError()) {
|
if (applyCheck.hasError()) {
|
||||||
|
if (applyCheck.getError() instanceof WebserviceInitException) {
|
||||||
|
throw applyCheck.getError();
|
||||||
|
}
|
||||||
SEBServerInit.INIT_LOGGER.info("--------> Unexpected Error: {}", applyCheck.getError().getMessage());
|
SEBServerInit.INIT_LOGGER.info("--------> Unexpected Error: {}", applyCheck.getError().getMessage());
|
||||||
} else {
|
} else {
|
||||||
SEBServerInit.INIT_LOGGER.info("--------> Result: {}", applyCheck.get());
|
SEBServerInit.INIT_LOGGER.info("--------> Result: {}", applyCheck.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} catch (final WebserviceInitException initE) {
|
||||||
|
throw initE;
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
log.error("Unexpected error while trying to apply data base integrity check: {}", dbIntegrityCheck);
|
log.error("Unexpected error while trying to apply data base integrity check: {}", dbIntegrityCheck);
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,10 +99,10 @@ public class WebserviceInit implements ApplicationListener<ApplicationReadyEvent
|
||||||
|
|
||||||
this.applicationEventPublisher.publishEvent(new SEBServerInitEvent(this));
|
this.applicationEventPublisher.publishEvent(new SEBServerInitEvent(this));
|
||||||
|
|
||||||
// Run the data base integrity checks and fixes if configured
|
// Run the database integrity checks and fixes if configured
|
||||||
this.dbIntegrityChecker.checkIntegrity();
|
this.dbIntegrityChecker.checkIntegrity();
|
||||||
|
|
||||||
// Create an initial admin account if requested and not already in the data-base
|
// Create an initial admin account if requested and not already in the database
|
||||||
this.adminUserInitializer.initAdminAccount();
|
this.adminUserInitializer.initAdminAccount();
|
||||||
|
|
||||||
SEBServerInit.INIT_LOGGER.info("----> *********************************************************");
|
SEBServerInit.INIT_LOGGER.info("----> *********************************************************");
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package ch.ethz.seb.sebserver.webservice;
|
||||||
|
|
||||||
|
public class WebserviceInitException extends RuntimeException {
|
||||||
|
|
||||||
|
public WebserviceInitException(final String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WebserviceInitException(final String message, final Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,152 @@
|
||||||
|
package ch.ethz.seb.sebserver.webservice.datalayer.checks;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.DBIntegrityCheck;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.WebserviceInitException;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.*;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationAttributeRecord;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.OrientationRecord;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.mybatis.dynamic.sql.SqlBuilder;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
@Component
|
||||||
|
@WebServiceProfile
|
||||||
|
public class DowngradeSEBSettingsCheck implements DBIntegrityCheck {
|
||||||
|
|
||||||
|
public static final Logger INIT_LOGGER = LoggerFactory.getLogger("ch.ethz.seb.SEB_SERVER_INIT");
|
||||||
|
|
||||||
|
private final OrientationRecordMapper orientationRecordMapper;
|
||||||
|
private final ConfigurationAttributeRecordMapper configurationAttributeRecordMapper;
|
||||||
|
private final DataSource dataSource;
|
||||||
|
private final String schemaName;
|
||||||
|
private final Long lastMigrationVersion = 22L;
|
||||||
|
private final String versionAttributeIds =
|
||||||
|
"1,2,3,4,8,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,42,43,44,45,46,47,48," +
|
||||||
|
"50,51,52,53,54,55,56,57,58,59,60,61,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,81,82,85,86,87,88," +
|
||||||
|
"89,90,91,92,93,94,95,96,97,98,99,100,200,201,202,203,204,205,206,210,220,221,222,223,231,233,234,235,236," +
|
||||||
|
"237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262," +
|
||||||
|
"263,264,265,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322," +
|
||||||
|
"400,401,402,403,404,405,406,407,408,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516," +
|
||||||
|
"517,518,519,520,804,812,900,901,904,919,928,940,941,942,950,951,952,953,960,961,970,971,972,973,974,975," +
|
||||||
|
"1100,1101,1102,1103,1104,1105,1106,1108,1116,1120,1121,1122,1123,1124,1125,1129,1130,1131,1132,1133,1500," +
|
||||||
|
"1501,1502,1503,1504,1505,1506,1508,1516,1530,1531,1532,1533,1551,1578,";
|
||||||
|
private final boolean fixDowngrade;
|
||||||
|
|
||||||
|
public DowngradeSEBSettingsCheck(
|
||||||
|
final OrientationRecordMapper orientationRecordMapper,
|
||||||
|
final ConfigurationAttributeRecordMapper configurationAttributeRecordMapper,
|
||||||
|
final DataSource dataSource,
|
||||||
|
@Value("${sebserver.init.database.integrity.fix.downgrade:false}") final boolean fixDowngrade,
|
||||||
|
@Value("${sebserver.init.database.integrity.check.schema:SEBServer}") final String schemaName) {
|
||||||
|
|
||||||
|
this.orientationRecordMapper = orientationRecordMapper;
|
||||||
|
this.configurationAttributeRecordMapper = configurationAttributeRecordMapper;
|
||||||
|
this.dataSource = dataSource;
|
||||||
|
this.fixDowngrade = fixDowngrade;
|
||||||
|
this.schemaName = schemaName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "DowngradeSEBSettingsCheck";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String description() {
|
||||||
|
return "Check if there are additional SEB Settings orientations within the database that do not match the once for the current SEB Server version.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<String> applyCheck(final boolean tryFix) {
|
||||||
|
return Result.tryCatch(() -> {
|
||||||
|
|
||||||
|
final String[] split = StringUtils.split(versionAttributeIds, Constants.LIST_SEPARATOR_CHAR);
|
||||||
|
final List<Long> config_attrs_ids = Arrays.stream(split).map(s -> {
|
||||||
|
try {
|
||||||
|
return Long.valueOf(s.trim());
|
||||||
|
} catch (final Exception e) {
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
final List<Long> attributeIds = orientationRecordMapper.selectByExample()
|
||||||
|
.where(OrientationRecordDynamicSqlSupport.templateId, SqlBuilder.isEqualTo(0L))
|
||||||
|
.and(OrientationRecordDynamicSqlSupport.configAttributeId, SqlBuilder.isNotIn(config_attrs_ids))
|
||||||
|
.build()
|
||||||
|
.execute()
|
||||||
|
.stream()
|
||||||
|
.map(OrientationRecord::getConfigAttributeId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (attributeIds.isEmpty()) {
|
||||||
|
return "No additional SEB Settings orientations for downgrading found.";
|
||||||
|
}
|
||||||
|
|
||||||
|
final Set<String> allNames = configurationAttributeRecordMapper
|
||||||
|
.selectByExample()
|
||||||
|
.where(ConfigurationAttributeRecordDynamicSqlSupport.id, SqlBuilder.isIn(attributeIds))
|
||||||
|
.build()
|
||||||
|
.execute()
|
||||||
|
.stream()
|
||||||
|
.map(ConfigurationAttributeRecord::getName)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
if (!fixDowngrade) {
|
||||||
|
INIT_LOGGER.error(" ---> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||||
|
INIT_LOGGER.error(" ---> !!! Detected a Database version integrity violation, probably due to SEB Server version downgrade.");
|
||||||
|
INIT_LOGGER.error(" ---> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||||
|
INIT_LOGGER.error(" ---> !!!! Please check the following correction and set 'sebserver.init.database.integrity.fix.downgrade'");
|
||||||
|
INIT_LOGGER.error(" ---> !!!! to true to apply repair with next startup. Then SEB Server will apply the repair task");
|
||||||
|
INIT_LOGGER.error(" ---> !!!! After successfully repair you can set 'sebserver.init.database.integrity.fix.downgrade' back to false ");
|
||||||
|
INIT_LOGGER.error(" ---> !!!! NOTE: Repair will delete the following SEB Settings orientation for Exam Configuration default Views");
|
||||||
|
INIT_LOGGER.error(" ---> !!!! Exam Configurations built from Configuration Template will stay the same and might have incorrect View Tabs");
|
||||||
|
INIT_LOGGER.error(" ---> !!!! Repair will remove following SEB Settings from default view:\n {}", allNames);
|
||||||
|
INIT_LOGGER.error(" ---> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||||
|
throw new WebserviceInitException("Detected a Database version integrity violation, probably due to SEB Server version downgrade. See logs above");
|
||||||
|
//return "Downgrade SEB Settings correction would delete the following SEB Settings: " + allNames;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
final Integer deletedOrientation = orientationRecordMapper
|
||||||
|
.deleteByExample()
|
||||||
|
.where(OrientationRecordDynamicSqlSupport.configAttributeId, SqlBuilder.isIn(attributeIds))
|
||||||
|
.and(OrientationRecordDynamicSqlSupport.templateId, SqlBuilder.isEqualTo(0L))
|
||||||
|
.build()
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
INIT_LOGGER.info(" ---> Deleted {} entries from table orientation", deletedOrientation);
|
||||||
|
|
||||||
|
INIT_LOGGER.info(" ---> Try delete migration task until this version...");
|
||||||
|
|
||||||
|
final Connection connection = this.dataSource.getConnection();
|
||||||
|
final PreparedStatement prepareStatement = connection.prepareStatement(
|
||||||
|
"DELETE FROM "+ schemaName +".flyway_schema_history WHERE version > " + lastMigrationVersion);
|
||||||
|
prepareStatement.execute();
|
||||||
|
|
||||||
|
INIT_LOGGER.info(" ---> Deleted {} entries from table flyway_schema_history", deletedOrientation);
|
||||||
|
|
||||||
|
return "Successfully deleted SEB Settings attributes: " + allNames;
|
||||||
|
} catch (final Exception e) {
|
||||||
|
INIT_LOGGER.error("Failed to delete SEB Settings attributes: ", e);
|
||||||
|
return "Failed to delete SEB Settings attributes: " + allNames;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,11 +10,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl;
|
||||||
|
|
||||||
import static org.mybatis.dynamic.sql.SqlBuilder.isIn;
|
import static org.mybatis.dynamic.sql.SqlBuilder.isIn;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
|
@ -61,4 +61,6 @@ springdoc.swagger-ui.enabled=true
|
||||||
management.server.port=${server.port}
|
management.server.port=${server.port}
|
||||||
management.endpoints.web.base-path=/management
|
management.endpoints.web.base-path=/management
|
||||||
management.endpoints.web.exposure.include=logfile,loggers,jolokia
|
management.endpoints.web.exposure.include=logfile,loggers,jolokia
|
||||||
management.endpoints.web.path-mapping.jolokia=jmx
|
management.endpoints.web.path-mapping.jolokia=jmx
|
||||||
|
|
||||||
|
sebserver.init.database.integrity.fix.downgrade=false
|
Loading…
Reference in a new issue