Commit b9bd0a75 authored by Roman Ondráček's avatar Roman Ondráček

Config: add JSON schema validations for imported scheduler's tasks

Signed-off-by: Roman Ondráček's avatarRoman Ondráček <ondracek.roman@centrum.cz>
parent df39799d
Pipeline #2148 passed with stages
in 13 minutes
......@@ -24,6 +24,7 @@ use App\ConfigModule\Exceptions\InvalidConfigurationFormatException;
use App\ConfigModule\Models\SchedulerManager;
use App\ConfigModule\Models\SchedulerMigrationManager;
use App\ConfigModule\Presenters\SchedulerPresenter;
use App\CoreModule\Exceptions\InvalidJsonException;
use App\CoreModule\Exceptions\NonExistingJsonSchemaException;
use App\CoreModule\Forms\FormFactory;
use App\ServiceModule\Exceptions\NotSupportedInitSystemException;
......@@ -150,7 +151,9 @@ class SchedulerImportFormFactory {
} catch (InvalidConfigurationFormatException $e) {
$this->presenter->flashError('config.migration.errors.invalidFormat');
} catch (NonExistingJsonSchemaException $e) {
$this->presenter->flashError('config.messages.writeFailures.nonExistingJsonSchema');
$this->presenter->flashError($e->getMessage());
} catch (InvalidJsonException $e) {
$this->presenter->flashError($e->getMessage());
} catch (NotSupportedInitSystemException $e) {
$this->presenter->flashError('service.errors.unsupportedInit');
} catch (IOException $e) {
......
......@@ -31,7 +31,10 @@ use Nette\Http\FileUpload;
use Nette\SmartObject;
use Nette\Utils\FileSystem;
use Nette\Utils\Finder;
use Nette\Utils\Json;
use Nette\Utils\Strings;
use SplFileInfo;
use Throwable;
use ZipArchive;
/**
......@@ -47,9 +50,9 @@ class SchedulerMigrationManager {
private $configDirectory;
/**
* @var string Path to ZIP archive
* @var SchedulerSchemaManager Scheduler JSON schema manager
*/
private $path = '/tmp/iqrf-daemon-scheduler.zip';
private $schemaManager;
/**
* @var ServiceManager Service manager
......@@ -61,9 +64,10 @@ class SchedulerMigrationManager {
* @param MainManager $mainManager Main configuration manager
* @param ServiceManager $serviceManager Service manager
*/
public function __construct(MainManager $mainManager, ServiceManager $serviceManager) {
public function __construct(MainManager $mainManager, ServiceManager $serviceManager, SchedulerSchemaManager $schemaManager) {
$this->configDirectory = $mainManager->getCacheDir() . '/scheduler/';
$this->serviceManager = $serviceManager;
$this->schemaManager = $schemaManager;
}
/**
......@@ -72,13 +76,18 @@ class SchedulerMigrationManager {
* @throws BadRequestException
*/
public function download(): FileResponse {
$zipManager = new ZipArchiveManager($this->path);
$now = new DateTime();
$fileName = 'iqrf-gateway-scheduler_' . $now->format('c') . '.zip';
try {
$now = new DateTime();
$timestamp = '_' . $now->format('c');
} catch (Throwable $e) {
$timestamp = '';
}
$fileName = 'iqrf-gateway-scheduler' . $timestamp . '.zip';
$zipManager = new ZipArchiveManager('/tmp/' . $fileName);
$contentType = 'application/zip';
$zipManager->addFolder($this->configDirectory, '');
$zipManager->close();
return new FileResponse($this->path, $fileName, $contentType, true);
return new FileResponse('/tmp/' . $fileName, $fileName, $contentType, true);
}
/**
......@@ -94,12 +103,17 @@ class SchedulerMigrationManager {
if ($zip->getContentType() !== 'application/zip') {
throw new InvalidConfigurationFormatException();
}
$zip->move($this->path);
$zipManagerUpload = new ZipArchiveManager($this->path, ZipArchive::CREATE);
$zipManager = new ZipArchiveManager($zip->getTemporaryFile(), ZipArchive::CREATE);
foreach ($zipManager->listFiles() as $fileName) {
if (Strings::startsWith($fileName, 'schema/')) {
continue;
}
$json = Json::decode($zipManager->openFile($fileName));
$this->schemaManager->validate($json);
}
$this->removeOldConfiguration();
$zipManagerUpload->extract($this->configDirectory);
$zipManagerUpload->close();
FileSystem::delete($this->path);
$zipManager->extract($this->configDirectory);
$zipManager->close();
$this->serviceManager->restart();
}
......
<?php
/**
* Copyright 2017 MICRORISC s.r.o.
* Copyright 2017-2019 IQRF Tech s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
declare(strict_types = 1);
namespace App\ConfigModule\Models;
use App\CoreModule\Exceptions\InvalidJsonException;
use App\CoreModule\Exceptions\NonExistingJsonSchemaException;
use App\CoreModule\Models\CommandManager;
use App\CoreModule\Models\JsonSchemaManager;
use App\IqrfNetModule\Models\ApiSchemaManager;
use Nette\Utils\JsonException;
/**
* Scheduler schema manager
*/
class SchedulerSchemaManager extends JsonSchemaManager {
/**
* @var ApiSchemaManager JSON API JSON schema manager
*/
private $apiSchemaManager;
/**
* Constructor
* @param MainManager $mainManager Main configuration manager
* @param CommandManager $commandManager Command manager
* @param ApiSchemaManager $apiSchemaManager JSON API JSON schema manager
*/
public function __construct(MainManager $mainManager, CommandManager $commandManager, ApiSchemaManager $apiSchemaManager) {
$configDir = $mainManager->getCacheDir() . '/scheduler/schema/';
parent::__construct($configDir, $commandManager);
$this->apiSchemaManager = $apiSchemaManager;
}
/**
* Validates JSON
* @param mixed $json JSON to validate
* @param bool $tryFix Try fix JSON?
* @return bool Is the JSON valid?
* @throws InvalidJsonException
* @throws JsonException
* @throws NonExistingJsonSchemaException
*/
public function validate($json, bool $tryFix = false): bool {
parent::setSchema('schema_cache_record');
parent::validate($json, $tryFix);
if (!is_array($json->task)) {
$tasks = [$json->task];
} else {
$tasks = $json->task;
}
foreach ($tasks as $id => $task) {
$this->apiSchemaManager->setSchemaForRequest($task->message->mType);
$this->apiSchemaManager->validate($task->message);
}
return true;
}
}
......@@ -10,5 +10,8 @@ services:
- App\ConfigModule\Models\MonitorManager
- App\ConfigModule\Models\SchedulerManager
- App\ConfigModule\Models\SchedulerMigrationManager
schemaSchedulerManager:
factory: App\ConfigModule\Models\SchedulerSchemaManager
autowired: self
- App\ConfigModule\Models\TaskTimeManager
- App\ConfigModule\Models\WebSocketManager
......@@ -52,6 +52,7 @@ class JsonSchemaManager extends JsonFileManager {
/**
* Sets the JSON schema file name
* @param string $fileName JSON schema file name
* @throws NonExistingJsonSchemaException
*/
public function setSchema(string $fileName): void {
if (parent::exists($fileName)) {
......
......@@ -157,7 +157,11 @@ class ZipArchiveManager {
* @return string Content of file
*/
public function openFile(string $fileName): string {
return $this->zip->getFromName('/' . $fileName);
$content = $this->zip->getFromName('/' . $fileName);
if (!is_bool($content)) {
return $content;
}
return $this->zip->getFromName($fileName);
}
/**
......
......@@ -12,6 +12,7 @@ namespace Tests\ConfigModule\Models;
use App\ConfigModule\Models\MainManager;
use App\ConfigModule\Models\SchedulerMigrationManager;
use App\ConfigModule\Models\SchedulerSchemaManager;
use App\CoreModule\Entities\CommandStack;
use App\CoreModule\Models\CommandManager;
use App\CoreModule\Models\FileManager;
......@@ -26,6 +27,7 @@ use Nette\Utils\Finder;
use Tester\Assert;
use Tester\Environment;
use Tester\TestCase;
use Throwable;
use ZipArchive;
require __DIR__ . '/../../bootstrap.php';
......@@ -55,11 +57,6 @@ class SchedulerMigrationManagerTest extends TestCase {
*/
private $manager;
/**
* @var string Path to the ZIP archive with IQRF Gateway Daemon's configuration
*/
private $path = '/tmp/iqrf-daemon-scheduler.zip';
/**
* @var string Path to a temporary ZIP archive with IQRF Gateway Daemon's configuration
*/
......@@ -69,14 +66,18 @@ class SchedulerMigrationManagerTest extends TestCase {
* Test function to download IQRF Gateway Daemon's configuration in a ZIP archive
*/
public function testDownload(): void {
$timestamp = (new DateTime())->format('c');
try {
$timestamp = '_' . (new DateTime())->format('c');
} catch (Throwable $e) {
$timestamp = '';
}
$actual = $this->manager->download();
$fileName = 'iqrf-gateway-scheduler_' . $timestamp . '.zip';
$fileName = 'iqrf-gateway-scheduler' . $timestamp . '.zip';
$contentType = 'application/zip';
$expected = new FileResponse($this->path, $fileName, $contentType, true);
$expected = new FileResponse('/tmp/' . $fileName, $fileName, $contentType, true);
Assert::equal($expected, $actual);
$files = $this->createList($this->configPath);
$zipManager = new ZipArchiveManager($this->path, ZipArchive::CREATE);
$zipManager = new ZipArchiveManager('/tmp/' . $fileName, ZipArchive::CREATE);
foreach ($files as $file) {
$expected = $this->fileManager->read($file);
Assert::same($expected, $zipManager->openFile($file));
......@@ -137,7 +138,9 @@ class SchedulerMigrationManagerTest extends TestCase {
$mainConfigManager->shouldReceive('getCacheDir')->andReturn($this->configTempPath . '/..');
$serviceManager = Mockery::mock(ServiceManager::class);
$serviceManager->shouldReceive('restart');
$this->manager = new SchedulerMigrationManager($mainConfigManager, $serviceManager);
$schemaManager = Mockery::mock(SchedulerSchemaManager::class);
$schemaManager->shouldReceive('validate')->andReturn(true);
$this->manager = new SchedulerMigrationManager($mainConfigManager, $serviceManager, $schemaManager);
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment