From 0fbaccf8a1ffb36e18ab88a9e5108d29eaeb1ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D?= Date: Tue, 22 Jan 2019 01:18:03 +0100 Subject: [PATCH] * [MOD] Improved plugins handling by moving items' data to new database table. * [MOD] Added plugins upgrade process MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rubén D --- .travis.yml | 2 +- .../web/Controllers/PluginController.php | 15 +- .../material-blue/views/plugin/plugin.inc | 12 +- lib/SP/DataModel/DataModelBase.php | 16 + lib/SP/Plugin/PluginInterface.php | 17 +- lib/SP/Plugin/PluginManager.php | 125 +++++-- lib/SP/Plugin/PluginOperation.php | 119 +++++++ .../Repositories/Plugin/PluginDataModel.php | 119 +++++++ .../Plugin/PluginDataRepository.php | 315 ++++++++++++++++++ .../Plugin/PluginModel.php} | 55 ++- .../Repositories/Plugin/PluginRepository.php | 33 +- lib/SP/Services/Install/Installer.php | 2 +- lib/SP/Services/Plugin/PluginDataService.php | 169 ++++++++++ lib/SP/Services/Plugin/PluginService.php | 18 +- lib/SP/Services/Upgrade/UpgradeAppService.php | 13 +- lib/SP/Services/Upgrade/UpgradePlugin.php | 61 ++++ lib/SP/Util/VersionUtil.php | 4 +- schemas/30119012201.sql | 16 + schemas/dbstructure.sql | 29 +- .../Repositories/PluginDataRepositoryTest.php | 270 +++++++++++++++ .../SP/Repositories/PluginRepositoryTest.php | 30 +- .../Services/Plugin/PluginDataServiceTest.php | 271 +++++++++++++++ .../SP/Services/Plugin/PluginServiceTest.php | 14 +- tests/res/datasets/syspass_plugin.xml | 22 ++ tests/res/scripts/db.sql | 127 +++++++ tests/res/scripts/dump_to_xml.sh | 23 ++ tests/res/scripts/reset_db.sh | 40 +++ 27 files changed, 1829 insertions(+), 108 deletions(-) create mode 100644 lib/SP/Plugin/PluginOperation.php create mode 100644 lib/SP/Repositories/Plugin/PluginDataModel.php create mode 100644 lib/SP/Repositories/Plugin/PluginDataRepository.php rename lib/SP/{DataModel/PluginData.php => Repositories/Plugin/PluginModel.php} (75%) create mode 100644 lib/SP/Services/Plugin/PluginDataService.php create mode 100644 lib/SP/Services/Upgrade/UpgradePlugin.php create mode 100644 schemas/30119012201.sql create mode 100644 tests/SP/Repositories/PluginDataRepositoryTest.php create mode 100644 tests/SP/Services/Plugin/PluginDataServiceTest.php create mode 100644 tests/res/scripts/db.sql create mode 100755 tests/res/scripts/dump_to_xml.sh create mode 100755 tests/res/scripts/reset_db.sh diff --git a/.travis.yml b/.travis.yml index 34756a47..960da5ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ php: branches: only: - master - - 3.0 + - /^v\d+\.\d+(\.\d+)?(-\S*)?$/ addons: mariadb: '10.1' diff --git a/app/modules/web/Controllers/PluginController.php b/app/modules/web/Controllers/PluginController.php index 44d3c1e0..b6ad3d3f 100644 --- a/app/modules/web/Controllers/PluginController.php +++ b/app/modules/web/Controllers/PluginController.php @@ -29,12 +29,13 @@ use Psr\Container\NotFoundExceptionInterface; use SP\Core\Acl\Acl; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; -use SP\DataModel\PluginData; use SP\Http\JsonResponse; use SP\Modules\Web\Controllers\Helpers\Grid\PluginGrid; use SP\Modules\Web\Controllers\Traits\ItemTrait; use SP\Modules\Web\Controllers\Traits\JsonTrait; use SP\Plugin\PluginManager; +use SP\Repositories\Plugin\PluginModel; +use SP\Services\Plugin\PluginDataService; use SP\Services\Plugin\PluginService; /** @@ -50,6 +51,10 @@ final class PluginController extends ControllerBase * @var PluginService */ protected $pluginService; + /** + * @var PluginDataService + */ + protected $pluginDataService; /** * indexAction @@ -165,8 +170,8 @@ final class PluginController extends ControllerBase { $this->view->addTemplate('plugin'); - $pluginData = $pluginId ? $this->pluginService->getById($pluginId) : new PluginData(); - $pluginInfo = $this->dic->get(PluginManager::class)->getPluginInfo($pluginData->name); + $pluginData = $pluginId ? $this->pluginService->getById($pluginId) : new PluginModel(); + $pluginInfo = $this->dic->get(PluginManager::class)->getPlugin($pluginData->getName()); $this->view->assign('plugin', $pluginData); $this->view->assign('pluginInfo', $pluginInfo); @@ -252,7 +257,8 @@ final class PluginController extends ControllerBase try { $this->checkSecurityToken($this->previousSk, $this->request); - $this->pluginService->resetById($id); + $pluginModel = $this->pluginService->getById($id); + $this->pluginDataService->delete($pluginModel->getName()); $this->eventDispatcher->notifyEvent('edit.plugin.reset', new Event($this, @@ -317,5 +323,6 @@ final class PluginController extends ControllerBase $this->checkLoggedIn(); $this->pluginService = $this->dic->get(PluginService::class); + $this->pluginDataService = $this->dic->get(PluginDataService::class); } } \ No newline at end of file diff --git a/app/modules/web/themes/material-blue/views/plugin/plugin.inc b/app/modules/web/themes/material-blue/views/plugin/plugin.inc index 08666b9c..ba4a51d0 100644 --- a/app/modules/web/themes/material-blue/views/plugin/plugin.inc +++ b/app/modules/web/themes/material-blue/views/plugin/plugin.inc @@ -1,11 +1,11 @@ {$name}; + } + + return null; + } } \ No newline at end of file diff --git a/lib/SP/Plugin/PluginInterface.php b/lib/SP/Plugin/PluginInterface.php index a4d4d1c9..e48a7977 100644 --- a/lib/SP/Plugin/PluginInterface.php +++ b/lib/SP/Plugin/PluginInterface.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -24,8 +24,6 @@ namespace SP\Plugin; -use SP\DataModel\PluginData; - /** * Interface PluginInterface * @@ -88,9 +86,9 @@ interface PluginInterface extends PluginEventReceiver public function getData(); /** - * @param PluginData $pluginData + * @param PluginOperation $pluginOperation */ - public function onLoadData(PluginData $pluginData); + public function onLoad(PluginOperation $pluginOperation); /** * @return int @@ -101,4 +99,11 @@ interface PluginInterface extends PluginEventReceiver * @param int $enabled */ public function setEnabled($enabled); + + /** + * @param string $version + * @param PluginOperation $pluginOperation + * @param mixed $extra + */ + public function upgrade(string $version, PluginOperation $pluginOperation, $extra = null); } \ No newline at end of file diff --git a/lib/SP/Plugin/PluginManager.php b/lib/SP/Plugin/PluginManager.php index 7e0818d2..5109e862 100644 --- a/lib/SP/Plugin/PluginManager.php +++ b/lib/SP/Plugin/PluginManager.php @@ -32,10 +32,12 @@ use SP\Core\Events\EventDispatcher; use SP\Core\Events\EventMessage; use SP\Core\Exceptions\ConstraintException; use SP\Core\Exceptions\QueryException; -use SP\DataModel\PluginData; use SP\Repositories\NoSuchItemException; +use SP\Repositories\Plugin\PluginModel; use SP\Services\Install\Installer; +use SP\Services\Plugin\PluginDataService; use SP\Services\Plugin\PluginService; +use SP\Util\VersionUtil; /** * Class PluginUtil @@ -72,17 +74,26 @@ final class PluginManager * @var EventDispatcher */ private $eventDispatcher; + /** + * @var PluginDataService + */ + private $pluginDataService; /** * PluginManager constructor. * - * @param PluginService $pluginService - * @param ContextInterface $context - * @param EventDispatcher $eventDispatcher + * @param PluginService $pluginService + * @param PluginDataService $pluginDataService + * @param ContextInterface $context + * @param EventDispatcher $eventDispatcher */ - public function __construct(PluginService $pluginService, ContextInterface $context, EventDispatcher $eventDispatcher) + public function __construct(PluginService $pluginService, + PluginDataService $pluginDataService, + ContextInterface $context, + EventDispatcher $eventDispatcher) { $this->pluginService = $pluginService; + $this->pluginDataService = $pluginDataService; $this->context = $context; $this->eventDispatcher = $eventDispatcher; @@ -127,13 +138,17 @@ final class PluginManager * * @return PluginInterface */ - public function getPluginInfo($name) + public function getPlugin($name) { if (isset(self::$pluginsAvailable[$name])) { - return $this->loadPluginClass( + $plugin = $this->loadPluginClass( $name, self::$pluginsAvailable[$name]['namespace'] ); + + $this->initPluginData($plugin); + + return $plugin; } return null; @@ -147,7 +162,7 @@ final class PluginManager * * @return PluginInterface */ - public function loadPluginClass(string $name, string $namespace) + private function loadPluginClass(string $name, string $namespace) { $name = ucfirst($name); @@ -171,16 +186,6 @@ final class PluginManager ); $this->disabledPlugins[] = $name; - - return $plugin; - } - - $pluginData = $this->pluginService->getByName($name); - - if ($pluginData->getEnabled() === 1) { - $plugin->onLoadData($pluginData); - } else { - $this->disabledPlugins[] = $name; } return $plugin; @@ -225,6 +230,31 @@ final class PluginManager return true; } + /** + * @param PluginInterface $plugin + */ + private function initPluginData(PluginInterface $plugin) + { + try { + $pluginData = $this->pluginService->getByName($plugin->getName()); + + if ($pluginData->getEnabled() === 1) { + $plugin->onLoad(new PluginOperation($this->pluginDataService, $plugin->getName())); + } else { + $this->disabledPlugins[] = $plugin->getName(); + } + } catch (\Exception $e) { + processException($e); + + $this->eventDispatcher->notifyEvent('exception', + new Event($e, EventMessage::factory() + ->addDescription(sprintf(__('Unable to load the "%s" plugin'), $plugin->getName())) + ->addDescription($e->getMessage()) + ->addDetail(__u('Plugin'), $plugin->getName())) + ); + } + } + /** * Loads the available and enabled plugins * @@ -287,6 +317,8 @@ final class PluginManager ); if ($plugin !== null) { + $this->initPluginData($plugin); + logger(sprintf('Plugin loaded: %s', $pluginName)); $this->eventDispatcher->notifyEvent('plugin.load', @@ -308,7 +340,7 @@ final class PluginManager */ private function registerPlugin(string $name) { - $pluginData = new PluginData(); + $pluginData = new PluginModel(); $pluginData->setName($name); $pluginData->setEnabled(false); @@ -323,6 +355,61 @@ final class PluginManager $this->disabledPlugins[] = $name; } + /** + * @param string $version + */ + public function upgradePlugins(string $version) + { + $available = array_keys(self::$pluginsAvailable); + + foreach ($available as $pluginName) { + $plugin = $this->loadPluginClass( + $pluginName, + self::$pluginsAvailable[$pluginName]['namespace'] + ); + + try { + $pluginModel = $this->pluginService->getByName($pluginName); + + if ($pluginModel->getVersionLevel() === null + || VersionUtil::checkVersion($pluginModel->getVersionLevel(), $version) + ) { + $this->eventDispatcher->notifyEvent('upgrade.plugin.process', + new Event($this, EventMessage::factory() + ->addDescription(__u('Upgrading plugin')) + ->addDetail(__u('Name'), $pluginName)) + ); + + $plugin->upgrade( + $version, + new PluginOperation($this->pluginDataService, $pluginName), + $pluginModel + ); + + $pluginModel->setData(null); + $pluginModel->setVersionLevel($version); + + $this->pluginService->update($pluginModel); + + $this->eventDispatcher->notifyEvent('upgrade.plugin.process', + new Event($this, EventMessage::factory() + ->addDescription(__u('Plugin upgraded')) + ->addDetail(__u('Name'), $pluginName)) + ); + } + } catch (\Exception $e) { + processException($e); + + $this->eventDispatcher->notifyEvent('exception', + new Event($e, EventMessage::factory() + ->addDescription(sprintf(__('Unable to upgrade the "%s" plugin'), $pluginName)) + ->addDescription($e->getMessage()) + ->addDetail(__u('Plugin'), $pluginName)) + ); + } + } + } + /** * Comprobar disponibilidad de plugins habilitados * diff --git a/lib/SP/Plugin/PluginOperation.php b/lib/SP/Plugin/PluginOperation.php new file mode 100644 index 00000000..a0b2c917 --- /dev/null +++ b/lib/SP/Plugin/PluginOperation.php @@ -0,0 +1,119 @@ +. + */ + +namespace SP\Plugin; + +use SP\Repositories\Plugin\PluginDataModel; +use SP\Services\Plugin\PluginDataService; + +/** + * Class PluginOperation + * + * @package SP\Plugin + */ +final class PluginOperation +{ + /** + * @var PluginDataService + */ + private $pluginDataService; + /** + * @var string + */ + private $name; + + /** + * PluginOperation constructor. + * + * @param PluginDataService $pluginDataService + * @param string $name + */ + public function __construct(PluginDataService $pluginDataService, string $name) + { + $this->pluginDataService = $pluginDataService; + $this->name = $name; + } + + /** + * @param int $itemId + * @param string $data + * + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function create(int $itemId, string $data) + { + $itemData = new PluginDataModel(); + $itemData->setName($this->name); + $itemData->setItemId($itemId); + $itemData->setData($data); + + $this->pluginDataService->create($itemData); + } + + /** + * @param int $itemId + * @param string $data + * + * @return int + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function update(int $itemId, string $data) + { + $itemData = new PluginDataModel(); + $itemData->setName($this->name); + $itemData->setItemId($itemId); + $itemData->setData($data); + + return $this->pluginDataService->update($itemData); + } + + /** + * @param int $itemId + * + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Repositories\NoSuchItemException + */ + public function delete(int $itemId) + { + $this->pluginDataService->deleteByItemId($this->name, $itemId); + } + + /** + * @param int $itemId + * @param string|null $class + * + * @return mixed|null + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\NoSuchPropertyException + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Repositories\NoSuchItemException + */ + public function get(int $itemId, string $class = null) + { + return $this->pluginDataService->getByItemId($this->name, $itemId)->hydrate($class); + } +} \ No newline at end of file diff --git a/lib/SP/Repositories/Plugin/PluginDataModel.php b/lib/SP/Repositories/Plugin/PluginDataModel.php new file mode 100644 index 00000000..3b42656e --- /dev/null +++ b/lib/SP/Repositories/Plugin/PluginDataModel.php @@ -0,0 +1,119 @@ +. + */ + +namespace SP\Repositories\Plugin; + +use SP\Core\Exceptions\NoSuchPropertyException; +use SP\DataModel\HydratableInterface; +use SP\Util\Util; + +/** + * Class PluginData + * + * @package SP\Repositories\Plugin + */ +final class PluginDataModel implements HydratableInterface +{ + /** + * @var string + */ + private $name; + /** + * @var int + */ + private $itemId; + /** + * @var string + */ + private $data; + + /** + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * @param string $name + */ + public function setName(string $name) + { + $this->name = $name; + } + + /** + * @return int + */ + public function getItemId(): int + { + return (int)$this->itemId; + } + + /** + * @param int $itemId + */ + public function setItemId(int $itemId) + { + $this->itemId = $itemId; + } + + /** + * @return string + */ + public function getData(): string + { + return $this->data; + } + + /** + * @param string $data + */ + public function setData(string $data) + { + $this->data = $data; + } + + /** + * @param string $class + * + * @param string $property + * + * @return mixed|null + * @throws NoSuchPropertyException + */ + public function hydrate(string $class = null, string $property = 'data') + { + if (property_exists($this, $property)) { + if ($this->data !== null) { + return $class !== null ? Util::unserialize($class, $this->data) : unserialize($this->data); + } + + return null; + } + + throw new NoSuchPropertyException($property); + } +} \ No newline at end of file diff --git a/lib/SP/Repositories/Plugin/PluginDataRepository.php b/lib/SP/Repositories/Plugin/PluginDataRepository.php new file mode 100644 index 00000000..ce5437a1 --- /dev/null +++ b/lib/SP/Repositories/Plugin/PluginDataRepository.php @@ -0,0 +1,315 @@ +. + */ + +namespace SP\Repositories\Plugin; + +use SP\Core\Exceptions\ConstraintException; +use SP\Core\Exceptions\QueryException; +use SP\DataModel\ItemSearchData; +use SP\Repositories\Repository; +use SP\Repositories\RepositoryItemInterface; +use SP\Repositories\RepositoryItemTrait; +use SP\Storage\Database\QueryData; +use SP\Storage\Database\QueryResult; + +/** + * Class PluginDataRepository + * + * @package SP\Repositories\Plugin + */ +final class PluginDataRepository extends Repository implements RepositoryItemInterface +{ + use RepositoryItemTrait; + + /** + * Creates an item + * + * @param PluginDataModel $itemData + * + * @return QueryResult + * @throws \SP\Core\Exceptions\ConstraintException + * @throws QueryException + */ + public function create($itemData) + { + $query = /** @lang SQL */ + 'INSERT INTO PluginData SET `name` = ?, itemId = ?, `data` = ?'; + + $queryData = new QueryData(); + $queryData->setQuery($query); + $queryData->setParams([ + $itemData->getName(), + $itemData->getItemId(), + $itemData->getData() + ]); + $queryData->setOnErrorMessage(__u('Error while adding plugin\'s data')); + + return $this->db->doQuery($queryData); + } + + /** + * Updates an item + * + * @param PluginDataModel $itemData + * + * @return int + * @throws \SP\Core\Exceptions\ConstraintException + * @throws QueryException + */ + public function update($itemData) + { + $query = /** @lang SQL */ + 'UPDATE PluginData + SET `data` = ? + WHERE `name` = ? AND itemId = ? LIMIT 1'; + + $queryData = new QueryData(); + $queryData->setQuery($query); + $queryData->setParams([ + $itemData->getData(), + $itemData->getName(), + $itemData->getItemId() + ]); + $queryData->setOnErrorMessage(__u('Error while updating plugin\'s data')); + + return $this->db->doQuery($queryData)->getAffectedNumRows(); + } + + /** + * Deletes an item + * + * @param $id + * + * @return int + * @throws \SP\Core\Exceptions\ConstraintException + * @throws QueryException + */ + public function delete($id) + { + $queryData = new QueryData(); + $queryData->setQuery('DELETE FROM PluginData WHERE `name` = ?'); + $queryData->addParam($id); + $queryData->setOnErrorMessage(__u('Error while deleting plugin\'s data')); + + return $this->db->doQuery($queryData)->getAffectedNumRows(); + } + + /** + * Deletes an item + * + * @param string $name + * @param int $itemId + * + * @return int + * @throws ConstraintException + * @throws QueryException + */ + public function deleteByItemId($name, $itemId) + { + $queryData = new QueryData(); + $queryData->setQuery('DELETE FROM PluginData WHERE `name` = ? AND itemId = ? LIMIT 1'); + $queryData->setParams([$name, $itemId]); + $queryData->setOnErrorMessage(__u('Error while deleting plugin\'s data')); + + return $this->db->doQuery($queryData)->getAffectedNumRows(); + } + + /** + * Returns the item for given id + * + * @param int $id + * + * @return QueryResult + * @throws ConstraintException + * @throws QueryException + */ + public function getById($id) + { + $query = /** @lang SQL */ + 'SELECT itemId, + `name`, + `data` + FROM PluginData + WHERE `name` = ?'; + + $queryData = new QueryData(); + $queryData->setMapClassName(PluginDataModel::class); + $queryData->setQuery($query); + $queryData->addParam($id); + + return $this->db->doSelect($queryData); + } + + /** + * Returns all the items + * + * @return QueryResult + * @throws ConstraintException + * @throws QueryException + */ + public function getAll() + { + $query = /** @lang SQL */ + 'SELECT itemId, + `name`, + `data` + FROM PluginData + ORDER BY `name`'; + + $queryData = new QueryData(); + $queryData->setMapClassName(PluginDataModel::class); + $queryData->setQuery($query); + + return $this->db->doSelect($queryData); + } + + /** + * Returns all the items for given ids + * + * @param array $ids + * + * @return QueryResult + * @throws ConstraintException + * @throws QueryException + */ + public function getByIdBatch(array $ids) + { + if (empty($ids)) { + return new QueryResult(); + } + + $query = /** @lang SQL */ + 'SELECT itemId, + `name`, + `data` + FROM PluginData + WHERE `name` IN (' . $this->getParamsFromArray($ids) . ') + ORDER BY `name`'; + + $queryData = new QueryData(); + $queryData->setMapClassName(PluginDataModel::class); + $queryData->setQuery($query); + $queryData->setParams($ids); + + return $this->db->doSelect($queryData); + } + + /** + * Deletes all the items for given ids + * + * @param array $ids + * + * @return int + * @throws ConstraintException + * @throws QueryException + */ + public function deleteByIdBatch(array $ids) + { + if (empty($ids)) { + return 0; + } + + $queryData = new QueryData(); + $queryData->setQuery('DELETE FROM PluginData WHERE `name` IN (' . $this->getParamsFromArray($ids) . ')'); + $queryData->setParams($ids); + $queryData->setOnErrorMessage(__u('Error while deleting plugin\'s data')); + + return $this->db->doQuery($queryData)->getAffectedNumRows(); + } + + /** + * Checks whether the item is in use or not + * + * @param $id int + * + * @return void + */ + public function checkInUse($id) + { + throw new \RuntimeException('Not implemented'); + } + + /** + * Checks whether the item is duplicated on updating + * + * @param mixed $itemData + * + * @return void + */ + public function checkDuplicatedOnUpdate($itemData) + { + throw new \RuntimeException('Not implemented'); + } + + /** + * Checks whether the item is duplicated on adding + * + * @param mixed $itemData + * + * @return void + */ + public function checkDuplicatedOnAdd($itemData) + { + throw new \RuntimeException('Not implemented'); + } + + /** + * Searches for items by a given filter + * + * @param ItemSearchData $SearchData + * + * @return mixed + */ + public function search(ItemSearchData $SearchData) + { + throw new \RuntimeException('Not implemented'); + } + + /** + * Devuelve los datos de un plugin por su nombre + * + * @param string $name + * @param int $itemId + * + * @return QueryResult + * @throws ConstraintException + * @throws QueryException + */ + public function getByItemId($name, $itemId) + { + $query = /** @lang SQL */ + 'SELECT itemId, + `name`, + `data` + FROM PluginData + WHERE `name` = ? AND itemId = ? LIMIT 1'; + + $queryData = new QueryData(); + $queryData->setMapClassName(PluginDataModel::class); + $queryData->setQuery($query); + $queryData->setParams([$name, $itemId]); + + return $this->db->doSelect($queryData); + } +} \ No newline at end of file diff --git a/lib/SP/DataModel/PluginData.php b/lib/SP/Repositories/Plugin/PluginModel.php similarity index 75% rename from lib/SP/DataModel/PluginData.php rename to lib/SP/Repositories/Plugin/PluginModel.php index 410610fe..52ea23f1 100644 --- a/lib/SP/DataModel/PluginData.php +++ b/lib/SP/Repositories/Plugin/PluginModel.php @@ -4,7 +4,7 @@ * * @author nuxsmin * @link https://syspass.org - * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org + * @copyright 2012-2019, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. * @@ -22,35 +22,42 @@ * along with sysPass. If not, see . */ -namespace SP\DataModel; +namespace SP\Repositories\Plugin; + +use SP\DataModel\DataModelBase; +use SP\DataModel\DataModelInterface; /** * Class PluginData * * @package SP\DataModel */ -class PluginData extends DataModelBase implements DataModelInterface +class PluginModel extends DataModelBase implements DataModelInterface { /** * @var int */ - public $id; + protected $id; /** * @var string */ - public $name; + protected $name; /** * @var string */ - public $data; + protected $data; /** * @var int */ - public $enabled = 0; + protected $enabled = 0; /** * @var int */ - public $available = 1; + protected $available = 1; + /** + * @var string + */ + protected $versionLevel; /** * @return int @@ -60,14 +67,6 @@ class PluginData extends DataModelBase implements DataModelInterface return (int)$this->id; } - /** - * @return string - */ - public function getName() - { - return $this->name; - } - /** * @param int $id */ @@ -76,6 +75,14 @@ class PluginData extends DataModelBase implements DataModelInterface $this->id = (int)$id; } + /** + * @return string + */ + public function getName() + { + return $this->name; + } + /** * @param string $name */ @@ -131,4 +138,20 @@ class PluginData extends DataModelBase implements DataModelInterface { $this->available = (int)$available; } + + /** + * @return string + */ + public function getVersionLevel() + { + return $this->versionLevel; + } + + /** + * @param string $versionLevel + */ + public function setVersionLevel(string $versionLevel) + { + $this->versionLevel = $versionLevel; + } } \ No newline at end of file diff --git a/lib/SP/Repositories/Plugin/PluginRepository.php b/lib/SP/Repositories/Plugin/PluginRepository.php index 5dd2d33d..c2fc7a20 100644 --- a/lib/SP/Repositories/Plugin/PluginRepository.php +++ b/lib/SP/Repositories/Plugin/PluginRepository.php @@ -29,7 +29,6 @@ use SP\Core\Exceptions\QueryException; use SP\Core\Exceptions\SPException; use SP\DataModel\ItemData; use SP\DataModel\ItemSearchData; -use SP\DataModel\PluginData; use SP\Repositories\Repository; use SP\Repositories\RepositoryItemInterface; use SP\Repositories\RepositoryItemTrait; @@ -48,7 +47,7 @@ final class PluginRepository extends Repository implements RepositoryItemInterfa /** * Creates an item * - * @param PluginData $itemData + * @param PluginModel $itemData * * @return QueryResult * @throws ConstraintException @@ -75,7 +74,7 @@ final class PluginRepository extends Repository implements RepositoryItemInterfa /** * Updates an item * - * @param PluginData $itemData + * @param PluginModel $itemData * * @return int * @throws ConstraintException @@ -88,7 +87,8 @@ final class PluginRepository extends Repository implements RepositoryItemInterfa SET `name` = ?, `data` = ?, enabled = ?, - available = ? + available = ?, + versionLevel = ? WHERE `name` = ? OR id = ? LIMIT 1'; $queryData = new QueryData(); @@ -98,6 +98,7 @@ final class PluginRepository extends Repository implements RepositoryItemInterfa $itemData->getData(), $itemData->getEnabled(), $itemData->getAvailable(), + $itemData->getVersionLevel(), $itemData->getName(), $itemData->getId() ]); @@ -122,12 +123,13 @@ final class PluginRepository extends Repository implements RepositoryItemInterfa `name`, `data`, enabled, - available + available, + versionLevel FROM Plugin WHERE id = ? LIMIT 1'; $queryData = new QueryData(); - $queryData->setMapClassName(PluginData::class); + $queryData->setMapClassName(PluginModel::class); $queryData->setQuery($query); $queryData->addParam($id); @@ -147,12 +149,13 @@ final class PluginRepository extends Repository implements RepositoryItemInterfa 'SELECT id, `name`, enabled, - available + available, + versionLevel FROM Plugin ORDER BY `name`'; $queryData = new QueryData(); - $queryData->setMapClassName(PluginData::class); + $queryData->setMapClassName(PluginModel::class); $queryData->setQuery($query); return $this->db->doSelect($queryData); @@ -177,13 +180,14 @@ final class PluginRepository extends Repository implements RepositoryItemInterfa 'SELECT id, `name`, enabled, - available + available, + versionLevel FROM Plugin WHERE id IN (' . $this->getParamsFromArray($ids) . ') ORDER BY id'; $queryData = new QueryData(); - $queryData->setMapClassName(PluginData::class); + $queryData->setMapClassName(PluginModel::class); $queryData->setQuery($query); $queryData->setParams($ids); @@ -282,8 +286,8 @@ final class PluginRepository extends Repository implements RepositoryItemInterfa public function search(ItemSearchData $itemSearchData) { $queryData = new QueryData(); - $queryData->setMapClassName(PluginData::class); - $queryData->setSelect('id, name, enabled, available'); + $queryData->setMapClassName(PluginModel::class); + $queryData->setSelect('id, name, enabled, available, versionLevel'); $queryData->setFrom('Plugin'); $queryData->setOrder('name'); @@ -318,12 +322,13 @@ final class PluginRepository extends Repository implements RepositoryItemInterfa `name`, `data`, enabled, - available + available, + versionLevel FROM Plugin WHERE `name` = ? LIMIT 1'; $queryData = new QueryData(); - $queryData->setMapClassName(PluginData::class); + $queryData->setMapClassName(PluginModel::class); $queryData->setQuery($query); $queryData->addParam($name); diff --git a/lib/SP/Services/Install/Installer.php b/lib/SP/Services/Install/Installer.php index ec3f39a2..969b01dd 100644 --- a/lib/SP/Services/Install/Installer.php +++ b/lib/SP/Services/Install/Installer.php @@ -56,7 +56,7 @@ final class Installer extends Service */ const VERSION = [3, 0, 1]; const VERSION_TEXT = '3.0'; - const BUILD = 19012002; + const BUILD = 19012201; /** * @var DatabaseSetupInterface diff --git a/lib/SP/Services/Plugin/PluginDataService.php b/lib/SP/Services/Plugin/PluginDataService.php new file mode 100644 index 00000000..6c292063 --- /dev/null +++ b/lib/SP/Services/Plugin/PluginDataService.php @@ -0,0 +1,169 @@ +. + */ + +namespace SP\Services\Plugin; + +use SP\Repositories\NoSuchItemException; +use SP\Repositories\Plugin\PluginDataModel; +use SP\Repositories\Plugin\PluginDataRepository; +use SP\Services\Service; + +/** + * Class PluginDataService + * + * @package SP\Services\Plugin + */ +final class PluginDataService extends Service +{ + /** + * @var PluginDataRepository + */ + protected $pluginRepository; + + /** + * Creates an item + * + * @param PluginDataModel $itemData + * + * @return \SP\Storage\Database\QueryResult + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function create(PluginDataModel $itemData) + { + $itemData->setData(serialize($itemData->getData())); + + return $this->pluginRepository->create($itemData); + } + + /** + * Updates an item + * + * @param PluginDataModel $itemData + * + * @return int + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function update(PluginDataModel $itemData) + { + $itemData->setData(serialize($itemData->getData())); + + return $this->pluginRepository->update($itemData); + } + + /** + * Returns the item for given plugin and id + * + * @param string $name + * @param int $id + * + * @return PluginDataModel + * @throws NoSuchItemException + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function getByItemId(string $name, int $id) + { + $result = $this->pluginRepository->getByItemId($name, $id); + + if ($result->getNumRows() === 0) { + throw new NoSuchItemException(__u('Plugin\'s data not found'), NoSuchItemException::INFO); + } + + return $result->getData(); + } + + /** + * Returns the item for given id + * + * @param int $id + * + * @return PluginDataModel[] + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + * @throws NoSuchItemException + */ + public function getById($id) + { + $result = $this->pluginRepository->getById($id); + + if ($result->getNumRows() === 0) { + throw new NoSuchItemException(__u('Plugin\'s data not found'), NoSuchItemException::INFO); + } + + return $result->getDataAsArray(); + } + + /** + * Returns all the items + * + * @return PluginDataModel[] + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function getAll() + { + return $this->pluginRepository->getAll()->getDataAsArray(); + } + + /** + * Deletes an item + * + * @param $id + * + * @throws NoSuchItemException + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function delete($id) + { + if ($this->pluginRepository->delete($id) === 0) { + throw new NoSuchItemException(__u('Plugin\'s data not found'), NoSuchItemException::INFO); + } + } + + /** + * Deletes an item + * + * @param string $name + * @param int $itemId + * + * @return void + * @throws NoSuchItemException + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function deleteByItemId(string $name, int $itemId) + { + if ($this->pluginRepository->deleteByItemId($name, $itemId) === 0) { + throw new NoSuchItemException(__u('Plugin\'s data not found'), NoSuchItemException::INFO); + } + } + + protected function initialize() + { + $this->pluginRepository = $this->dic->get(PluginDataRepository::class); + } +} \ No newline at end of file diff --git a/lib/SP/Services/Plugin/PluginService.php b/lib/SP/Services/Plugin/PluginService.php index 8eaac480..c08e4af5 100644 --- a/lib/SP/Services/Plugin/PluginService.php +++ b/lib/SP/Services/Plugin/PluginService.php @@ -27,8 +27,8 @@ namespace SP\Services\Plugin; use SP\Core\Exceptions\SPException; use SP\DataModel\ItemData; use SP\DataModel\ItemSearchData; -use SP\DataModel\PluginData; use SP\Repositories\NoSuchItemException; +use SP\Repositories\Plugin\PluginModel; use SP\Repositories\Plugin\PluginRepository; use SP\Services\Service; use SP\Services\ServiceException; @@ -49,13 +49,13 @@ final class PluginService extends Service /** * Creates an item * - * @param PluginData $itemData + * @param \SP\Repositories\Plugin\PluginModel $itemData * * @return int * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Core\Exceptions\QueryException */ - public function create(PluginData $itemData) + public function create(PluginModel $itemData) { return $this->pluginRepository->create($itemData)->getLastId(); } @@ -63,13 +63,13 @@ final class PluginService extends Service /** * Updates an item * - * @param PluginData $itemData + * @param \SP\Repositories\Plugin\PluginModel $itemData * * @return mixed * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Core\Exceptions\QueryException */ - public function update(PluginData $itemData) + public function update(PluginModel $itemData) { return $this->pluginRepository->update($itemData); } @@ -79,7 +79,7 @@ final class PluginService extends Service * * @param int $id * - * @return PluginData + * @return \SP\Repositories\Plugin\PluginModel * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Core\Exceptions\QueryException * @throws NoSuchItemException @@ -98,7 +98,7 @@ final class PluginService extends Service /** * Returns all the items * - * @return PluginData[] + * @return PluginModel[] * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Core\Exceptions\QueryException */ @@ -112,7 +112,7 @@ final class PluginService extends Service * * @param array $ids * - * @return PluginData[] + * @return \SP\Repositories\Plugin\PluginModel[] * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Core\Exceptions\QueryException */ @@ -173,7 +173,7 @@ final class PluginService extends Service * * @param string $name * - * @return PluginData + * @return \SP\Repositories\Plugin\PluginModel * @throws NoSuchItemException * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Core\Exceptions\QueryException diff --git a/lib/SP/Services/Upgrade/UpgradeAppService.php b/lib/SP/Services/Upgrade/UpgradeAppService.php index abf15c19..4de58960 100644 --- a/lib/SP/Services/Upgrade/UpgradeAppService.php +++ b/lib/SP/Services/Upgrade/UpgradeAppService.php @@ -38,7 +38,12 @@ use SP\Util\VersionUtil; */ final class UpgradeAppService extends Service implements UpgradeInterface { - const UPGRADES = ['300.18010101', '300.18072901', '300.18072902']; + const UPGRADES = [ + '300.18010101', + '300.18072901', + '300.18072902', + '310.19012201' + ]; /** * @param $version @@ -55,8 +60,6 @@ final class UpgradeAppService extends Service implements UpgradeInterface * @param ConfigData $configData * * @throws UpgradeException - * @throws \DI\DependencyException - * @throws \DI\NotFoundException * @throws \SP\Storage\File\FileException */ public function upgrade($version, ConfigData $configData) @@ -117,6 +120,10 @@ final class UpgradeAppService extends Service implements UpgradeInterface $this->dic->get(UpgradeCustomFieldData::class) ->upgrade_300_18072902(); return true; + case '310.19012201': + $this->dic->get(UpgradePlugin::class) + ->upgrade_310_19012201(); + return true; } } catch (\Exception $e) { processException($e); diff --git a/lib/SP/Services/Upgrade/UpgradePlugin.php b/lib/SP/Services/Upgrade/UpgradePlugin.php new file mode 100644 index 00000000..67f94f32 --- /dev/null +++ b/lib/SP/Services/Upgrade/UpgradePlugin.php @@ -0,0 +1,61 @@ +. + */ + +namespace SP\Services\Upgrade; + +use SP\Core\Events\Event; +use SP\Core\Events\EventMessage; +use SP\Plugin\PluginManager; +use SP\Services\Service; + +/** + * Class UpgradePlugin + * + * @package SP\Services\Upgrade + */ +final class UpgradePlugin extends Service +{ + /** + * upgrade_300_18010101 + * + * @throws \Exception + */ + public function upgrade_310_19012201() + { + $this->eventDispatcher->notifyEvent('upgrade.plugin.start', + new Event($this, EventMessage::factory() + ->addDescription(__u('Plugins upgrade')) + ->addDescription(__FUNCTION__)) + ); + + $this->dic->get(PluginManager::class) + ->upgradePlugins('310.19012201'); + + $this->eventDispatcher->notifyEvent('upgrade.plugin.end', + new Event($this, EventMessage::factory() + ->addDescription(__u('Plugins upgrade')) + ->addDescription(__FUNCTION__)) + ); + } +} \ No newline at end of file diff --git a/lib/SP/Util/VersionUtil.php b/lib/SP/Util/VersionUtil.php index 95fdf3b8..4bb7a236 100644 --- a/lib/SP/Util/VersionUtil.php +++ b/lib/SP/Util/VersionUtil.php @@ -44,12 +44,12 @@ final class VersionUtil } /** - * Comprobar si una versión necesita actualización + * Compare versions * * @param string $currentVersion * @param array|string $upgradeableVersion * - * @return bool True si la versión es menor. + * @return bool True if $currentVersion is lower than $upgradeableVersion */ public static function checkVersion($currentVersion, $upgradeableVersion) { diff --git a/schemas/30119012201.sql b/schemas/30119012201.sql new file mode 100644 index 00000000..82781dec --- /dev/null +++ b/schemas/30119012201.sql @@ -0,0 +1,16 @@ +DELIMITER $$ + +alter table Plugin + add versionLevel varchar(15) null $$ + +create table PluginData +( + name varchar(100) not null, + itemId int null, + data blob not null, + constraint `PRIMARY` + primary key (name, itemId), + constraint fk_PluginData_name + foreign key (name) references Plugin (name) + on update cascade on delete cascade +)$$ \ No newline at end of file diff --git a/schemas/dbstructure.sql b/schemas/dbstructure.sql index d178834a..50c6480e 100644 --- a/schemas/dbstructure.sql +++ b/schemas/dbstructure.sql @@ -417,11 +417,12 @@ DROP TABLE IF EXISTS `Plugin`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `Plugin` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `name` varchar(100) NOT NULL, - `data` mediumblob DEFAULT NULL, - `enabled` tinyint(1) NOT NULL DEFAULT 0, - `available` tinyint(1) DEFAULT 0, + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(100) NOT NULL, + `data` mediumblob DEFAULT NULL, + `enabled` tinyint(1) NOT NULL DEFAULT 0, + `available` tinyint(1) DEFAULT 0, + `versionLevel` varchar(15) NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_Plugin_01` (`name`) ) @@ -596,6 +597,24 @@ CREATE TABLE `UserToUserGroup` ( DEFAULT CHARSET = utf8 COLLATE utf8_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; +DROP TABLE IF EXISTS `PluginData`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +create table PluginData +( + name varchar(100) not null, + itemId int not null, + data blob not null, + primary key (name, itemId), + constraint fk_PluginData_name + foreign key (name) references Plugin (name) + on update cascade + on delete cascade +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8 + COLLATE utf8_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `account_data_v`; /*!50001 DROP VIEW IF EXISTS `account_data_v`*/; SET @saved_cs_client = @@character_set_client; diff --git a/tests/SP/Repositories/PluginDataRepositoryTest.php b/tests/SP/Repositories/PluginDataRepositoryTest.php new file mode 100644 index 00000000..c7a159df --- /dev/null +++ b/tests/SP/Repositories/PluginDataRepositoryTest.php @@ -0,0 +1,270 @@ +. + */ + +namespace SP\Tests\Repositories; + +use DI\DependencyException; +use SP\Core\Exceptions\ConstraintException; +use SP\Repositories\Plugin\PluginDataModel; +use SP\Repositories\Plugin\PluginDataRepository; +use SP\Storage\Database\DatabaseConnectionData; +use SP\Tests\DatabaseTestCase; +use function SP\Tests\setupContext; + +/** + * Class PluginDataRepositoryTest + * + * @package SP\Tests\Repositories + */ +class PluginDataRepositoryTest extends DatabaseTestCase +{ + /** + * @var PluginDataRepository + */ + private static $repository; + + /** + * @throws DependencyException + * @throws \DI\NotFoundException + * @throws \SP\Core\Context\ContextException + */ + public static function setUpBeforeClass() + { + $dic = setupContext(); + + self::$dataset = 'syspass_plugin.xml'; + + // Datos de conexión a la BBDD + self::$databaseConnectionData = $dic->get(DatabaseConnectionData::class); + + // Inicializar el repositorio + self::$repository = $dic->get(PluginDataRepository::class); + } + + /** + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testUpdate() + { + $data = new PluginDataModel(); + $data->setItemId(1); + $data->setName('Authenticator'); + $data->setData('data_updated'); + + $this->assertEquals(1, self::$repository->update($data)); + + $result = self::$repository->getByItemId($data->getName(), $data->getItemId()); + + $this->assertEquals(1, $result->getNumRows()); + $this->assertEquals($data, $result->getData()); + + $data = new PluginDataModel(); + $data->setItemId(0); + $data->setName('Authenticator'); + $data->setData('data_updated'); + + $this->assertEquals(0, self::$repository->update($data)); + } + + /** + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testUpdateUnkown() + { + $data = new PluginDataModel(); + $data->setItemId(2); + $data->setName('Test'); + $data->setData('data'); + + $this->assertEquals(0, self::$repository->update($data)); + } + + /** + * @throws ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testGetAll() + { + $result = self::$repository->getAll(); + /** @var PluginDataModel[] $data */ + $data = $result->getDataAsArray(); + + $this->assertEquals(4, $result->getNumRows()); + $this->assertCount(4, $data); + $this->assertEquals(1, $data[0]->getItemId()); + $this->assertEquals('Authenticator', $data[0]->getName()); + $this->assertEquals('data_item1', $data[0]->getData()); + + $this->assertEquals(2, $data[1]->getItemId()); + $this->assertEquals(3, $data[2]->getItemId()); + $this->assertEquals(2, $data[3]->getItemId()); + } + + /** + * @requires testGetById + * @throws ConstraintException + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Core\Exceptions\SPException + */ + public function testDelete() + { + $this->assertEquals(2, self::$repository->delete('Authenticator')); + $this->assertEquals(0, self::$repository->getById('Authenticator')->getNumRows()); + + $this->assertEquals(1, self::$repository->delete('DokuWiki')); + $this->assertEquals(0, self::$repository->getById('DokuWiki')->getNumRows()); + + $this->assertEquals(0, self::$repository->delete('Test')); + } + + /** + * @throws ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testDeleteByItemId() + { + $this->assertEquals(1, self::$repository->deleteByItemId('Authenticator', 1)); + $this->assertEquals(1, self::$repository->getById('Authenticator')->getNumRows()); + + $this->assertEquals(0, self::$repository->delete('Test')); + } + + /** + * @throws ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testGetById() + { + $result = self::$repository->getById('Authenticator'); + /** @var PluginDataModel[] $data */ + $data = $result->getDataAsArray(); + + $this->assertEquals(2, $result->getNumRows()); + $this->assertInstanceOf(PluginDataModel::class, $data[0]); + $this->assertEquals(1, $data[0]->getItemId()); + $this->assertEquals('Authenticator', $data[0]->getName()); + $this->assertEquals('data_item1', $data[0]->getData()); + + $this->assertInstanceOf(PluginDataModel::class, $data[1]); + $this->assertEquals(2, $data[1]->getItemId()); + $this->assertEquals('Authenticator', $data[1]->getName()); + $this->assertEquals('plugin_data', $data[1]->getData()); + + $this->assertEquals(1, self::$repository->getById('XML Exporter')->getNumRows()); + + $this->assertEquals(0, self::$repository->getById('Test')->getNumRows()); + } + + /** + * @throws ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testGetByItemId() + { + $result = self::$repository->getByItemId('Authenticator', 1); + /** @var PluginDataModel $data */ + $data = $result->getData(); + + $this->assertEquals(1, $result->getNumRows()); + $this->assertInstanceOf(PluginDataModel::class, $data); + $this->assertEquals(1, $data->getItemId()); + $this->assertEquals('Authenticator', $data->getName()); + $this->assertEquals('data_item1', $data->getData()); + + $this->assertEquals(0, self::$repository->getByItemId('Test', 1)->getNumRows()); + } + + /** + * @throws ConstraintException + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Core\Exceptions\SPException + */ + public function testDeleteByIdBatch() + { + $this->assertEquals(3, self::$repository->deleteByIdBatch(['Authenticator', 'XML Exporter', 'Test'])); + $this->assertEquals(0, self::$repository->deleteByIdBatch([])); + } + + /** + * @throws ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testCreate() + { + $data = new PluginDataModel(); + $data->setItemId(4); + $data->setName('Authenticator'); + $data->setData('data'); + + self::$repository->create($data); + + $result = self::$repository->getByItemId($data->getName(), $data->getItemId()); + + $this->assertEquals(1, $result->getNumRows()); + $this->assertEquals($data, $result->getData()); + + $this->expectException(ConstraintException::class); + + self::$repository->create($data); + } + + /** + * @throws ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testCreateUnknown() + { + $this->expectException(ConstraintException::class); + + $data = new PluginDataModel(); + $data->setItemId(4); + $data->setName('Test'); + $data->setData('data'); + + self::$repository->create($data); + } + + /** + * @throws ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testGetByIdBatch() + { + $result = self::$repository->getByIdBatch(['Authenticator', 'XML Exporter', 'Test']); + /** @var \SP\Repositories\Plugin\PluginDataModel[] $data */ + $data = $result->getDataAsArray(); + + $this->assertEquals(3, $result->getNumRows()); + $this->assertCount(3, $data); + $this->assertEquals(1, $data[0]->getItemId()); + $this->assertEquals(2, $data[1]->getItemId()); + $this->assertEquals(2, $data[2]->getItemId()); + + $result = self::$repository->getByIdBatch([]); + + $this->assertEquals(0, $result->getNumRows()); + } +} diff --git a/tests/SP/Repositories/PluginRepositoryTest.php b/tests/SP/Repositories/PluginRepositoryTest.php index 2351f022..c8376405 100644 --- a/tests/SP/Repositories/PluginRepositoryTest.php +++ b/tests/SP/Repositories/PluginRepositoryTest.php @@ -28,7 +28,7 @@ use DI\DependencyException; use SP\Core\Exceptions\ConstraintException; use SP\DataModel\ItemData; use SP\DataModel\ItemSearchData; -use SP\DataModel\PluginData; +use SP\Repositories\Plugin\PluginModel; use SP\Repositories\Plugin\PluginRepository; use SP\Storage\Database\DatabaseConnectionData; use SP\Tests\DatabaseTestCase; @@ -70,7 +70,7 @@ class PluginRepositoryTest extends DatabaseTestCase */ public function testUpdate() { - $data = new PluginData(); + $data = new PluginModel(); $data->setId(1); $data->setName('Authenticator 2'); $data->setAvailable(1); @@ -104,7 +104,7 @@ class PluginRepositoryTest extends DatabaseTestCase public function testGetAll() { $result = self::$repository->getAll(); - /** @var PluginData[] $data */ + /** @var \SP\Repositories\Plugin\PluginModel[] $data */ $data = $result->getDataAsArray(); $this->assertEquals(3, $result->getNumRows()); @@ -126,11 +126,11 @@ class PluginRepositoryTest extends DatabaseTestCase public function testGetByName() { $result = self::$repository->getByName('Authenticator'); - /** @var PluginData $data */ + /** @var \SP\Repositories\Plugin\PluginModel $data */ $data = $result->getData(); $this->assertEquals(1, $result->getNumRows()); - $this->assertInstanceOf(PluginData::class, $data); + $this->assertInstanceOf(PluginModel::class, $data); $this->assertEquals(1, $data->getId()); $this->assertEquals('Authenticator', $data->getName()); $this->assertNull($data->getData()); @@ -148,7 +148,7 @@ class PluginRepositoryTest extends DatabaseTestCase { $this->assertEquals(1, self::$repository->toggleAvailableByName('Authenticator', 0)); - /** @var PluginData $data */ + /** @var PluginModel $data */ $data = self::$repository->getByName('Authenticator')->getData(); $this->assertEquals(0, $data->getAvailable()); @@ -187,11 +187,11 @@ class PluginRepositoryTest extends DatabaseTestCase public function testGetById() { $result = self::$repository->getById(1); - /** @var PluginData $data */ + /** @var \SP\Repositories\Plugin\PluginModel $data */ $data = $result->getData(); $this->assertEquals(1, $result->getNumRows()); - $this->assertInstanceOf(PluginData::class, $data); + $this->assertInstanceOf(PluginModel::class, $data); $this->assertEquals(1, $data->getId()); $this->assertEquals('Authenticator', $data->getName()); $this->assertNull($data->getData()); @@ -238,7 +238,7 @@ class PluginRepositoryTest extends DatabaseTestCase */ public function testCreate() { - $data = new PluginData(); + $data = new PluginModel(); $data->setId(4); $data->setName('Authenticator 2'); $data->setAvailable(1); @@ -266,7 +266,7 @@ class PluginRepositoryTest extends DatabaseTestCase { $this->expectException(ConstraintException::class); - self::$repository->create(new PluginData()); + self::$repository->create(new PluginModel()); } /** @@ -277,7 +277,7 @@ class PluginRepositoryTest extends DatabaseTestCase { $this->assertEquals(1, self::$repository->resetById(2)); - /** @var PluginData $data */ + /** @var \SP\Repositories\Plugin\PluginModel $data */ $data = self::$repository->getById(2)->getData(); $this->assertNull($data->getData()); @@ -296,7 +296,7 @@ class PluginRepositoryTest extends DatabaseTestCase $itemSearchData->setSeachString('Auth'); $result = self::$repository->search($itemSearchData); - /** @var PluginData[] $data */ + /** @var PluginModel[] $data */ $data = $result->getDataAsArray(); $this->assertEquals(1, $result->getNumRows()); @@ -325,7 +325,7 @@ class PluginRepositoryTest extends DatabaseTestCase { $this->assertEquals(1, self::$repository->toggleEnabledByName('Authenticator', 1)); - /** @var PluginData $data */ + /** @var \SP\Repositories\Plugin\PluginModel $data */ $data = self::$repository->getByName('Authenticator')->getData(); $this->assertEquals(1, $data->getEnabled()); @@ -341,7 +341,7 @@ class PluginRepositoryTest extends DatabaseTestCase { $this->assertEquals(1, self::$repository->toggleAvailable(1, 0)); - /** @var PluginData $data */ + /** @var \SP\Repositories\Plugin\PluginModel $data */ $data = self::$repository->getByName('Authenticator')->getData(); $this->assertEquals(0, $data->getAvailable()); @@ -356,7 +356,7 @@ class PluginRepositoryTest extends DatabaseTestCase public function testGetByIdBatch() { $result = self::$repository->getByIdBatch([1, 2, 4]); - /** @var PluginData[] $data */ + /** @var \SP\Repositories\Plugin\PluginModel[] $data */ $data = $result->getDataAsArray(); $this->assertEquals(2, $result->getNumRows()); diff --git a/tests/SP/Services/Plugin/PluginDataServiceTest.php b/tests/SP/Services/Plugin/PluginDataServiceTest.php new file mode 100644 index 00000000..e682b1f4 --- /dev/null +++ b/tests/SP/Services/Plugin/PluginDataServiceTest.php @@ -0,0 +1,271 @@ +. + */ + +namespace SP\Tests\Services\Plugin; + +use SP\Core\Exceptions\ConstraintException; +use SP\Repositories\NoSuchItemException; +use SP\Repositories\Plugin\PluginDataModel; +use SP\Services\Plugin\PluginDataService; +use SP\Storage\Database\DatabaseConnectionData; +use SP\Tests\DatabaseTestCase; +use function SP\Tests\setupContext; + +/** + * Class PluginDataServiceTest + * + * @package SP\Tests\Services\Plugin + */ +class PluginDataServiceTest extends DatabaseTestCase +{ + /** + * @var PluginDataService + */ + private static $service; + + /** + * @throws \DI\NotFoundException + * @throws \SP\Core\Context\ContextException + * @throws \DI\DependencyException + */ + public static function setUpBeforeClass() + { + $dic = setupContext(); + + self::$dataset = 'syspass_plugin.xml'; + + // Datos de conexión a la BBDD + self::$databaseConnectionData = $dic->get(DatabaseConnectionData::class); + + // Inicializar el servicio + self::$service = $dic->get(PluginDataService::class); + } + + /** + * @throws ConstraintException + * @throws NoSuchItemException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testUpdate() + { + $data = new PluginDataModel(); + $data->setItemId(1); + $data->setName('Authenticator'); + $data->setData('data_updated'); + + $this->assertEquals(1, self::$service->update($data)); + + $this->assertEquals($data, self::$service->getByItemId($data->getName(), $data->getItemId())); + + $data = new PluginDataModel(); + $data->setItemId(0); + $data->setName('Authenticator'); + $data->setData('data_updated'); + + $this->assertEquals(0, self::$service->update($data)); + } + + /** + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testUpdateUnkown() + { + $data = new PluginDataModel(); + $data->setItemId(2); + $data->setName('Test'); + $data->setData('data'); + + $this->assertEquals(0, self::$service->update($data)); + } + + /** + * @throws ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testGetAll() + { + $data = self::$service->getAll(); + + $this->assertCount(4, $data); + $this->assertEquals(1, $data[0]->getItemId()); + $this->assertEquals('Authenticator', $data[0]->getName()); + $this->assertEquals('data_item1', $data[0]->getData()); + + $this->assertEquals(2, $data[1]->getItemId()); + $this->assertEquals(3, $data[2]->getItemId()); + $this->assertEquals(2, $data[3]->getItemId()); + } + + /** + * @throws ConstraintException + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Core\Exceptions\SPException + */ + public function testDelete() + { + self::$service->delete('Authenticator'); + + $this->assertTableRowCount('PluginData', 2); + + self::$service->delete('DokuWiki'); + + $this->assertTableRowCount('PluginData', 1); + } + + /** + * @throws ConstraintException + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Core\Exceptions\SPException + */ + public function testDeleteUnkown() + { + $this->expectException(NoSuchItemException::class); + + self::$service->delete('Test'); + } + + /** + * @throws ConstraintException + * @throws NoSuchItemException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testCreate() + { + $data = new PluginDataModel(); + $data->setItemId(4); + $data->setName('Authenticator'); + $data->setData('data'); + + self::$service->create($data); + + $this->assertEquals($data, self::$service->getByItemId($data->getName(), $data->getItemId())); + + $this->expectException(ConstraintException::class); + + self::$service->create($data); + } + + /** + * @throws ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testCreateUnknown() + { + $this->expectException(ConstraintException::class); + + $data = new PluginDataModel(); + $data->setItemId(4); + $data->setName('Test'); + $data->setData('data'); + + self::$service->create($data); + } + + /** + * @throws ConstraintException + * @throws NoSuchItemException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testGetByItemId() + { + $data = self::$service->getByItemId('Authenticator', 1); + + $this->assertInstanceOf(PluginDataModel::class, $data); + $this->assertEquals(1, $data->getItemId()); + $this->assertEquals('Authenticator', $data->getName()); + $this->assertEquals('data_item1', $data->getData()); + } + + /** + * @throws ConstraintException + * @throws NoSuchItemException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testGetByItemIdUnkown() + { + $this->expectException(NoSuchItemException::class); + + self::$service->getByItemId('Test', 1); + } + + /** + * @throws ConstraintException + * @throws NoSuchItemException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testGetById() + { + $result = self::$service->getById('Authenticator'); + + $this->assertCount(2, $result); + $this->assertInstanceOf(PluginDataModel::class, $result[0]); + $this->assertEquals(1, $result[0]->getItemId()); + $this->assertEquals('Authenticator', $result[0]->getName()); + $this->assertEquals('data_item1', $result[0]->getData()); + + $this->assertInstanceOf(PluginDataModel::class, $result[1]); + $this->assertEquals(2, $result[1]->getItemId()); + $this->assertEquals('Authenticator', $result[1]->getName()); + $this->assertEquals('plugin_data', $result[1]->getData()); + + $this->assertCount(1, self::$service->getById('XML Exporter')); + } + + /** + * @throws ConstraintException + * @throws NoSuchItemException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testGetByIdUnkown() + { + $this->expectException(NoSuchItemException::class); + + self::$service->getById('Test'); + } + + /** + * @throws ConstraintException + * @throws NoSuchItemException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testDeleteByItemId() + { + self::$service->deleteByItemId('Authenticator', 1); + + $this->assertCount(1, self::$service->getById('Authenticator')); + } + + /** + * @throws ConstraintException + * @throws NoSuchItemException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testDeleteByItemIdUnkown() + { + $this->expectException(NoSuchItemException::class); + + self::$service->deleteByItemId('Test', 1); + } +} diff --git a/tests/SP/Services/Plugin/PluginServiceTest.php b/tests/SP/Services/Plugin/PluginServiceTest.php index a75998be..86da6e75 100644 --- a/tests/SP/Services/Plugin/PluginServiceTest.php +++ b/tests/SP/Services/Plugin/PluginServiceTest.php @@ -27,8 +27,8 @@ namespace SP\Tests\Services\Plugin; use SP\Core\Exceptions\ConstraintException; use SP\DataModel\ItemData; use SP\DataModel\ItemSearchData; -use SP\DataModel\PluginData; use SP\Repositories\NoSuchItemException; +use SP\Repositories\Plugin\PluginModel; use SP\Services\Plugin\PluginService; use SP\Services\ServiceException; use SP\Storage\Database\DatabaseConnectionData; @@ -72,7 +72,7 @@ class PluginServiceTest extends DatabaseTestCase */ public function testUpdate() { - $data = new PluginData(); + $data = new PluginModel(); $data->setId(1); $data->setName('Authenticator 2'); $data->setAvailable(1); @@ -159,7 +159,7 @@ class PluginServiceTest extends DatabaseTestCase { $data = self::$service->getByName('Authenticator'); - $this->assertInstanceOf(PluginData::class, $data); + $this->assertInstanceOf(PluginModel::class, $data); $this->assertEquals(1, $data->getId()); $this->assertEquals('Authenticator', $data->getName()); $this->assertNull($data->getData()); @@ -201,7 +201,7 @@ class PluginServiceTest extends DatabaseTestCase $this->assertEquals(1, $result->getNumRows()); - /** @var PluginData[] $data */ + /** @var PluginModel[] $data */ $data = $result->getDataAsArray(); $this->assertCount(1, $data); @@ -230,7 +230,7 @@ class PluginServiceTest extends DatabaseTestCase { $data = self::$service->getById(1); - $this->assertInstanceOf(PluginData::class, $data); + $this->assertInstanceOf(PluginModel::class, $data); $this->assertEquals(1, $data->getId()); $this->assertEquals('Authenticator', $data->getName()); $this->assertNull($data->getData()); @@ -249,7 +249,7 @@ class PluginServiceTest extends DatabaseTestCase */ public function testCreate() { - $data = new PluginData(); + $data = new PluginModel(); $data->setId(4); $data->setName('Authenticator 2'); $data->setAvailable(1); @@ -273,7 +273,7 @@ class PluginServiceTest extends DatabaseTestCase { $this->expectException(ConstraintException::class); - self::$service->create(new PluginData()); + self::$service->create(new PluginModel()); } /** diff --git a/tests/res/datasets/syspass_plugin.xml b/tests/res/datasets/syspass_plugin.xml index 1e57c34f..96bc20e1 100644 --- a/tests/res/datasets/syspass_plugin.xml +++ b/tests/res/datasets/syspass_plugin.xml @@ -24,5 +24,27 @@ 0 + + + 1 + Authenticator + data_item1 + + + 2 + Authenticator + plugin_data + + + 2 + XML Exporter + data + + + 3 + DokuWiki + data_item3 + + diff --git a/tests/res/scripts/db.sql b/tests/res/scripts/db.sql new file mode 100644 index 00000000..a410454d --- /dev/null +++ b/tests/res/scripts/db.sql @@ -0,0 +1,127 @@ +-- MySQL dump 10.16 Distrib 10.1.26-MariaDB, for debian-linux-gnu (x86_64) +-- +-- Host: 127.0.0.1 Database: syspass +-- ------------------------------------------------------ +-- Server version 10.2.17-MariaDB-1:10.2.17+maria~bionic + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +/*!40000 ALTER TABLE `Account` DISABLE KEYS */; +INSERT INTO `Account` VALUES (1,1,1,1,3,'Amazon SES',2,'admin','https://aws.amazon.com/','def502008fde3a27bb1a6023f1b4ec524ba147c80ae78f90f9b3d0637af6809ad9263afaa36d34237ded5e8803b53f17121bd5e2a66919c0ce21d27c9360dfbc39d8151df9cbb4aadd1a0daa83ff59181ce1f1535c4b93d2701fa72c662115e919','def10000def502002937bbb81177ff4f769aeae126108783a141170588f3482fcbab44ae3390e80f85ab38521bafa8ec19648d267c9d46062294f5068a16706dcdb9042ddbb5b23ef54b3a12e7c5723b15d32ab9d8f5559e1fbc658c0b547a2a88a34b2498ef934d55395f857f28c9e3314493f319ebd4140d4a1b968e678cc12b58b5d2d057530be80f5f58c592cedcd85a90529d0895b11d6c04768bfbf4f1527babf5ee563798d35886f1c1017d1a3221cfd317cb84b13302d7d71c33e6753bcdb913dacd8909e195387f47b136a2789f85c48c3600f4ac6433a26e2bd0cae74fa2c461e4495108d340d7120febc65cfe79a4e2acc046f9bac29a0ce35cda','Simple Email Service',8,1,'2018-08-25 20:12:20','2018-08-25 20:16:11',0,0,0,0,1535227940,0,0); +INSERT INTO `Account` VALUES (2,1,1,1,1,'Google GCP',1,'admin','https://cloud.google.com/','def50200894e22b540a4975a3efe7dae669760aa6337195c690ac79ebff28f03393ae1070c5c7a635fa5a9aee5059df912c1948c41d8198f24f9f892a728d400d12d200c184a793d03a3f13eebfa45614efd0004ad7ea83338d1a04e20e6846078','def10000def50200f3d572936f4496e90369f6cc1feadce57c803b01a78c64b5987efd6369f7ecf526494a148d0e056feafe60d903bbb65ea9f79ad9b4f7ad42c7fe3c9c586f1807d252444c42667129da3727cf6f702a5aadf5db2391ba4a581f950df65262ae04b314b88d69d3174e6f226cb1f939f04d102799e58e0b6ed839fe2282056c58069e6298865c386e3d2114635621ed14eb199b1dad6dfcabc9b364ea2ae147c38352cd72bc0c79761a9df0f58690d5da1d1e3cc5e17261d740ca6863383a869b0253790d46ba2df032e741e8bb788033d8eb7b97d124d58b3c4310d15df7a4fd4d373dcc0ae111d46f6d623bac7ccf330520439736b223ae81','Google Cloud',2,0,'2018-08-25 20:15:02',NULL,0,0,0,0,1535228102,0,0); +/*!40000 ALTER TABLE `Account` ENABLE KEYS */; + +/*!40000 ALTER TABLE `AccountToTag` DISABLE KEYS */; +INSERT INTO `AccountToTag` VALUES (1,6); +INSERT INTO `AccountToTag` VALUES (2,3); +/*!40000 ALTER TABLE `AccountToTag` ENABLE KEYS */; + +/*!40000 ALTER TABLE `AuthToken` DISABLE KEYS */; +INSERT INTO `AuthToken` VALUES (1,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',2,1,1535228249,NULL,NULL); +INSERT INTO `AuthToken` VALUES (2,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',3,1,1535228254,NULL,NULL); +INSERT INTO `AuthToken` VALUES (3,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',7,1,1535228286,'O:19:\"SP\\Core\\Crypt\\Vault\":4:{s:25:\"\0SP\\Core\\Crypt\\Vault\0data\";s:190:\"def502005c9146e03665d0ecf8002f292580e91a5f20937e40414411038651ef6b5842a824c391b64ce1ef5781093302f0c64b574c4486faac0f7b4413a007e85f17e558e39482b470d971716d0b1ea50350c8c6128e37126e6f2b3e89a987\";s:24:\"\0SP\\Core\\Crypt\\Vault\0key\";s:512:\"def10000def50200dc68c3693660b0af530e6bfaaba9692b76459362b31b2c90106534a63ae6a193602de76b37de0d638c4aef7c9db0ff25e21a457fff326a1dc28c84d070b5df66f265779425b3e252b185342f7f0d9a0c977d4954860beabd1ff1f923f021b3dd19e0287d4be4051e43a6deae227e4f1475215db32b18d132aef7bf9d637c3f32ef39dd811e2fe28366a8ccb00f20fbe3b4d99ae7bbbbf170491a0275e9687ad53e511b2a3d3db32707105c24b64a3a931a3371aeb923234fa2814c3cef3785347024de8e337941812d8a1d5d48119052846cda8e280ff47d203f42d0954e446bd5dba77eef7889c5587605e74d439e21925603b24d15eea0\";s:28:\"\0SP\\Core\\Crypt\\Vault\0timeSet\";i:1535228286;s:32:\"\0SP\\Core\\Crypt\\Vault\0timeUpdated\";i:0;}','$2y$10$.uXTzsk75gEhgZXZJZML8O7au2HrMKY.WNhK3wN6RMe5ZaI2ZN2pG'); +INSERT INTO `AuthToken` VALUES (4,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',6,1,1535228293,NULL,NULL); +INSERT INTO `AuthToken` VALUES (5,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',4,1,1535228308,'O:19:\"SP\\Core\\Crypt\\Vault\":4:{s:25:\"\0SP\\Core\\Crypt\\Vault\0data\";s:190:\"def502001e44aef74b0e1ef844e0b4924e623e7b272826530cb4694388798bb5238a6f14bbcac2539697245ace4474e573fb39019576c1350c21d3bc141ae93b217c2722247ee431b04e2548cad4578a7de45c2877801500a045a395158192\";s:24:\"\0SP\\Core\\Crypt\\Vault\0key\";s:512:\"def10000def50200cf06fdb73f2529aff306eb7240631ef49a7455322b1030225aca3e6f46663b095d9097a5dca9eda13b9264db60cad8006ca1dcbc006f2c4beecca1d5859aca01ccd102c617aaee43e56c7e87071ddcb655d8c80478af75add7f0fff0acaf0970a96d4dca056c8e5f69a7fcfe1835c1b88ffb02072efb0b71de0ad28ddafe998e20f3370b71f868502457d29ea3a38498f04f4a6642a3420b45ac18acbabc3d8f673392b75eaeeac04bfc9e592967fec7804b1c23a5a8e1783139e530ef548207db1ad348e22122ad06d15caa45e4b14a89427f09822ad89d2d96fc2261e9857825f2b2cb02de74f6b16b981d83928ba8ea0affa8c3f26193\";s:28:\"\0SP\\Core\\Crypt\\Vault\0timeSet\";i:1535228308;s:32:\"\0SP\\Core\\Crypt\\Vault\0timeUpdated\";i:0;}','$2y$10$/myArYtpc/jfmO3AHEMe2uDrN7zwjGJk1fAcmXbZ.wcbyVwlunqjS'); +INSERT INTO `AuthToken` VALUES (6,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',102,1,1535228316,NULL,NULL); +INSERT INTO `AuthToken` VALUES (7,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',302,1,1535228368,NULL,NULL); +INSERT INTO `AuthToken` VALUES (8,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',202,1,1535228374,NULL,NULL); +INSERT INTO `AuthToken` VALUES (9,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',1541,1,1535228393,NULL,NULL); +INSERT INTO `AuthToken` VALUES (10,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',1561,1,1535228398,NULL,NULL); +INSERT INTO `AuthToken` VALUES (11,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',103,1,1535321537,NULL,NULL); +INSERT INTO `AuthToken` VALUES (12,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',104,1,1535321543,NULL,NULL); +INSERT INTO `AuthToken` VALUES (13,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',105,1,1535321552,NULL,NULL); +INSERT INTO `AuthToken` VALUES (14,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',106,1,1535321560,NULL,NULL); +INSERT INTO `AuthToken` VALUES (15,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',303,1,1535321568,NULL,NULL); +INSERT INTO `AuthToken` VALUES (16,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',304,1,1535321575,NULL,NULL); +INSERT INTO `AuthToken` VALUES (17,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',305,1,1535321580,NULL,NULL); +INSERT INTO `AuthToken` VALUES (18,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',306,1,1535321589,NULL,NULL); +INSERT INTO `AuthToken` VALUES (19,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',203,1,1535321594,NULL,NULL); +INSERT INTO `AuthToken` VALUES (20,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',204,1,1535321602,NULL,NULL); +INSERT INTO `AuthToken` VALUES (21,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',205,1,1535321608,NULL,NULL); +INSERT INTO `AuthToken` VALUES (22,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',206,1,1535321615,NULL,NULL); +INSERT INTO `AuthToken` VALUES (24,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',8,1,1535374384,'O:19:\"SP\\Core\\Crypt\\Vault\":4:{s:25:\"\0SP\\Core\\Crypt\\Vault\0data\";s:190:\"def50200d38515bf8e89df08a81876eba6d8522b86186bbea8b853a12cfe5226c674dbe5623d2f1b04b0accd39320fbc7d1a979caeb044c3664bf03eb00418798c35f9e5db87d97422d82f17726b0e57a9ff826e15e5ef94c2435d5ac5fb04\";s:24:\"\0SP\\Core\\Crypt\\Vault\0key\";s:512:\"def10000def5020049ec25f46b3d280f816e755f49fd3afccd74eba8a8d502fc15890212fbb240a4a8ca4d4758e2eaa0acff7ceea40f05e3af2cd898a8c2a64f44c839fc730ca2bfb38cd42611a3ff6d2b509112a57858c9c8613d1843d8224fba14ed940f4498759bfe8403f4f3c3cfe7d4f620f34bf11d7921714cc30d68937d685473f0d331cefd02e3f5a67d9dbaa52c9be66b0f291d776f13b9a1386e15fe61e3c91b3db06235ac76b9a1b5e8026262fe5150d398c969e1cf4112ef4925c88642cfaa52bf7daf0d8a0f90ef568adb549f868cf49280d13c2ad7e15e4acb0bf7e0d28627488d287e3817055e7e3e51cf9540ec2fb02a3c89afd20996a74f\";s:28:\"\0SP\\Core\\Crypt\\Vault\0timeSet\";i:1535374383;s:32:\"\0SP\\Core\\Crypt\\Vault\0timeUpdated\";i:0;}','$2y$10$vVrDPoi6wflaYzQIMuhVpeqtEvMN.4xwOAzLbxTZIw6gCP3kGTELG'); +INSERT INTO `AuthToken` VALUES (25,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',5,1,1535407845,NULL,NULL); +INSERT INTO `AuthToken` VALUES (26,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',803,1,1538818218,NULL,NULL); +INSERT INTO `AuthToken` VALUES (27,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',804,1,1538818227,NULL,NULL); +INSERT INTO `AuthToken` VALUES (28,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',805,1,1538818235,NULL,NULL); +INSERT INTO `AuthToken` VALUES (29,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',802,1,1538818243,NULL,NULL); +INSERT INTO `AuthToken` VALUES (30,1,'4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28',806,1,1538818294,NULL,NULL); +/*!40000 ALTER TABLE `AuthToken` ENABLE KEYS */; + +/*!40000 ALTER TABLE `Category` DISABLE KEYS */; +INSERT INTO `Category` VALUES (1,'GCP','','50f66ecbc45488ee5826941bfbc50411'); +INSERT INTO `Category` VALUES (2,'AWS','','ac68bbf921d953d1cfab916cb6120864'); +INSERT INTO `Category` VALUES (3,'SSH','','1787d7646304c5d987cf4e64a3973dc7'); +INSERT INTO `Category` VALUES (4,'Web','','2567a5ec9705eb7ac2c984033e06189d'); +/*!40000 ALTER TABLE `Category` ENABLE KEYS */; + +/*!40000 ALTER TABLE `Client` DISABLE KEYS */; +INSERT INTO `Client` VALUES (1,'Google','c822c1b63853ed273b89687ac505f9fa','',0); +INSERT INTO `Client` VALUES (2,'Apple','1f3870be274f6c49b3e31a0c6728957f','',0); +INSERT INTO `Client` VALUES (3,'Amazon','2d0d4809e6bdb6f4db3e547f27b1873c','',0); +/*!40000 ALTER TABLE `Client` ENABLE KEYS */; + +/*!40000 ALTER TABLE `Config` DISABLE KEYS */; +INSERT INTO `Config` VALUES ('config_backup','789c955851739b3810ee6fe1ed1e72231060204f4e9ca4bde61a4f713279b8998c8484ad31461441e33493ff7e1260179348d017db32df27ad56bbfbadb88b1c1059f1f2bf4b9ea76cdd7d2d5085ac2808a357114127b23e7d04f85417eb1211fa95be58e72292d3a82f38d3c109dfd6cf6ccbae7284334aac73160145806384fb32fba30524fe0209dae7b8a31c41cb3f222c91107d423846f8867654142839b12bd0b132828a054d519d553725af8b1ec9051348cb92a72c9be683a2e4fb97c9a7d2a0635afe3c75986dc42f7959a9a903108071f4f03046e61e9c84d6a7458d33966fc5bf68ffc0e8b35006416344f5182bb6a38ae003308932f4a7d6fb2849789d5797ea43a16dc7e8fe0e7e2bd768d0c6b9930d4db6f705411595bbc5239634e89c572ce9a1b5d99f343f3f23b13904254e6d9bba0e4689eda1104027012981c4a58e0bc12cc1be7c96ca870aef684f89e0cf5c540a637b91255e64ce087146f099dc43f337d4c63fc1314fb6b4ea4583691d95910a333b2e33c638849aed4796fde8ff857fbcfd02d9d5c5e6ad2cc7b887a0565c513c7938b0b1ed139f02188eaedba50f84c057507d09a4b85e1fcf4e5f59e98e0f0354bbbcaa23629e65fc9992ab7d251d8022db8d5e3b5e642d17d7c7508cac7f96376ae4b4a39b2fd7c73493c86fcd33b71ddd2d566ae41d4671935fed687177a94633155acde8b1291fedc3c7db061a76a3f8b659beb3e6215e34c3ce9cd5e3ea775645d665fcd00c3b832ee65fadf3b7a9bb8fd92fda2ee5b8c64c6a483d079bb3749d718cb298a232d91cd1da9ac77251a1ac3fb1510f262b6103663999ac8407c2b0fe7a26c2f2a3faae8d53c518c4a9a3155a059e13710c68ad07157028aafa3aa7d0efe5cee815b53f5455e5b4f9f9fab8453c72f60afb93e66d0e82e8f5cda4443bc4b2795d6de8546557846155d0c696025f977cd7dfa3113c0c1333b82b788e2a0eaed61f0afa9dfea8a5324c175c458a695297ac7a9974422d61180146fb8711ee9b7790b082b5c73ad19c43144cc82109cf2b1903b9ea3cc75a002582cfbc2431ca1a15f5e5f4c40b3c1b040e82a1ed22df9d21087d12843690c24ea5aae3200de43d20755ce2cca0130217504c00715ba9d76fbea442b6aa622e2e51d94b5c2d5e502118cf552bc6eb263e42608e52c12a7a8bf2b5b243d6259a3fddc7e6965231561bda7606b6f4ea4e364f2543d919ce6a6a2e706d4bf4404b6565c397870801f8db967dafe3007be4fe223fb02cd76313688ffaa3db95368c14f89a65d5c452dcde79d6b43ebd8c697da1f0ada40d18230da5fcd96aac073de8037fa634dfd5920eedf6979db46df21d46b6a8dbba78daf49a5719be08433243204cb08c668fa85e35f453cff6430753884892a60e357b89ee0b59b94e26060e2558f20124d0b37100210dc3591822dbc39e8f027f066422616c96954d5515a2a713c0e87cd9ce9eca0a3096d116fe5d3685d53b1f6a2d6a49efeba2f6a85ac2a1b27bb67b6ebacb76f71ca51a2bde9ceef8b1b61114a3ce22e91e44762c3717219a27e54b51c56d6d393a6becbe765d6759d344cc13795d12e36d3492522c9b31960cd4ded5d6832343aa38bfe56b960f1b8571ea82abfa3fe9f58910fcf48d43b7236dc3f59b707cdbd052f4e9da39ef6a5fb0f25da869173a611d2ee236807e0064fd7ffb1fe0f40600'); +INSERT INTO `Config` VALUES ('config_backup_date','1535363117'); +INSERT INTO `Config` VALUES ('lastupdatempass','1535226221'); +INSERT INTO `Config` VALUES ('masterPwd','$2y$10$Aiht18h7jXSj6U.S6tCkreAFvlUq./F84TeCtyN4oSWVHQc9vjosO'); +INSERT INTO `Config` VALUES ('version','300.18082201'); +/*!40000 ALTER TABLE `Config` ENABLE KEYS */; + +/*!40000 ALTER TABLE `EventLog` DISABLE KEYS */; +INSERT INTO `EventLog` VALUES (1,1538818164,'admin',1,'172.17.0.1','show.itemlist.security',NULL,'INFO'); +INSERT INTO `EventLog` VALUES (2,1538818174,'admin',1,'172.17.0.1','show.itemlist.items',NULL,'INFO'); +INSERT INTO `EventLog` VALUES (3,1538818177,'admin',1,'172.17.0.1','show.itemlist.accesses',NULL,'INFO'); +INSERT INTO `EventLog` VALUES (4,1538818194,'admin',1,'172.17.0.1','show.authToken.create',NULL,'INFO'); +INSERT INTO `EventLog` VALUES (5,1538818218,'admin',1,'172.17.0.1','show.itemlist.accesses',NULL,'INFO'); +INSERT INTO `EventLog` VALUES (6,1538818219,'admin',1,'172.17.0.1','show.authToken.create',NULL,'INFO'); +INSERT INTO `EventLog` VALUES (7,1538818227,'admin',1,'172.17.0.1','show.itemlist.accesses',NULL,'INFO'); +INSERT INTO `EventLog` VALUES (8,1538818228,'admin',1,'172.17.0.1','show.authToken.create',NULL,'INFO'); +INSERT INTO `EventLog` VALUES (9,1538818235,'admin',1,'172.17.0.1','show.itemlist.accesses',NULL,'INFO'); +INSERT INTO `EventLog` VALUES (10,1538818236,'admin',1,'172.17.0.1','show.authToken.create',NULL,'INFO'); +INSERT INTO `EventLog` VALUES (11,1538818243,'admin',1,'172.17.0.1','show.itemlist.accesses',NULL,'INFO'); +INSERT INTO `EventLog` VALUES (12,1538818288,'admin',1,'172.17.0.1','show.authToken.create',NULL,'INFO'); +INSERT INTO `EventLog` VALUES (13,1538818294,'admin',1,'172.17.0.1','show.itemlist.accesses',NULL,'INFO'); +INSERT INTO `EventLog` VALUES (14,1538818303,'admin',1,'172.17.0.1','show.account.search',NULL,'INFO'); +/*!40000 ALTER TABLE `EventLog` ENABLE KEYS */; + +/*!40000 ALTER TABLE `Tag` DISABLE KEYS */; +INSERT INTO `Tag` VALUES (1,'SSH','1787d7646304c5d987cf4e64a3973dc7'); +INSERT INTO `Tag` VALUES (2,'JBoss','9764dc122be894c72f6314703587f596'); +INSERT INTO `Tag` VALUES (3,'SaaS','593be52a46f869eea8b31d146d21de7a'); +INSERT INTO `Tag` VALUES (4,'Apache','b6efd606d118d0f62066e31419ff04cc'); +INSERT INTO `Tag` VALUES (5,'Tomcat','1b359d8753858b55befa0441067aaed3'); +INSERT INTO `Tag` VALUES (6,'Email','0c83f57c786a0b4a39efab23731c7ebc'); +/*!40000 ALTER TABLE `Tag` ENABLE KEYS */; + +/*!40000 ALTER TABLE `User` DISABLE KEYS */; +INSERT INTO `User` VALUES (1,'sysPass Admin',1,'admin',NULL,'$2y$10$YL0plKONrjT8ayrACgLZW.ZYytyz/Tm/6r5wLpLYSkl44niUHYvt6','def502003379170b312867d6c8e8b792773d912b9acb828728fb2b7b61fc3b98cac8dfd71073b44253c9eb2dc1ee68609d80bad2e00f78972eaf1fc98c38b88e85147709446027f1bddeec14c7e78983ac5e1aa52f2445cc84a824d16efbac','def10000def502003d5898af299ffc237380f5666737d8eb32e2be39e82c5116351047905c14b1f21c8e2f546865c4af7832fc83163dad672d85e00f64ddbee91ec9155eea15070966af390e1085addaef88c207f9d76cfd725f11784a3b62b816d51901ba74293837b68560d1db995aaee0ed4bf3e50c747023d544fdff78ef3b1294d8e788b30568a7b8e5a63ae7dfd83f1340e7e97428c1d8e1a6219610adc330e58d5d989524a6bd6d86e909153e733d2f08ab41d36e6892a9780b6a3f68b5942480c27b4f90fdf445ed711f736284d5285555a54b9c578292b140b741f3da1039e69997f7dc193cc536f033bab5778f8147925b161a43e83ae68b821587',NULL,NULL,24,1,'2018-08-27 12:45:05',NULL,1535226222,1,0,0,0,'',0,0,0,NULL); +/*!40000 ALTER TABLE `User` ENABLE KEYS */; + +/*!40000 ALTER TABLE `UserGroup` DISABLE KEYS */; +INSERT INTO `UserGroup` VALUES (1,'Admins','sysPass Admins'); +/*!40000 ALTER TABLE `UserGroup` ENABLE KEYS */; + +/*!40000 ALTER TABLE `UserProfile` DISABLE KEYS */; +INSERT INTO `UserProfile` VALUES (1,'Admin','O:24:\"SP\\DataModel\\ProfileData\":29:{s:10:\"\0*\0accView\";b:0;s:14:\"\0*\0accViewPass\";b:0;s:17:\"\0*\0accViewHistory\";b:0;s:10:\"\0*\0accEdit\";b:0;s:14:\"\0*\0accEditPass\";b:0;s:9:\"\0*\0accAdd\";b:0;s:12:\"\0*\0accDelete\";b:0;s:11:\"\0*\0accFiles\";b:0;s:13:\"\0*\0accPrivate\";b:0;s:18:\"\0*\0accPrivateGroup\";b:0;s:16:\"\0*\0accPermission\";b:0;s:17:\"\0*\0accPublicLinks\";b:0;s:18:\"\0*\0accGlobalSearch\";b:0;s:16:\"\0*\0configGeneral\";b:0;s:19:\"\0*\0configEncryption\";b:0;s:15:\"\0*\0configBackup\";b:0;s:15:\"\0*\0configImport\";b:0;s:11:\"\0*\0mgmUsers\";b:0;s:12:\"\0*\0mgmGroups\";b:0;s:14:\"\0*\0mgmProfiles\";b:0;s:16:\"\0*\0mgmCategories\";b:0;s:15:\"\0*\0mgmCustomers\";b:0;s:15:\"\0*\0mgmApiTokens\";b:0;s:17:\"\0*\0mgmPublicLinks\";b:0;s:14:\"\0*\0mgmAccounts\";b:0;s:10:\"\0*\0mgmTags\";b:0;s:11:\"\0*\0mgmFiles\";b:0;s:6:\"\0*\0evl\";b:0;s:18:\"\0*\0mgmCustomFields\";b:0;}'); +/*!40000 ALTER TABLE `UserProfile` ENABLE KEYS */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2018-10-06 11:36:16 diff --git a/tests/res/scripts/dump_to_xml.sh b/tests/res/scripts/dump_to_xml.sh new file mode 100755 index 00000000..472af506 --- /dev/null +++ b/tests/res/scripts/dump_to_xml.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +DB_HOST=$(docker inspect syspass-db-test --format {{.NetworkSettings.Networks.bridge.IPAddress}}) + +if [ -z "${DB_HOST}" ]; then + echo "Unknown host" + exit 1 +fi + +DB_TABLE=$1 +DUMP_PATH=$2 + +if [ -z ${DB_TABLE} ]; then + echo "Table not set" + exit 1 +fi + +if [ -z ${DUMP_PATH} ]; then + echo "Dump path not set" + exit 1 +fi + +mysqldump --hex-blob -t -u root --password=syspass-test --host=${DB_HOST} --xml syspass-test `echo "${DB_TABLE^}"` >> ${DUMP_PATH}/syspass_${DB_TABLE}.xml diff --git a/tests/res/scripts/reset_db.sh b/tests/res/scripts/reset_db.sh new file mode 100755 index 00000000..df0c9623 --- /dev/null +++ b/tests/res/scripts/reset_db.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +DB_HOST=$(docker inspect syspass-db-test --format {{.NetworkSettings.Networks.bridge.IPAddress}}) + +if [[ -z "${DB_HOST}" ]]; then + echo "Unknown host" + exit 1 +fi + +SQL_FILE=$1 +DB_NAME=$2 +PROJECT_DIR=$3 + +if [[ ! -e "${SQL_FILE}" ]]; then + echo "SQL file does not exist: ${SQL_FILE}" + exit 1 +fi + +echo "Database host: ${DB_HOST}" +echo "Database name: ${DB_NAME}" + +case ${DB_NAME} in + "syspass") + mysql -h ${DB_HOST} -u root -psyspass ${DB_NAME} < ${PROJECT_DIR}/schemas/dbstructure.sql + mysql -h ${DB_HOST} -u root -psyspass ${DB_NAME} < ${SQL_FILE} + ;; + "syspass-test") + mysql -h ${DB_HOST} -u root -psyspass -e 'DROP DATABASE IF EXISTS `'"${DB_NAME}"'`;' + mysql -h ${DB_HOST} -u root -psyspass -e 'CREATE DATABASE `'"${DB_NAME}"'` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;' + mysql -h ${DB_HOST} -u root -psyspass ${DB_NAME} < ${SQL_FILE} + ;; + *) + echo "Database name not set" + exit 1 + ;; +esac + +if [[ $? -eq 0 ]]; then + echo "Database data imported" +fi \ No newline at end of file