Search in sources :

Example 1 with InvalidModule

use of com.infiniteautomation.mango.rest.latest.model.modules.UpgradeUploadResult.InvalidModule in project ma-modules-public by infiniteautomation.

the class ModulesRestController method uploadUpgrades.

@PreAuthorize("isAdmin()")
@ApiOperation(value = "Upload upgrade zip bundle, to be installed on restart", notes = "The bundle can be downloaded from the Mango Store")
@RequestMapping(method = RequestMethod.POST, value = "/upload-upgrades")
public UpgradeUploadResult uploadUpgrades(@ApiParam(value = "Perform Backup first", required = false, defaultValue = "false", allowMultiple = false) @RequestParam(required = false, defaultValue = "false") boolean backup, @ApiParam(value = "Restart after upload completes", required = false, defaultValue = "false", allowMultiple = false) @RequestParam(required = false, defaultValue = "false") boolean restart, MultipartHttpServletRequest multipartRequest) throws IOException {
    if (env.getProperty("store.disableUpgrades", Boolean.class, false)) {
        throw new FeatureDisabledException(new TranslatableMessage("modules.error.upgradesDisabled"));
    }
    synchronized (UPLOAD_UPGRADE_LOCK) {
        if (UPLOAD_UPGRADE_IN_PROGRESS == null) {
            UPLOAD_UPGRADE_IN_PROGRESS = new Object();
        } else {
            throw new BadRequestException(new TranslatableMessage("rest.error.upgradeUploadInProgress"));
        }
    }
    UpgradeUploadResult result = new UpgradeUploadResult();
    try {
        if (backup) {
            // Do the backups. They run async, so this returns immediately. The shutdown will
            // wait for the
            // background processes to finish though.
            BackupWorkItem.queueBackup(SystemSettingsDao.getInstance().getValue(SystemSettingsDao.BACKUP_FILE_LOCATION));
            DatabaseBackupWorkItem.queueBackup(SystemSettingsDao.getInstance().getValue(SystemSettingsDao.DATABASE_BACKUP_FILE_LOCATION));
        }
        List<MultipartFile> files = new ArrayList<>();
        MultiValueMap<String, MultipartFile> filemap = multipartRequest.getMultiFileMap();
        for (String nameField : filemap.keySet()) {
            files.addAll(filemap.get(nameField));
        }
        // Validate the zip
        if (files.size() == 0)
            throw new BadRequestException(new TranslatableMessage("rest.error.noFileProvided"));
        // Create the temp directory into which to download, if necessary.
        Path tempDir = Common.getTempPath().resolve(ModuleUtils.DOWNLOAD_DIR);
        Files.createDirectories(tempDir);
        // Delete anything that is currently the temp directory.
        FileUtils.cleanDirectory(tempDir.toFile());
        try {
            // Save the upload(s) to the temp dir
            for (MultipartFile file : files) {
                Path newFile = tempDir.resolve(file.getOriginalFilename());
                try (InputStream is = file.getInputStream()) {
                    Files.copy(is, newFile);
                }
            }
            List<Path> potentialUpgrades = Files.list(tempDir).filter(p -> p.toString().endsWith(".zip")).collect(Collectors.toList());
            List<String> upgraded = new ArrayList<>();
            List<String> unsigned = new ArrayList<>();
            boolean developmentMode = env.getProperty("development.enabled", Boolean.class, false);
            for (Path file : potentialUpgrades) {
                boolean core = false;
                boolean hasWebModules = false;
                // Test to see if it is a core or a bundle of only zips or many zip files
                try (ZipInputStream is = new ZipInputStream(Files.newInputStream(file))) {
                    ZipEntry entry = is.getNextEntry();
                    if (entry == null) {
                        // Not a zip file or empty, either way we don't care
                        throw new BadRequestException(new TranslatableMessage("rest.error.badUpgradeFile"));
                    } else {
                        do {
                            String entryName = entry.getName();
                            if ("release.signed".equals(entryName) || "release.properties".equals(entryName)) {
                                if (!developmentMode && "release.properties".equals(entryName)) {
                                    throw new BadRequestException(new TranslatableMessage("modules.unsigned.core.development"));
                                }
                                core = true;
                                break;
                            } else if (entry.getName().startsWith(WEB_MODULE_PREFIX)) {
                                hasWebModules = true;
                            }
                        } while ((entry = is.getNextEntry()) != null);
                    }
                }
                if (core) {
                    // move file to core directory
                    Files.move(file, Common.MA_HOME_PATH.resolve("m2m2-core-upgrade.zip"));
                    upgraded.add(file.getFileName().toString());
                } else if (hasWebModules) {
                    // This is a zip with modules in web/modules move them all out into the MA_HOME/web/modules dir
                    try (ZipInputStream is = new ZipInputStream(Files.newInputStream(file))) {
                        ZipEntry entry;
                        while ((entry = is.getNextEntry()) != null) {
                            if (entry.getName().startsWith(WEB_MODULE_PREFIX)) {
                                Path newModule = Common.MA_HOME_PATH.resolve(entry.getName());
                                Files.copy(is, newModule);
                                upgraded.add(newModule.getFileName().toString());
                            }
                        }
                    }
                } else {
                    // if its a module move it to the modules folder
                    if (isModule(file, unsigned)) {
                        // Its extra work but we better check that it is a module from the store:
                        Files.move(file, Common.MODULES.resolve(file.getFileName()));
                        upgraded.add(file.getFileName().toString());
                    } else {
                        // Is this a zip of modules?
                        try (ZipInputStream is = new ZipInputStream(Files.newInputStream(file))) {
                            ZipEntry entry;
                            while ((entry = is.getNextEntry()) != null) {
                                if (entry.getName().startsWith(ModuleUtils.Constants.MODULE_PREFIX)) {
                                    // Extract it and confirm it is a module
                                    Path newModule = tempDir.resolve(entry.getName());
                                    Files.copy(is, newModule);
                                    if (isModule(newModule, unsigned)) {
                                        Files.move(newModule, Common.MODULES.resolve(newModule.getFileName()));
                                        upgraded.add(newModule.getFileName().toString());
                                    }
                                }
                            }
                        }
                    }
                }
            }
            // Ensure we have some upgrades
            if (upgraded.size() == 0 && unsigned.size() == 0) {
                throw new BadRequestException(new TranslatableMessage("rest.error.invalidUpgradeFile"));
            } else if (upgraded.size() == 0 && unsigned.size() > 0) {
                throw new BadRequestException(new TranslatableMessage("modules.unsigned.development"));
            }
            result.setToUpgrade(upgraded);
            List<InvalidModule> invalid = new ArrayList<>();
            result.setInvalid(invalid);
            for (String u : unsigned) {
                invalid.add(new InvalidModule(u, new TranslatableMessage("modules.unsigned.development")));
            }
        } finally {
            FileUtils.deleteDirectory(tempDir.toFile());
        }
    } finally {
        // Release the lock
        synchronized (UPLOAD_UPGRADE_LOCK) {
            UPLOAD_UPGRADE_IN_PROGRESS = null;
        }
    }
    if (restart && result.getToUpgrade().size() > 0) {
        IMangoLifecycle lifecycle = Providers.get(IMangoLifecycle.class);
        lifecycle.scheduleShutdown(null, true, Common.getUser());
        result.setRestart(restart);
    }
    return result;
}
Also used : Path(java.nio.file.Path) Version(com.github.zafarkhaja.semver.Version) RequestParam(org.springframework.web.bind.annotation.RequestParam) Module(com.serotonin.m2m2.module.Module) PreAuthorize(org.springframework.security.access.prepost.PreAuthorize) UpdateLicensePayloadModel(com.infiniteautomation.mango.rest.latest.model.modules.UpdateLicensePayloadModel) Autowired(org.springframework.beans.factory.annotation.Autowired) ApiParam(io.swagger.annotations.ApiParam) PermissionHolder(com.serotonin.m2m2.vo.permission.PermissionHolder) StringUtils(org.apache.commons.lang3.StringUtils) JsonException(com.serotonin.json.JsonException) Matcher(java.util.regex.Matcher) Map(java.util.Map) ZoneOffset(java.time.ZoneOffset) FeatureDisabledException(com.infiniteautomation.mango.util.exception.FeatureDisabledException) Path(java.nio.file.Path) CoreModule(com.serotonin.m2m2.module.ModuleRegistry.CoreModule) BackupWorkItem(com.serotonin.m2m2.rt.maint.work.BackupWorkItem) RestController(org.springframework.web.bind.annotation.RestController) ZoneId(java.time.ZoneId) ModuleRegistry(com.serotonin.m2m2.module.ModuleRegistry) HttpException(org.apache.http.HttpException) ProcessResult(com.serotonin.m2m2.i18n.ProcessResult) JsonValue(com.serotonin.json.type.JsonValue) CredentialsModel(com.infiniteautomation.mango.rest.latest.model.CredentialsModel) PermissionService(com.infiniteautomation.mango.spring.service.PermissionService) AdminView(com.infiniteautomation.mango.rest.latest.model.modules.ModuleModel.AdminView) UpgradeStatus(com.infiniteautomation.mango.spring.service.ModulesService.UpgradeStatus) StandardCopyOption(java.nio.file.StandardCopyOption) ArrayList(java.util.ArrayList) RequestBody(org.springframework.web.bind.annotation.RequestBody) HttpServletRequest(javax.servlet.http.HttpServletRequest) ICoreLicense(com.serotonin.m2m2.ICoreLicense) JsonString(com.serotonin.json.type.JsonString) SocketTimeoutException(java.net.SocketTimeoutException) Api(io.swagger.annotations.Api) ModuleModel(com.infiniteautomation.mango.rest.latest.model.modules.ModuleModel) Properties(java.util.Properties) Common(com.serotonin.m2m2.Common) Files(java.nio.file.Files) AnonymousAccess(com.serotonin.m2m2.web.mvc.spring.security.permissions.AnonymousAccess) MultiValueMap(org.springframework.util.MultiValueMap) IOException(java.io.IOException) FileUtils(org.apache.commons.io.FileUtils) UnknownHostException(java.net.UnknownHostException) File(java.io.File) JsonArray(com.serotonin.json.type.JsonArray) HttpStatus(org.springframework.http.HttpStatus) SystemSettingsDao(com.serotonin.m2m2.db.dao.SystemSettingsDao) BadRequestException(com.infiniteautomation.mango.rest.latest.exception.BadRequestException) PathVariable(org.springframework.web.bind.annotation.PathVariable) UriComponentsBuilder(org.springframework.web.util.UriComponentsBuilder) Date(java.util.Date) Providers(com.serotonin.provider.Providers) LoggerFactory(org.slf4j.LoggerFactory) MultipartHttpServletRequest(org.springframework.web.multipart.MultipartHttpServletRequest) GenericRestException(com.infiniteautomation.mango.rest.latest.exception.GenericRestException) ApiOperation(io.swagger.annotations.ApiOperation) UpgradeStatusModel(com.infiniteautomation.mango.rest.latest.model.modules.UpgradeStatusModel) URI(java.net.URI) ZipEntry(java.util.zip.ZipEntry) ModuleUpgradeModel(com.infiniteautomation.mango.rest.latest.model.modules.ModuleUpgradeModel) HttpHeaders(org.springframework.http.HttpHeaders) RequestMethod(org.springframework.web.bind.annotation.RequestMethod) TranslatableMessage(com.serotonin.m2m2.i18n.TranslatableMessage) DatabaseBackupWorkItem(com.serotonin.m2m2.rt.maint.work.DatabaseBackupWorkItem) Collectors(java.util.stream.Collectors) StringStringPair(com.serotonin.db.pair.StringStringPair) FileNotFoundException(java.io.FileNotFoundException) List(java.util.List) ModuleUtils(com.serotonin.m2m2.shared.ModuleUtils) Environment(org.springframework.core.env.Environment) Writer(java.io.Writer) Pattern(java.util.regex.Pattern) User(com.serotonin.m2m2.vo.User) MangoStoreClient(com.infiniteautomation.mango.rest.latest.util.MangoStoreClient) IMangoLifecycle(com.serotonin.m2m2.IMangoLifecycle) InvalidModule(com.infiniteautomation.mango.rest.latest.model.modules.UpgradeUploadResult.InvalidModule) ZipInputStream(java.util.zip.ZipInputStream) ModuleRestException(com.infiniteautomation.mango.rest.latest.exception.ModuleRestException) ModulesService(com.infiniteautomation.mango.spring.service.ModulesService) NotFoundException(com.infiniteautomation.mango.util.exception.NotFoundException) RequestMapping(org.springframework.web.bind.annotation.RequestMapping) HashMap(java.util.HashMap) ModuleInfo(com.infiniteautomation.mango.rest.latest.model.modules.AngularJSModuleDefinitionGroupModel.ModuleInfo) Constants(com.serotonin.m2m2.Constants) ServerErrorException(com.infiniteautomation.mango.rest.latest.exception.ServerErrorException) MappingJacksonValue(org.springframework.http.converter.json.MappingJacksonValue) CoreModuleModel(com.infiniteautomation.mango.rest.latest.model.modules.CoreModuleModel) ValidationFailedRestException(com.infiniteautomation.mango.rest.latest.exception.ValidationFailedRestException) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) AngularJSModuleDefinitionGroupModel(com.infiniteautomation.mango.rest.latest.model.modules.AngularJSModuleDefinitionGroupModel) ModuleUpgradesModel(com.infiniteautomation.mango.rest.latest.model.modules.ModuleUpgradesModel) FileInputStream(java.io.FileInputStream) UpgradeVersionState(com.serotonin.m2m2.UpgradeVersionState) JsonObject(com.serotonin.json.type.JsonObject) UpgradeState(com.serotonin.m2m2.module.ModuleNotificationListener.UpgradeState) DateTimeFormatter(java.time.format.DateTimeFormatter) AuthenticationPrincipal(org.springframework.security.core.annotation.AuthenticationPrincipal) AngularJSModuleDefinition(com.serotonin.m2m2.module.AngularJSModuleDefinition) MultipartFile(org.springframework.web.multipart.MultipartFile) ResponseEntity(org.springframework.http.ResponseEntity) UpgradeUploadResult(com.infiniteautomation.mango.rest.latest.model.modules.UpgradeUploadResult) InputStream(java.io.InputStream) ZipInputStream(java.util.zip.ZipInputStream) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) ZipEntry(java.util.zip.ZipEntry) ArrayList(java.util.ArrayList) InvalidModule(com.infiniteautomation.mango.rest.latest.model.modules.UpgradeUploadResult.InvalidModule) JsonString(com.serotonin.json.type.JsonString) FeatureDisabledException(com.infiniteautomation.mango.util.exception.FeatureDisabledException) MultipartFile(org.springframework.web.multipart.MultipartFile) ZipInputStream(java.util.zip.ZipInputStream) UpgradeUploadResult(com.infiniteautomation.mango.rest.latest.model.modules.UpgradeUploadResult) BadRequestException(com.infiniteautomation.mango.rest.latest.exception.BadRequestException) JsonObject(com.serotonin.json.type.JsonObject) TranslatableMessage(com.serotonin.m2m2.i18n.TranslatableMessage) IMangoLifecycle(com.serotonin.m2m2.IMangoLifecycle) ApiOperation(io.swagger.annotations.ApiOperation) PreAuthorize(org.springframework.security.access.prepost.PreAuthorize) RequestMapping(org.springframework.web.bind.annotation.RequestMapping)

Aggregations

Version (com.github.zafarkhaja.semver.Version)1 BadRequestException (com.infiniteautomation.mango.rest.latest.exception.BadRequestException)1 GenericRestException (com.infiniteautomation.mango.rest.latest.exception.GenericRestException)1 ModuleRestException (com.infiniteautomation.mango.rest.latest.exception.ModuleRestException)1 ServerErrorException (com.infiniteautomation.mango.rest.latest.exception.ServerErrorException)1 ValidationFailedRestException (com.infiniteautomation.mango.rest.latest.exception.ValidationFailedRestException)1 CredentialsModel (com.infiniteautomation.mango.rest.latest.model.CredentialsModel)1 AngularJSModuleDefinitionGroupModel (com.infiniteautomation.mango.rest.latest.model.modules.AngularJSModuleDefinitionGroupModel)1 ModuleInfo (com.infiniteautomation.mango.rest.latest.model.modules.AngularJSModuleDefinitionGroupModel.ModuleInfo)1 CoreModuleModel (com.infiniteautomation.mango.rest.latest.model.modules.CoreModuleModel)1 ModuleModel (com.infiniteautomation.mango.rest.latest.model.modules.ModuleModel)1 AdminView (com.infiniteautomation.mango.rest.latest.model.modules.ModuleModel.AdminView)1 ModuleUpgradeModel (com.infiniteautomation.mango.rest.latest.model.modules.ModuleUpgradeModel)1 ModuleUpgradesModel (com.infiniteautomation.mango.rest.latest.model.modules.ModuleUpgradesModel)1 UpdateLicensePayloadModel (com.infiniteautomation.mango.rest.latest.model.modules.UpdateLicensePayloadModel)1 UpgradeStatusModel (com.infiniteautomation.mango.rest.latest.model.modules.UpgradeStatusModel)1 UpgradeUploadResult (com.infiniteautomation.mango.rest.latest.model.modules.UpgradeUploadResult)1 InvalidModule (com.infiniteautomation.mango.rest.latest.model.modules.UpgradeUploadResult.InvalidModule)1 MangoStoreClient (com.infiniteautomation.mango.rest.latest.util.MangoStoreClient)1 ModulesService (com.infiniteautomation.mango.spring.service.ModulesService)1