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;
 | 
			
		||||
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import java.util.function.Function;
 | 
			
		||||
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.slf4j.Logger;
 | 
			
		||||
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.Orientation;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
 | 
			
		||||
import org.springframework.core.io.ClassPathResource;
 | 
			
		||||
 | 
			
		||||
public class AttributeMapping {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -49,7 +49,6 @@ public class AttributeMapping {
 | 
			
		|||
        Objects.requireNonNull(orientations);
 | 
			
		||||
 | 
			
		||||
        this.templateId = templateId;
 | 
			
		||||
 | 
			
		||||
        this.orientationAttributeMapping = Utils.immutableMapOf(orientations
 | 
			
		||||
                .stream()
 | 
			
		||||
                .collect(Collectors.toMap(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,11 +60,16 @@ public class DBIntegrityChecker {
 | 
			
		|||
 | 
			
		||||
            final Result<String> applyCheck = dbIntegrityCheck.applyCheck(this.tryFix);
 | 
			
		||||
            if (applyCheck.hasError()) {
 | 
			
		||||
                if (applyCheck.getError() instanceof  WebserviceInitException) {
 | 
			
		||||
                    throw applyCheck.getError();
 | 
			
		||||
                }
 | 
			
		||||
                SEBServerInit.INIT_LOGGER.info("--------> Unexpected Error: {}", applyCheck.getError().getMessage());
 | 
			
		||||
            } else {
 | 
			
		||||
                SEBServerInit.INIT_LOGGER.info("--------> Result: {}", applyCheck.get());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } catch (final WebserviceInitException initE) {
 | 
			
		||||
            throw initE;
 | 
			
		||||
        } catch (final Exception e) {
 | 
			
		||||
            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));
 | 
			
		||||
 | 
			
		||||
        // Run the data base integrity checks and fixes if configured
 | 
			
		||||
        // Run the database integrity checks and fixes if configured
 | 
			
		||||
        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();
 | 
			
		||||
 | 
			
		||||
        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 java.util.ArrayList;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import java.util.function.Predicate;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,3 +62,5 @@ management.server.port=${server.port}
 | 
			
		|||
management.endpoints.web.base-path=/management
 | 
			
		||||
management.endpoints.web.exposure.include=logfile,loggers,jolokia
 | 
			
		||||
management.endpoints.web.path-mapping.jolokia=jmx
 | 
			
		||||
 | 
			
		||||
sebserver.init.database.integrity.fix.downgrade=false
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue