diff --git a/.travis.yml b/.travis.yml index 601aec29..8881edd4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,7 @@ before_script: - composer self-update - composer install --prefer-source --no-interaction --dev -script: ./vendor/bin/phpunit -c ./phpunit.xml --testsuite Core +script: ./vendor/bin/phpunit -c ./tests/phpunit.xml --testsuite Core after_script: - if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then mv ./tests/_output/coverage-clover.xml clover.xml && ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT -t clover; fi @@ -33,8 +33,9 @@ env: - DB_SERVER=127.0.0.1 DB_NAME=syspass DB_USER=root DB_PASS= before_install: - - mysql -e 'CREATE DATABASE IF NOT EXISTS `'"$DB_NAME"'` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;' - - mysql $DB_NAME < $TRAVIS_BUILD_DIR/schemas/dbstructure.sql + - mysql -e 'DROP DATABASE IF EXISTS `'"$DB_NAME"'`;' + - mysql -e 'CREATE DATABASE `'"$DB_NAME"'` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;' + - mysql $DB_NAME < ./schemas/dbstructure.sql cache: directories: diff --git a/app/modules/api/Controllers/AccountController.php b/app/modules/api/Controllers/AccountController.php index 66011b5c..26f59d96 100644 --- a/app/modules/api/Controllers/AccountController.php +++ b/app/modules/api/Controllers/AccountController.php @@ -29,6 +29,7 @@ use SP\Core\Crypt\Crypt; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; use SP\Modules\Api\Controllers\Help\AccountHelp; +use SP\Mvc\Model\QueryCondition; use SP\Services\Account\AccountRequest; use SP\Services\Account\AccountSearchFilter; use SP\Services\Account\AccountService; @@ -162,6 +163,26 @@ final class AccountController extends ControllerBase $accountSearchFilter->setCleanTxtSearch($this->apiService->getParamString('text')); $accountSearchFilter->setCategoryId($this->apiService->getParamInt('categoryId')); $accountSearchFilter->setClientId($this->apiService->getParamInt('clientId')); + + $tagsId = $this->apiService->getParamArray('tagsId', false, []); + + if (!empty($tagsId)) { + $accountSearchFilter->setTagsId($tagsId); + } + + $op = $this->apiService->getParamString('op'); + + if ($op !== null) { + switch ($op) { + case 'and': + $accountSearchFilter->setFilterOperator(QueryCondition::CONDITION_AND); + break; + case 'or': + $accountSearchFilter->setFilterOperator(QueryCondition::CONDITION_OR); + break; + } + } + $accountSearchFilter->setLimitCount($this->apiService->getParamInt('count', false, 50)); $accountSearchFilter->setSortOrder($this->apiService->getParamInt('order', false, AccountSearchFilter::SORT_DEFAULT)); @@ -194,7 +215,7 @@ final class AccountController extends ControllerBase ->addDetail(__u('Cliente'), $accountDetails->getClientName())) ); - $this->returnResponse(new ApiResponse(__u('Cuenta eliminada'), ApiResponse::RESULT_SUCCESS, $accountId)); + $this->returnResponse(new ApiResponse(__('Cuenta eliminada'), ApiResponse::RESULT_SUCCESS, $accountId)); } catch (\Exception $e) { processException($e); diff --git a/app/modules/api/Controllers/ConfigController.php b/app/modules/api/Controllers/ConfigController.php index 53e29748..42fccbe0 100644 --- a/app/modules/api/Controllers/ConfigController.php +++ b/app/modules/api/Controllers/ConfigController.php @@ -45,7 +45,7 @@ final class ConfigController extends ControllerBase public function backupAction() { try { - $this->setupApi(ActionsInterface::CONFIG_BACKUP); + $this->setupApi(ActionsInterface::CONFIG_BACKUP_RUN); $path = $this->apiService->getParamString('path', false, BACKUP_PATH); @@ -58,7 +58,7 @@ final class ConfigController extends ControllerBase ->addDetail(__u('Ruta'), $path)) ); - $this->returnResponse(new ApiResponse(__u('Proceso de backup finalizado'))); + $this->returnResponse(new ApiResponse(__('Proceso de backup finalizado'))); } catch (\Exception $e) { processException($e); @@ -72,7 +72,7 @@ final class ConfigController extends ControllerBase public function exportAction() { try { - $this->setupApi(ActionsInterface::CONFIG_EXPORT); + $this->setupApi(ActionsInterface::CONFIG_EXPORT_RUN); $password = $this->apiService->getParamString('password'); $path = $this->apiService->getParamString('path', false, BACKUP_PATH); @@ -91,7 +91,7 @@ final class ConfigController extends ControllerBase ->addDescription(__u('Proceso de exportación finalizado'))) ); - $this->returnResponse(new ApiResponse(__u('Proceso de exportación finalizado'))); + $this->returnResponse(new ApiResponse(__('Proceso de exportación finalizado'))); } catch (\Exception $e) { processException($e); diff --git a/app/modules/api/Controllers/ControllerBase.php b/app/modules/api/Controllers/ControllerBase.php index c41f674a..de6d11cc 100644 --- a/app/modules/api/Controllers/ControllerBase.php +++ b/app/modules/api/Controllers/ControllerBase.php @@ -30,6 +30,7 @@ use Psr\Container\ContainerInterface; use SP\Core\Context\StatelessContext; use SP\Core\Events\EventDispatcher; use SP\Core\Exceptions\SPException; +use SP\Http\Json; use SP\Services\Api\ApiResponse; use SP\Services\Api\ApiService; use SP\Services\Api\JsonRpcResponse; @@ -145,25 +146,30 @@ abstract class ControllerBase throw new SPException(__u('Acceso no permitido')); } - $this->router->response()->headers()->set('Content-type', 'application/json; charset=utf-8'); - $this->router->response()->send(true); - - echo JsonRpcResponse::getResponse($apiResponse, $this->apiService->getRequestId()); + $this->sendJsonResponse(JsonRpcResponse::getResponse($apiResponse, $this->apiService->getRequestId())); } catch (SPException $e) { processException($e); - echo JsonRpcResponse::getResponseException($e, $this->apiService->getRequestId()); + $this->returnResponseException($e); } } + /** + * Returns a JSON response back to the browser + * + * @param string $response + */ + final private function sendJsonResponse(string $response) + { + $json = Json::factory($this->router->response()); + $json->returnRawJson($response); + } + /** * @param \Exception $e */ final protected function returnResponseException(\Exception $e) { - $this->router->response()->headers()->set('Content-type', 'application/json; charset=utf-8'); - $this->router->response()->send(true); - - echo JsonRpcResponse::getResponseException($e, $this->apiService->getRequestId()); + $this->sendJsonResponse(JsonRpcResponse::getResponseException($e, $this->apiService->getRequestId())); } } \ No newline at end of file diff --git a/app/modules/api/Controllers/Help/AccountHelp.php b/app/modules/api/Controllers/Help/AccountHelp.php index 84f47526..2a3d5c4d 100644 --- a/app/modules/api/Controllers/Help/AccountHelp.php +++ b/app/modules/api/Controllers/Help/AccountHelp.php @@ -89,7 +89,9 @@ class AccountHelp implements HelpInterface self::getItem('text', __('Texto a buscar')), self::getItem('count', __('Número de resultados a mostrar')), self::getItem('categoryId', __('Id de categoría a filtrar')), - self::getItem('clientId', __('Id de cliente a filtrar')) + self::getItem('clientId', __('Id de cliente a filtrar')), + self::getItem('tagsId', __('Array de Ids de etiquetas a filtrar')), + self::getItem('op', __('Operador de filtrado')) ]; } diff --git a/composer.lock b/composer.lock index 367a08f5..b207e24e 100644 --- a/composer.lock +++ b/composer.lock @@ -1027,16 +1027,16 @@ }, { "name": "php-di/php-di", - "version": "6.0.2", + "version": "6.0.3", "source": { "type": "git", "url": "https://github.com/PHP-DI/PHP-DI.git", - "reference": "71a7f2ed1e728138060ea159cbb1a92dc8620bd2" + "reference": "61ef5c9fcbf04c8504a46d20bd27ea608eab7864" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/71a7f2ed1e728138060ea159cbb1a92dc8620bd2", - "reference": "71a7f2ed1e728138060ea159cbb1a92dc8620bd2", + "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/61ef5c9fcbf04c8504a46d20bd27ea608eab7864", + "reference": "61ef5c9fcbf04c8504a46d20bd27ea608eab7864", "shasum": "" }, "require": { @@ -1086,7 +1086,7 @@ "ioc", "psr11" ], - "time": "2018-04-23T06:54:40+00:00" + "time": "2018-08-25T22:21:38+00:00" }, { "name": "php-di/phpdoc-reader", @@ -1435,12 +1435,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "f834fd02a512672f298ed7c59e44e46621b6423d" + "reference": "0abc14e0df387fe74b4b32e0b8647d1639256d38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/f834fd02a512672f298ed7c59e44e46621b6423d", - "reference": "f834fd02a512672f298ed7c59e44e46621b6423d", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/0abc14e0df387fe74b4b32e0b8647d1639256d38", + "reference": "0abc14e0df387fe74b4b32e0b8647d1639256d38", "shasum": "" }, "conflict": { @@ -1577,7 +1577,7 @@ "zendframework/zend-validator": ">=2.3,<2.3.6", "zendframework/zend-view": ">=2,<2.2.7|>=2.3,<2.3.1", "zendframework/zend-xmlrpc": ">=2.1,<2.1.6|>=2.2,<2.2.6", - "zendframework/zendframework": ">=2,<2.4.11|>=2.5,<2.5.1", + "zendframework/zendframework": "<2.5.1", "zendframework/zendframework1": "<1.12.20", "zendframework/zendopenid": ">=2,<2.0.2", "zendframework/zendxml": ">=1,<1.0.1", @@ -1599,7 +1599,7 @@ } ], "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", - "time": "2018-08-10T10:05:21+00:00" + "time": "2018-08-14T15:39:17+00:00" }, { "name": "symfony/polyfill-php56", @@ -2535,16 +2535,16 @@ }, { "name": "phpunit/phpunit", - "version": "6.5.11", + "version": "6.5.12", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "7bab54cb366076023bbf457a2a0d513332cd40f2" + "reference": "24da433d7384824d65ea93fbb462e2f31bbb494e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7bab54cb366076023bbf457a2a0d513332cd40f2", - "reference": "7bab54cb366076023bbf457a2a0d513332cd40f2", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/24da433d7384824d65ea93fbb462e2f31bbb494e", + "reference": "24da433d7384824d65ea93fbb462e2f31bbb494e", "shasum": "" }, "require": { @@ -2615,7 +2615,7 @@ "testing", "xunit" ], - "time": "2018-08-07T07:05:35+00:00" + "time": "2018-08-22T06:32:48+00:00" }, { "name": "phpunit/phpunit-mock-objects", diff --git a/lib/SP/Http/Json.php b/lib/SP/Http/Json.php index e7cfe5f2..76ced573 100644 --- a/lib/SP/Http/Json.php +++ b/lib/SP/Http/Json.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. @@ -130,7 +130,7 @@ final class Json * * @return bool */ - public function returnRawJson($data) + public function returnRawJson(string $data) { return $this->response ->header('Content-type', 'application/json; charset=utf-8') diff --git a/lib/SP/Services/Api/ApiService.php b/lib/SP/Services/Api/ApiService.php index 2bf4cbcc..487491e9 100644 --- a/lib/SP/Services/Api/ApiService.php +++ b/lib/SP/Services/Api/ApiService.php @@ -97,7 +97,7 @@ final class ApiService extends Service __u('Intentos excedidos'), ServiceException::ERROR, null, - -32601 + JsonRpcResponse::INTERNAL_ERROR ); } @@ -132,7 +132,7 @@ final class ApiService extends Service __u('Error interno'), ServiceException::ERROR, null, - -32601 + JsonRpcResponse::INTERNAL_ERROR ); } } @@ -144,7 +144,7 @@ final class ApiService extends Service * @param bool $required Si es requerido * @param mixed $default Valor por defecto * - * @return int|string + * @return mixed * @throws ServiceException */ public function getParam($param, $required = false, $default = null) @@ -155,7 +155,7 @@ final class ApiService extends Service __u('Parámetros incorrectos'), ServiceException::ERROR, $this->getHelp($this->apiRequest->getMethod()), - -32602 + JsonRpcResponse::INVALID_PARAMS ); } @@ -189,7 +189,7 @@ final class ApiService extends Service __u('Acceso no permitido'), ServiceException::ERROR, null, - -32601 + JsonRpcResponse::INTERNAL_ERROR ); } @@ -230,7 +230,7 @@ final class ApiService extends Service __u('Error interno'), ServiceException::ERROR, __u('Datos inválidos'), - -32603 + JsonRpcResponse::INTERNAL_ERROR ); } } catch (CryptoException $e) { @@ -238,7 +238,7 @@ final class ApiService extends Service __u('Error interno'), ServiceException::ERROR, $e->getMessage(), - -32603 + JsonRpcResponse::INTERNAL_ERROR ); } } @@ -246,7 +246,7 @@ final class ApiService extends Service /** * @param string $param * @param bool $required - * @param null $default + * @param mixed $default * * @return int * @throws ServiceException @@ -259,7 +259,7 @@ final class ApiService extends Service /** * @param string $param * @param bool $required - * @param null $default + * @param mixed $default * * @return string * @throws ServiceException @@ -272,7 +272,20 @@ final class ApiService extends Service /** * @param string $param * @param bool $required - * @param null $default + * @param mixed $default + * + * @return array + * @throws ServiceException + */ + public function getParamArray($param, $required = false, $default = null) + { + return Filter::getArray($this->getParam($param, $required, $default)); + } + + /** + * @param string $param + * @param bool $required + * @param mixed $default * * @return int|string * @throws ServiceException @@ -285,7 +298,7 @@ final class ApiService extends Service /** * @param string $param * @param bool $required - * @param null $default + * @param mixed $default * * @return string * @throws ServiceException diff --git a/lib/SP/Services/Export/XmlExportService.php b/lib/SP/Services/Export/XmlExportService.php index 03f91045..850d9a1a 100644 --- a/lib/SP/Services/Export/XmlExportService.php +++ b/lib/SP/Services/Export/XmlExportService.php @@ -88,6 +88,7 @@ final class XmlExportService extends Service * @param string $pass string La clave de exportación * * @throws ServiceException + * @throws \SP\Storage\File\FileException */ public function doExport(string $exportPath, string $pass = null) { @@ -118,6 +119,8 @@ final class XmlExportService extends Service /** * Genera el nombre del archivo usado para la exportación. + * + * @throws \SP\Storage\File\FileException */ private function generateExportFilename(): string { @@ -497,7 +500,10 @@ final class XmlExportService extends Service $hashNode = $this->xml->createElement('Hash', $hash); $hashNode->appendChild($this->xml->createAttribute('sign')); - $hashNode->setAttribute('sign', Hash::signMessage($hash, $this->configData->getPasswordSalt())); + + $key = $this->exportPass ?: sha1($this->configData->getPasswordSalt()); + + $hashNode->setAttribute('sign', Hash::signMessage($hash, $key)); $this->root ->getElementsByTagName('Meta') diff --git a/lib/SP/Services/Export/XmlVerifyService.php b/lib/SP/Services/Export/XmlVerifyService.php index 28960dab..a2cd1ee4 100644 --- a/lib/SP/Services/Export/XmlVerifyService.php +++ b/lib/SP/Services/Export/XmlVerifyService.php @@ -116,11 +116,9 @@ final class XmlVerifyService extends Service * Obtener la versión del XML * * @param DOMDocument $document - * * @param string $key * - * @return void - * @throws ServiceException + * @return bool */ public static function checkXmlHash(DOMDocument $document, string $key) { @@ -128,11 +126,7 @@ final class XmlVerifyService extends Service $hash = $DOMXPath->query('/Root/Meta/Hash')->item(0)->nodeValue; $hmac = $DOMXPath->query('/Root/Meta/Hash/@sign')->item(0)->nodeValue; - if (!Hash::checkMessage($hash, $key, $hmac) - || $hash !== XmlExportService::generateHashFromNodes($document) - ) { - throw new ServiceException(__u('Fallo en la verificación del hash de integridad')); - } + return Hash::checkMessage($hash, $key, $hmac) || $hash === XmlExportService::generateHashFromNodes($document); } /** @@ -177,7 +171,11 @@ final class XmlVerifyService extends Service $this->checkPassword(); - self::checkXmlHash($this->xml, $this->config->getConfigData()->getPasswordSalt()); + $key = $password !== '' ? $password : $this->config->getConfigData()->getPasswordSalt(); + + if (!self::checkXmlHash($this->xml, $key)) { + throw new ServiceException(__u('Fallo en la verificación del hash de integridad')); + } return new VerifyResult($this->getXmlVersion(), $this->detectEncrypted(), $this->countItemNodes($this->processEncrypted())); } diff --git a/lib/SP/Services/Import/CsvImportBase.php b/lib/SP/Services/Import/CsvImportBase.php index 05d88134..5fa3cdd1 100644 --- a/lib/SP/Services/Import/CsvImportBase.php +++ b/lib/SP/Services/Import/CsvImportBase.php @@ -24,7 +24,7 @@ namespace SP\Services\Import; -use DI\Container; +use Psr\Container\ContainerInterface; use SP\Core\Events\Event; use SP\Core\Events\EventDispatcher; use SP\Core\Events\EventMessage; @@ -75,14 +75,12 @@ abstract class CsvImportBase /** * ImportBase constructor. * - * @param Container $dic - * @param FileImport $fileImport - * @param ImportParams $importParams + * @param ContainerInterface $dic + * @param FileImport $fileImport + * @param ImportParams $importParams * - * @throws \DI\DependencyException - * @throws \DI\NotFoundException */ - public function __construct(Container $dic, FileImport $fileImport, ImportParams $importParams) + public function __construct(ContainerInterface $dic, FileImport $fileImport, ImportParams $importParams) { $this->fileImport = $fileImport; $this->importParams = $importParams; diff --git a/lib/SP/Services/Import/ImportService.php b/lib/SP/Services/Import/ImportService.php index de0f4070..1407d750 100644 --- a/lib/SP/Services/Import/ImportService.php +++ b/lib/SP/Services/Import/ImportService.php @@ -35,7 +35,7 @@ defined('APP_ROOT') || die(); final class ImportService extends Service { const ALLOWED_EXTS = ['CSV', 'XML']; - + /** * @var ImportParams */ @@ -71,8 +71,6 @@ final class ImportService extends Service /** * @return ImportInterface * @throws ImportException - * @throws \DI\DependencyException - * @throws \DI\NotFoundException * @throws \SP\Storage\File\FileException */ protected function selectImportType() diff --git a/lib/SP/Services/Import/SyspassImport.php b/lib/SP/Services/Import/SyspassImport.php index befd1cd4..e505e903 100644 --- a/lib/SP/Services/Import/SyspassImport.php +++ b/lib/SP/Services/Import/SyspassImport.php @@ -72,7 +72,7 @@ final class SyspassImport extends XmlImportBase implements ImportInterface $this->processEncrypted(); } - XmlVerifyService::checkXmlHash($this->xmlDOM, $this->configData->getPasswordSalt()); + $this->checkIntegrity(); $this->processCategories(); @@ -163,6 +163,22 @@ final class SyspassImport extends XmlImportBase implements ImportInterface ); } + /** + * Checks XML file's data integrity using the signed hash + */ + protected function checkIntegrity() + { + $key = $this->importParams->getImportPwd() ?: sha1($this->configData->getPasswordSalt()); + + if (!XmlVerifyService::checkXmlHash($this->xmlDOM, $key)) { + $this->eventDispatcher->notifyEvent('run.import.syspass.process.verify', + new Event($this, EventMessage::factory() + ->addDescription(__u('Fallo en la verificación del hash de integridad')) + ->addDescription(__u('Si está importando un archivo exportado desde el mismo origen, los datos pueden estar comprometidos.'))) + ); + } + } + /** * Obtener las categorías y añadirlas a sysPass. * diff --git a/lib/SP/Services/Import/XmlImport.php b/lib/SP/Services/Import/XmlImport.php index ca726322..8fbb6282 100644 --- a/lib/SP/Services/Import/XmlImport.php +++ b/lib/SP/Services/Import/XmlImport.php @@ -25,6 +25,7 @@ namespace SP\Services\Import; use DI\Container; +use Psr\Container\ContainerInterface; defined('APP_ROOT') || die(); @@ -52,11 +53,11 @@ final class XmlImport implements ImportInterface /** * XmlImport constructor. * - * @param Container $dic - * @param XmlFileImport $xmlFileImport - * @param ImportParams $importParams + * @param ContainerInterface $dic + * @param XmlFileImport $xmlFileImport + * @param ImportParams $importParams */ - public function __construct(Container $dic, XmlFileImport $xmlFileImport, ImportParams $importParams) + public function __construct(ContainerInterface $dic, XmlFileImport $xmlFileImport, ImportParams $importParams) { $this->xmlFileImport = $xmlFileImport; $this->importParams = $importParams; diff --git a/lib/SP/Services/Install/Installer.php b/lib/SP/Services/Install/Installer.php index 7d7bfeaa..39751105 100644 --- a/lib/SP/Services/Install/Installer.php +++ b/lib/SP/Services/Install/Installer.php @@ -57,7 +57,7 @@ final class Installer extends Service */ const VERSION = [3, 0, 0]; const VERSION_TEXT = '3.0-beta'; - const BUILD = 18082201; + const BUILD = 18082701; /** * @var DatabaseSetupInterface diff --git a/phpunit.xml b/phpunit.xml deleted file mode 100644 index ab271201..00000000 --- a/phpunit.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - ./tests/SP - ./tests/SP/Modules - - - ./tests/SP/Modules - - - - - ./lib/SP - - ./lib/SP/DataModel - ./lib/SP/Html/Assets - ./lib/SP/Html/DataGrid - ./lib/SP/Config/ConfigData.php - - - - - - - - \ No newline at end of file diff --git a/tests/SP/Modules/Api/ApiTest.php b/tests/SP/Modules/Api/ApiTest.php index d9c514ac..3664f4c6 100644 --- a/tests/SP/Modules/Api/ApiTest.php +++ b/tests/SP/Modules/Api/ApiTest.php @@ -26,7 +26,6 @@ namespace SP\Tests\Modules\Api; use SP\Services\Api\JsonRpcResponse; use SP\Tests\WebTestCase; -use Symfony\Component\BrowserKit\Response; /** * Class ApiTest @@ -36,21 +35,13 @@ use Symfony\Component\BrowserKit\Response; class ApiTest extends WebTestCase { - const API_TOKEN = 'ca28f2ad2af09064ce0bfc2aff144cacb4a48df09b0978c4b6dc3970db7b2c48'; - const API_PASS = '123456'; + const API_TOKEN = '4eb7a989fab4c8fd9ade0ea80df7032d5ee78d4496c1c10f9c4388a872bfff28'; + const API_PASS = ')%Iykm*4A]wg'; const API_URL = 'http://syspass-app-test/api.php'; public function testInvalidRequest() { - $client = self::postJson(self::API_URL); - - /** @var Response $response */ - $response = $client->getResponse(); - - $this->assertEquals(200, $response->getStatus()); - $this->assertEquals('application/json; charset=utf-8', $response->getHeader('Content-Type')); - - $result = json_decode($response->getContent()); + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL)); $this->assertInstanceOf(\stdClass::class, $result); $this->assertEquals('2.0', $result->jsonrpc); @@ -70,15 +61,7 @@ class ApiTest extends WebTestCase 'id' => 1 ]; - $client = self::postJson(self::API_URL, $data); - - /** @var Response $response */ - $response = $client->getResponse(); - - $this->assertEquals(200, $response->getStatus()); - $this->assertEquals('application/json; charset=utf-8', $response->getHeader('Content-Type')); - - $result = json_decode($response->getContent()); + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); $this->assertInstanceOf(\stdClass::class, $result); $this->assertEquals('2.0', $result->jsonrpc); @@ -99,15 +82,7 @@ class ApiTest extends WebTestCase 'id' => 1 ]; - $client = self::postJson(self::API_URL, $data); - - /** @var Response $response */ - $response = $client->getResponse(); - - $this->assertEquals(200, $response->getStatus()); - $this->assertEquals('application/json; charset=utf-8', $response->getHeader('Content-Type')); - - $result = json_decode($response->getContent()); + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); $this->assertInstanceOf(\stdClass::class, $result); $this->assertEquals('2.0', $result->jsonrpc); diff --git a/tests/SP/Modules/Api/Controllers/AccountControllerTest.php b/tests/SP/Modules/Api/Controllers/AccountControllerTest.php index 24c239d5..78926e6c 100644 --- a/tests/SP/Modules/Api/Controllers/AccountControllerTest.php +++ b/tests/SP/Modules/Api/Controllers/AccountControllerTest.php @@ -26,7 +26,6 @@ namespace SP\Tests\Modules\Api\Controllers; use SP\Tests\Modules\Api\ApiTest; use SP\Tests\WebTestCase; -use Symfony\Component\BrowserKit\Response; /** * Class AccountControllerTest @@ -35,6 +34,9 @@ use Symfony\Component\BrowserKit\Response; */ class AccountControllerTest extends WebTestCase { + /** + * @return int + */ public function testCreateAction() { $data = [ @@ -44,38 +46,35 @@ class AccountControllerTest extends WebTestCase 'authToken' => ApiTest::API_TOKEN, 'tokenPass' => ApiTest::API_PASS, 'name' => 'API test', - 'categoryId' => 1, - 'clientId' => 1, + 'categoryId' => 2, + 'clientId' => 2, 'login' => 'root', 'pass' => 'password_test', - 'passDateChange' => time() + 86400, + 'expireDate' => time() + 86400, 'url' => 'http://syspass.org', - 'notes' => "test\ntest", + 'notes' => "test\n\ntest", 'isPrivate' => 1, 'isPrivateGroup' => 1, ], 'id' => 1 ]; - $client = self::postJson(ApiTest::API_URL, $data); - - /** @var Response $response */ - $response = $client->getResponse(); - - $this->assertEquals(200, $response->getStatus()); - $this->assertEquals('application/json; charset=utf-8', $response->getHeader('Content-Type')); - - $result = json_decode($response->getContent()); + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); $this->assertInstanceOf(\stdClass::class, $result); $this->assertEquals(0, $result->result->resultCode); - $this->assertEquals(1, $result->result->count); - $this->assertCount(2, $result->result->result); - $this->assertEquals(1, $result->result->result->itemId); - $this->assertNotEmpty($result->result->result->password); + $this->assertNull($result->result->count); + $this->assertEquals(3, $result->result->itemId); + + return $result->result->itemId; } - public function testViewPassAction() + /** + * @depends testCreateAction + * + * @param int $id + */ + public function testViewPassAction($id) { $data = [ 'jsonrpc' => '2.0', @@ -83,27 +82,64 @@ class AccountControllerTest extends WebTestCase 'params' => [ 'authToken' => ApiTest::API_TOKEN, 'tokenPass' => ApiTest::API_PASS, - 'id' => 1, + 'id' => $id, ], 'id' => 1 ]; - $client = self::postJson(ApiTest::API_URL, $data); - - /** @var Response $response */ - $response = $client->getResponse(); - - $this->assertEquals(200, $response->getStatus()); - $this->assertEquals('application/json; charset=utf-8', $response->getHeader('Content-Type')); - - $result = json_decode($response->getContent()); + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); $this->assertInstanceOf(\stdClass::class, $result); $this->assertEquals(0, $result->result->resultCode); - $this->assertEquals(1, $result->result->count); - $this->assertCount(2, $result->result->result); - $this->assertEquals(1, $result->result->result->itemId); - $this->assertNotEmpty($result->result->result->password); + $this->assertEquals(2, $result->result->count); + $this->assertInstanceOf(\stdClass::class, $result->result->result); + $this->assertEquals($id, $result->result->result->itemId); + $this->assertEquals('password_test', $result->result->result->password); + } + + /** + * @depends testCreateAction + * + * @param int $id + */ + public function testViewAction($id) + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/view', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'id' => $id, + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertNull($result->result->count); + $this->assertInstanceOf(\stdClass::class, $result->result->result); + $this->assertEquals($id, $result->result->result->id); + $this->assertEquals(1, $result->result->result->userId); + $this->assertEquals(1, $result->result->result->userGroupId); + $this->assertEquals(1, $result->result->result->userEditId); + $this->assertEquals('API test', $result->result->result->name); + $this->assertEquals(2, $result->result->result->clientId); + $this->assertEquals(2, $result->result->result->categoryId); + $this->assertEquals('root', $result->result->result->login); + $this->assertEquals('http://syspass.org', $result->result->result->url); + $this->assertEmpty($result->result->result->pass); + $this->assertEmpty($result->result->result->key); + $this->assertEquals("test\n\ntest", $result->result->result->notes); + $this->assertNull($result->result->result->dateEdit); + $this->assertEquals(0, $result->result->result->countView); + $this->assertEquals(1, $result->result->result->countDecrypt); + $this->assertEquals(0, $result->result->result->isPrivate); + $this->assertEquals(0, $result->result->result->isPrivateGroup); + $this->assertGreaterThan(0, $result->result->result->passDate); + $this->assertGreaterThan(0, $result->result->result->passDateChange); + $this->assertEquals(0, $result->result->result->parentId); } public function testSearchAction() @@ -117,29 +153,363 @@ class AccountControllerTest extends WebTestCase 'id' => 1 ]; - $client = self::postJson(ApiTest::API_URL, $data); - - /** @var Response $response */ - $response = $client->getResponse(); - - $this->assertEquals(200, $response->getStatus()); - $this->assertEquals('application/json; charset=utf-8', $response->getHeader('Content-Type')); - - $result = json_decode($response->getContent()); + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); $this->assertInstanceOf(\stdClass::class, $result); $this->assertEquals(0, $result->result->resultCode); $this->assertEquals(3, $result->result->count); $this->assertCount(3, $result->result->result); + + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'count' => 1 + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(1, $result->result->count); + $this->assertCount(1, $result->result->result); } - public function testDeleteAction() + public function testSearchByTextAction() { - $this->markTestSkipped(); + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'text' => 'Simple' + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(1, $result->result->count); + $this->assertCount(1, $result->result->result); + + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'text' => 'admin' + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(2, $result->result->count); + $this->assertCount(2, $result->result->result); + + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'text' => 'cloud' + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(1, $result->result->count); + $this->assertCount(1, $result->result->result); } - public function testViewAction() + public function testSearchByClientAction() { - $this->markTestSkipped(); + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'clientId' => 2 + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(1, $result->result->count); + $this->assertCount(1, $result->result->result); + + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'clientId' => 3 + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(1, $result->result->count); + $this->assertCount(1, $result->result->result); + + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'clientId' => 10 + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(0, $result->result->count); + $this->assertCount(0, $result->result->result); + } + + public function testSearchByCategoryAction() + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'categoryId' => 1 + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(1, $result->result->count); + $this->assertCount(1, $result->result->result); + + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'categoryId' => 3 + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(0, $result->result->count); + $this->assertCount(0, $result->result->result); + + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'categoryId' => 10 + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(0, $result->result->count); + $this->assertCount(0, $result->result->result); + } + + public function testSearchByTagsAction() + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'tagsId' => [3] + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(1, $result->result->count); + $this->assertCount(1, $result->result->result); + + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'tagsId' => [3, 6] + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(0, $result->result->count); + $this->assertCount(0, $result->result->result); + + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'tagsId' => [3, 6], + 'op' => 'or' + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(2, $result->result->count); + $this->assertCount(2, $result->result->result); + + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'tagsId' => [10] + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(0, $result->result->count); + $this->assertCount(0, $result->result->result); + } + + public function testSearchByCategoryAndClientAction() + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'categoryId' => 1, + 'clientId' => 1 + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(1, $result->result->count); + $this->assertCount(1, $result->result->result); + + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'categoryId' => 2, + 'clientId' => 3 + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(1, $result->result->count); + $this->assertCount(1, $result->result->result); + + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'categoryId' => 2, + 'clientId' => 1 + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(0, $result->result->count); + $this->assertCount(0, $result->result->result); + + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'categoryId' => 1, + 'clientId' => 3, + 'op' => 'or' + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(2, $result->result->count); + $this->assertCount(2, $result->result->result); + } + + /** + * @depends testCreateAction + * + * @param int $id + */ + public function testDeleteAction($id) + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'account/delete', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'id' => $id, + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertNull($result->result->count); + $this->assertEquals($id, $result->result->itemId); } } diff --git a/tests/SP/Modules/Api/Controllers/CategoryControllerTest.php b/tests/SP/Modules/Api/Controllers/CategoryControllerTest.php new file mode 100644 index 00000000..1945eeb1 --- /dev/null +++ b/tests/SP/Modules/Api/Controllers/CategoryControllerTest.php @@ -0,0 +1,199 @@ +. + */ + +namespace SP\Tests\Modules\Api\Controllers; + +use SP\Tests\Modules\Api\ApiTest; +use SP\Tests\WebTestCase; + +/** + * Class CategoryControllerTest + * + * @package SP\Tests\Modules\Api\Controllers + */ +class CategoryControllerTest extends WebTestCase +{ + /** + * @return int + */ + public function testCreateAction() + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'category/create', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'name' => 'API Category', + 'description' => "API test\ndescription" + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertNull($result->result->count); + $this->assertEquals(5, $result->result->itemId); + + return $result->result->itemId; + } + + /** + * @depends testCreateAction + * + * @param $id + */ + public function testViewAction($id) + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'category/view', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'id' => $id + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertNull($result->result->count); + $this->assertEquals($id, $result->result->result->id); + $this->assertEquals('API Category', $result->result->result->name); + $this->assertEquals("API test\ndescription", $result->result->result->description); + } + + /** + * @depends testCreateAction + * + * @param int $id + */ + public function testEditAction($id) + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'category/edit', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'id' => $id, + 'name' => 'API category edit', + 'description' => "API test\ndescription\nedit" + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertNull($result->result->count); + $this->assertEquals($id, $result->result->itemId); + } + + public function testSearchAction() + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'category/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(5, $result->result->count); + $this->assertCount(5, $result->result->result); + + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'category/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'count' => 1 + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(1, $result->result->count); + $this->assertCount(1, $result->result->result); + } + + public function testSearchByTextAction() + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'category/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'text' => 'API category edit' + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(1, $result->result->count); + $this->assertCount(1, $result->result->result); + $this->assertEquals('API category edit', $result->result->result[0]->name); + $this->assertEquals("API test\ndescription\nedit", $result->result->result[0]->description); + } + + /** + * @depends testCreateAction + * + * @param int $id + */ + public function testDeleteAction($id) + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'category/delete', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'id' => $id, + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertNull($result->result->count); + $this->assertEquals($id, $result->result->itemId); + } +} diff --git a/tests/SP/Modules/Api/Controllers/ClientControllerTest.php b/tests/SP/Modules/Api/Controllers/ClientControllerTest.php new file mode 100644 index 00000000..e253af2c --- /dev/null +++ b/tests/SP/Modules/Api/Controllers/ClientControllerTest.php @@ -0,0 +1,203 @@ +. + */ + +namespace SP\Tests\Modules\Api\Controllers; + +use SP\Tests\Modules\Api\ApiTest; +use SP\Tests\WebTestCase; + +/** + * Class ClientControllerTest + * + * @package SP\Tests\Modules\Api\Controllers + */ +class ClientControllerTest extends WebTestCase +{ + /** + * @return int + */ + public function testCreateAction() + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'client/create', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'name' => 'API Client', + 'description' => "API test\ndescription", + 'global' => 1 + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertNull($result->result->count); + $this->assertEquals(4, $result->result->itemId); + + return $result->result->itemId; + } + + /** + * @depends testCreateAction + * + * @param $id + */ + public function testViewAction($id) + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'client/view', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'id' => $id + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertNull($result->result->count); + $this->assertEquals($id, $result->result->result->id); + $this->assertEquals('API Client', $result->result->result->name); + $this->assertEquals("API test\ndescription", $result->result->result->description); + $this->assertEquals(1, $result->result->result->isGlobal); + } + + /** + * @depends testCreateAction + * + * @param int $id + */ + public function testEditAction($id) + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'client/edit', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'id' => $id, + 'name' => 'API Client edit', + 'description' => "API test\ndescription\nedit", + 'global' => 0 + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertNull($result->result->count); + $this->assertEquals($id, $result->result->itemId); + } + + public function testSearchAction() + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'client/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(4, $result->result->count); + $this->assertCount(4, $result->result->result); + + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'client/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'count' => 1 + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(1, $result->result->count); + $this->assertCount(1, $result->result->result); + } + + public function testSearchByTextAction() + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'client/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'text' => 'API Client edit' + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(1, $result->result->count); + $this->assertCount(1, $result->result->result); + $this->assertEquals('API Client edit', $result->result->result[0]->name); + $this->assertEquals("API test\ndescription\nedit", $result->result->result[0]->description); + $this->assertEquals(0, $result->result->result[0]->isGlobal); + } + + /** + * @depends testCreateAction + * + * @param int $id + */ + public function testDeleteAction($id) + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'client/delete', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'id' => $id, + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertNull($result->result->count); + $this->assertEquals($id, $result->result->itemId); + } +} diff --git a/tests/SP/Modules/Api/Controllers/ConfigControllerTest.php b/tests/SP/Modules/Api/Controllers/ConfigControllerTest.php new file mode 100644 index 00000000..802032b6 --- /dev/null +++ b/tests/SP/Modules/Api/Controllers/ConfigControllerTest.php @@ -0,0 +1,77 @@ +. + */ + +namespace SP\Tests\Modules\Api\Controllers; + +use SP\Tests\Modules\Api\ApiTest; +use SP\Tests\WebTestCase; + +/** + * Class ConfigControllerTest + * + * @package SP\Tests\Modules\Api\Controllers + */ +class ConfigControllerTest extends WebTestCase +{ + public function testExportAction() + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'config/export', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertNull($result->result->count); + $this->assertEquals('Export process finished', $result->result->result); + $this->assertEquals(0, $result->result->resultCode); + } + + public function testBackupAction() + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'config/backup', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertNull($result->result->count); + $this->assertEquals(0, $result->result->itemId); + $this->assertEquals('Backup process finished', $result->result->result); + $this->assertEquals(0, $result->result->resultCode); + } +} diff --git a/tests/SP/Modules/Api/Controllers/TagControllerTest.php b/tests/SP/Modules/Api/Controllers/TagControllerTest.php new file mode 100644 index 00000000..bef85181 --- /dev/null +++ b/tests/SP/Modules/Api/Controllers/TagControllerTest.php @@ -0,0 +1,196 @@ +. + */ + +namespace SP\Tests\Modules\Api\Controllers; + +use SP\Tests\Modules\Api\ApiTest; +use SP\Tests\WebTestCase; + +/** + * Class TagControllerTest + * + * @package SP\Tests\Modules\Api\Controllers + */ +class TagControllerTest extends WebTestCase +{ + /** + * @return int + */ + public function testCreateAction() + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'tag/create', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'name' => 'API Tag', + 'description' => "API test\ndescription" + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertNull($result->result->count); + $this->assertEquals(7, $result->result->itemId); + + return $result->result->itemId; + } + + /** + * @depends testCreateAction + * + * @param $id + */ + public function testViewAction($id) + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'tag/view', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'id' => $id + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertNull($result->result->count); + $this->assertEquals($id, $result->result->result->id); + $this->assertEquals('API Tag', $result->result->result->name); + } + + /** + * @depends testCreateAction + * + * @param int $id + */ + public function testEditAction($id) + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'tag/edit', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'id' => $id, + 'name' => 'API Tag edit' + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertNull($result->result->count); + $this->assertEquals($id, $result->result->itemId); + } + + public function testSearchAction() + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'tag/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(7, $result->result->count); + $this->assertCount(7, $result->result->result); + + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'tag/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'count' => 1 + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(1, $result->result->count); + $this->assertCount(1, $result->result->result); + } + + public function testSearchByTextAction() + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'tag/search', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'text' => 'API Tag edit' + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertEquals(1, $result->result->count); + $this->assertCount(1, $result->result->result); + $this->assertEquals('API Tag edit', $result->result->result[0]->name); + } + + /** + * @depends testCreateAction + * + * @param int $id + */ + public function testDeleteAction($id) + { + $data = [ + 'jsonrpc' => '2.0', + 'method' => 'tag/delete', + 'params' => [ + 'authToken' => ApiTest::API_TOKEN, + 'id' => $id, + ], + 'id' => 1 + ]; + + $result = self::checkAndProcessJsonResponse(self::postJson(ApiTest::API_URL, $data)); + + $this->assertInstanceOf(\stdClass::class, $result); + $this->assertEquals(0, $result->result->resultCode); + $this->assertNull($result->result->count); + $this->assertEquals($id, $result->result->itemId); + } +} diff --git a/tests/SP/Services/Api/ApiServiceTest.php b/tests/SP/Services/Api/ApiServiceTest.php index 1c84cd60..6f8a5d42 100644 --- a/tests/SP/Services/Api/ApiServiceTest.php +++ b/tests/SP/Services/Api/ApiServiceTest.php @@ -192,6 +192,9 @@ class ApiServiceTest extends DatabaseTestCase $this->assertEquals(10, self::$service->getRequestId()); } + /** + * @throws ServiceException + */ public function testGetMasterPass() { $this->assertEquals('12345678900', self::$service->getMasterPass()); diff --git a/tests/SP/Services/Export/XmlVerifyServiceTest.php b/tests/SP/Services/Export/XmlVerifyServiceTest.php new file mode 100644 index 00000000..5b048ef1 --- /dev/null +++ b/tests/SP/Services/Export/XmlVerifyServiceTest.php @@ -0,0 +1,114 @@ +. + */ + +namespace SP\Tests\Services\Export; + +use PHPUnit\Framework\TestCase; +use SP\Services\Export\VerifyResult; +use SP\Services\Export\XmlVerifyService; +use function SP\Tests\setupContext; + +/** + * Class XmlVerifyServiceTest + * + * @package SP\Tests\Services\Export + */ +class XmlVerifyServiceTest extends TestCase +{ + + /** + * @throws \DI\DependencyException + * @throws \DI\NotFoundException + * @throws \Defuse\Crypto\Exception\CryptoException + * @throws \SP\Core\Context\ContextException + * @throws \SP\Services\ServiceException + * @throws \SP\Storage\File\FileException + */ + public function testVerifyEncrypted() + { + $dic = setupContext(); + $service = $dic->get(XmlVerifyService::class); + + $file = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_syspass_encrypted.xml'; + + $result = $service->verifyEncrypted($file, 'test_encrypt'); + + $this->assertInstanceOf(VerifyResult::class, $result); + $this->assertEquals(300.18082201, $result->getVersion()); + + $nodes = $result->getNodes(); + + $this->assertCount(4, $nodes); + $this->assertEquals(4, $nodes['Category']); + $this->assertEquals(3, $nodes['Client']); + $this->assertEquals(6, $nodes['Tag']); + $this->assertEquals(2, $nodes['Account']); + } + + /** + * @throws \DI\DependencyException + * @throws \DI\NotFoundException + * @throws \SP\Core\Context\ContextException + * @throws \SP\Services\ServiceException + * @throws \SP\Storage\File\FileException + */ + public function testVerify() + { + $dic = setupContext(); + $service = $dic->get(XmlVerifyService::class); + + $file = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_syspass.xml'; + + $result = $service->verify($file); + + $this->assertInstanceOf(VerifyResult::class, $result); + $this->assertEquals(300.18071701, $result->getVersion()); + + $nodes = $result->getNodes(); + + $this->assertCount(4, $nodes); + $this->assertEquals(5, $nodes['Category']); + $this->assertEquals(4, $nodes['Client']); + $this->assertEquals(7, $nodes['Tag']); + $this->assertEquals(5, $nodes['Account']); + } + + public function testCheckXmlHash() + { + $dom = new \DOMDocument(); + $dom->load(RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_syspass_encrypted.xml'); + + $this->assertTrue(XmlVerifyService::checkXmlHash($dom, 'test_encrypt')); + + $dom->load(RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_syspass_invalid.xml'); + + $this->assertFalse(XmlVerifyService::checkXmlHash($dom, 'test_encrypt')); + + $key = sha1('d5851082a3914a647a336d8910e24eb64b8f8adef24d27329040ebd0d4c1'); + + $dom->load(RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_syspass_valid_hash.xml'); + + $this->assertTrue(XmlVerifyService::checkXmlHash($dom, $key)); + } +} diff --git a/tests/SP/Services/Import/SyspassImportTest.php b/tests/SP/Services/Import/SyspassImportTest.php index d52ba198..ee85dead 100644 --- a/tests/SP/Services/Import/SyspassImportTest.php +++ b/tests/SP/Services/Import/SyspassImportTest.php @@ -30,7 +30,6 @@ use SP\Services\Account\AccountService; use SP\Services\Category\CategoryService; use SP\Services\Client\ClientService; use SP\Services\Import\FileImport; -use SP\Services\Import\ImportException; use SP\Services\Import\ImportParams; use SP\Services\Import\SyspassImport; use SP\Services\Import\XmlFileImport; @@ -224,23 +223,4 @@ class SyspassImportTest extends DatabaseTestCase $this->assertEquals(7, $this->conn->getRowCount('Account')); } - - /** - * @throws ImportException - * @throws \SP\Storage\File\FileException - */ - public function testDoImportInvalidData() - { - $file = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_syspass_invalid.xml'; - - $params = new ImportParams(); - $params->setDefaultUser(1); - $params->setDefaultGroup(1); - - $import = new SyspassImport(self::$dic, new XmlFileImport(FileImport::fromFilesystem($file)), $params); - - $this->expectException(ImportException::class); - - $import->doImport(); - } } diff --git a/tests/SP/Services/Install/InstallerTest.php b/tests/SP/Services/Install/InstallerTest.php index 2b0682da..1d4933ec 100644 --- a/tests/SP/Services/Install/InstallerTest.php +++ b/tests/SP/Services/Install/InstallerTest.php @@ -55,8 +55,6 @@ class InstallerTest extends TestCase private static $dic; /** - * @throws \DI\DependencyException - * @throws \DI\NotFoundException * @throws \SP\Core\Context\ContextException */ public static function setUpBeforeClass() diff --git a/tests/SP/WebTestCase.php b/tests/SP/WebTestCase.php index 98c7e9fd..921c43f2 100644 --- a/tests/SP/WebTestCase.php +++ b/tests/SP/WebTestCase.php @@ -26,6 +26,7 @@ namespace SP\Tests; use Goutte\Client; use PHPUnit\Framework\TestCase; +use Symfony\Component\BrowserKit\Response; /** * Class WebTestCase @@ -57,4 +58,20 @@ abstract class WebTestCase extends TestCase { return new Client($server); } + + /** + * @param Client $client + * + * @return \stdClass + */ + protected static function checkAndProcessJsonResponse(Client $client) + { + /** @var Response $response */ + $response = $client->getResponse(); + + self::assertEquals(200, $response->getStatus()); + self::assertEquals('application/json; charset=utf-8', $response->getHeader('Content-Type')); + + return json_decode($response->getContent()); + } } \ No newline at end of file diff --git a/tests/SP/bootstrap.php b/tests/SP/bootstrap.php index 2e5db2a7..00cc5307 100644 --- a/tests/SP/bootstrap.php +++ b/tests/SP/bootstrap.php @@ -96,8 +96,6 @@ function getRealIpAddress() /** * Configura el contexto de la aplicación para los tests * - * @throws \DI\DependencyException - * @throws \DI\NotFoundException * @throws \SP\Core\Context\ContextException * @return \DI\Container * @throws \Exception diff --git a/tests/phpunit.xml b/tests/phpunit.xml new file mode 100644 index 00000000..9d5a1069 --- /dev/null +++ b/tests/phpunit.xml @@ -0,0 +1,58 @@ + + + + + + + ./SP + ./SP/Modules + + + ./SP/Modules + + + + + ../lib/SP + + ../lib/SP/DataModel + ../lib/SP/Html/Assets + ../lib/SP/Html/DataGrid + ../lib/SP/Config/ConfigData.php + + + + + + + + \ No newline at end of file diff --git a/tests/res/config/config.xml b/tests/res/config/config.xml index 9a6df428..f34b246b 100644 --- a/tests/res/config/config.xml +++ b/tests/res/config/config.xml @@ -9,11 +9,11 @@ 1 1 - 9a55c224e6cf0886bf4ddcf657f826bc7ea85c87 + 3a965d46f6da8fdf1fe749f137455863bdbe7409 0 0 - 1533969857 - 579424e820c8c2f327d6eb42a8f19e37464fc260 + 1535360745 + e623682d0999b924c0c70e03e8f42f2ff3806fe0 @@ -32,7 +32,7 @@ 0 - 3489b3a48cc900d02d5b6eefbdf29fc22296c288 + f247312233ce03616c1de4d4512e53963cb620ac PDF JPG diff --git a/tests/res/import/data_syspass_encrypted.xml b/tests/res/import/data_syspass_encrypted.xml new file mode 100644 index 00000000..11c4fcfa --- /dev/null +++ b/tests/res/import/data_syspass_encrypted.xml @@ -0,0 +1,17 @@ + + + + sysPass + 300.18082201 + + admin + + 77eac126d14f717b60bee5de7d78fb53ee512433 + + + ZGVmNTAyMDAwYjMyYWIxMjRjNmMzZjU0ZWE1Njg5YzM1MjcwN2I0YmEzZDYwMzE1NjFjYTk5NzA2NDI0NTc3OGIwMWMwNzQ3MjllOGVmOGFiOGEzYWE4YTE2OGE3NjhmY2RhODFhNTE0NTJjM2FjYWVmZGMyNjc4YjI3NWExMWI4MjI3MTliNjIzNmM3ZGZjYzg4YTNkYmY0MTQ0ODRkMmJkZGJjMDIzMzY5NDhkOTA2ODg1MjUyMmIzNjViY2Y2ZDAzM2VjZDdkMmFmZjljZDA4NmFiMzNjNTM3YTNlMmZkZmU4OGE1YmEwZGI0NjI4NDFjZDg0ODVjYzI0ODc1YTc1MTY5ZWZlZjY4MDk2NDI3NDRhYjhmMWVjZTQ3ZDg3ODQ1N2U4YjdiN2E2MGU1ZjM4N2M3OTg5ZGZkZTRmZDg2ZjJmMmRjODBhZTU4M2U4OWQwNWFjZGZiMzc0YzQxZjhkMTE4MzBkZDgwOWExNmE2MDJjMzgzZWUxOTM5ODdiN2M0NDA3YWM4MjcxZWM4M2NkMjViOWJhMjhlYzg2MzVkNjA5NTkwYzNiODA3ZDU3YWU5NzE2NjE2ZWEyNjQxYjFhMjY1MWVmNzhhNDc2M2EwYzljNDUyNzRiYTk2ZTZkMGRiMDUyZjM4MzM5ZDc2YzRjZjFhNjBjZWIyY2U2ZmUzOGQ3NjkxMTJmM2VlZmRkZjE0YWU3OTZmYmU0ODIxM2FiN2FhMDg1OTRmNzRlZTU4N2MxYTExODhjMGQ0MThhNzkwMDc5NDk1MGIwMGRlZmE5NDg0MmU4YTg3ZDA2MzViOTVhYjgwNzc3MjJiYjAxMjM2NDM4MjcyYzRhZmVmMTFkMDliNjA4Mjk5ZDY5NzJjOTFhMGI2MjUwM2I3OWJjZDRhN2NmMzZmMw== + ZGVmNTAyMDAwMmYwZmEzM2U5Mzc2ZDViNDRhNTFhNWM1ZTg5ZjVhYTUyMjkzYzczZDQ0MTM1YTY4ODI4OTAzMWJhZDQ1NTVjMmY2M2EzYmNlYzAwMzI5NzUwZDhmNzczMjA0MzQ1MDQ0MTVhZDQ1MDU3ODEzODM3ODhmYjM5YzhhMGVmYzVhNDJhY2JlMTQ1OWQzMmRmMDM1OWE2YmFiOWI2ZmZmYmNkYThiNzE2Y2QxMDQ0Y2IyNmFmNmY5Y2M3OWM2YTVkZGFhZTY0ZDFjMjYwYzkxYTIxMGI0ZDEwNjI4NTc3MTkwYTMwNjM4M2U2ZGQxYjNmNjRlMjE0MWFhNDhhOGVjMTkwNzg1NTllNDgwYWQ0ZGM2YzBmZjBmNGQzMThkMWM2MmI2MmFlYTBhM2FlZTJlNWVkN2NiMzhiNjI1MzE5MzllNTRlNmE3ODA3YjRhZTc4ZWI2ZTJhZWQ1NTkyNWMyY2MwMThhNTVjNzQ1MGIzMjFmYmQzNmY3NDNjYzdkNDZmMjA3ODU1ZjFjNzI4MjE1NWU0NGE4MDRhZTdiYTE1MTU0ZDIyMWVmMTQ5MjBiNmRmMjI2MzBiMWY5ODhjZjg4MDEyZDU4MzBkZjAyZWMwNDEyMzA0MmM2MmFjYTYwYTE1MTljNTFlMjJlY2E0ZDNiODI0YzkxM2RjMDMxOWNlMmI4NzcwMjdhMDgxMDhlYzVmMWYwMTVjZWZiMWYy + ZGVmNTAyMDA0NzY4NTRiYjAyMzZhNThmZWEzMjMzODQ3MmQ1NGQyOWJjYjQ5YWFkNTdkMGIzNzlmYmYyYmI2OWMxZmJlOTFhMzhlNGQ2MTE1YzNmNGExMTNlY2NlY2Y0ODE5MWU2YjZiNDFiODk0MzcxZmNhMTU1ZmU5MTAwNDUwYTc4N2UxM2NmODQzMTM5MjIyYTA4ZWUwNThlMDkwODMxYmJmZWMwNmUyZjFmNzY1NGNkMGIxYTc2OTllM2E4NmFmYzc2NmMwYjhkYTI1Y2FlNzMxNGFiNTE1ZGMwMzNhOTI3ODNmNjNjZGRhNDQwNmViNGRmMDgxYjYyYjRhNmZjN2NkZmYwZWNmZGI2ZWFhN2FjNDdkNDk5YjY4ZWNlNTVmNjhmYzdjNTVlOTUyNmIwNmI4MzY5NDlmOTYyN2QwMWE5ZjM4Y2ExNmYyZTY4NDA3NzE4YzdjYjhjNGRjMmE3NDRkNzMxMmI2NWQ4MDU2OWIzYWRmZjU1MTFmOTE4ZDZiMjNmZjAyYTg3MjFhMGNiYTk0OWFiOGYwNGM3N2MwNWEyNTVlNDY2YTNkNTE2ZGI5OGI0OGQzOGUwZWY3OThlNzc4NmIxYjdiNjlmZDA1NGRiM2VkMzgzOWEyOWE3YmU0ZjY3NzAwNWE1ZTY5MzAwMDhiOTVkYWYxNDFmZmVjN2I3ZDFiODliZjZiMTkxYmEzMDJhODIyODY3NWRmZjBjMDlkZGI1ZTk4OWE5ZjBmNjU5ZjU1NTI3NmJjZWE2MDg3YzJjZjcwMTIzZDEwODAwMzNlMmQwMDk0NWNkZGI4MmM4ZWQ4YTJlZDIwYjkz + ZGVmNTAyMDBjMjgzOGQ2M2Q3ZTU0N2FkODMyM2RmMWM5YTVkZjRiMmM0NDAzNTgwZDU0ODY5MDliYTMzZDY4NDY0ZmNiOTJlM2Q3Y2ZmNDk4YWMzMTg3ODY3Y2EwYzBhMTgzZWVlNDE2MmJlZDAxZTI3MzYwZDI3NDE4MjkwMTQ5ZTc1ZmY1ZDM2ZjM5MDIzZjAwZDI3NzA5NWJkODhhYzQ3NzU2YTlhYWRlNzRlYzhhYTY0YzBjOTBmNzYyMDgxYWY3NTY0MzYwOGM0NjMwNjg1NDU2NDZkMzM5YmY0NmQzODViOTk4Y2NhY2MxYzcyNzE1YjQ4ODc1NDZlYTQwMmRjZmM0ZDJlZjM2YjQ3NDAzMzkwNmUzNDBhMTY3N2I2MzNmOTYzYTg5Y2VlMWYyMzAyNWZhNGY0NDM0OGM4MTI0OWJiZTkxNWI2ZGJlNzdkYzNjYTE1MWU3NjcyYmVmY2M0Y2M1NmFkOWJjOTc0MWM3MDE1OGU4ZjhiZDQ0ODFjZTA5ZjRhZTdjMGFmMzBiOTU3ZjgwMzI3ZjEzZWU0YWY1OWVlNDUxODhmM2MwZDNkYzI2ZWNlMTdiYThiNzI4NGFjOWNiNmFmOTg2ZWQ3MDg5YzZlMjAxNTNhZGI4ZTFkMjkxMTgwNDA3OTYzNGFmNmZmZTJjN2I3MmVlNzU1MDlmMDg1YWVjODY5YjZmNzZkNDFkZmRhZGRkMGZlYTBjMzEyZTAxYWI0ZTc3MDUyNGFlZTY0YmVhYzI3N2JkNzRkMzAzMWNhNzhjMTdjMjNkNThhOTVhNTYxNDIzMjBlYTFmOTkwNDUzNTlmODI3NDczMmZiMmEwODc0YjFlNWIzZjViZWM0ZGI4OTA5OGFiMWU5Y2IxMmI2Yjg2NmNhZWJhZjNlYTI4ZTc4NDE2NmI5N2ViOGFjMTUxM2IzYTc1MDExMzc2ZmNmMzQyODhhZTQzNzBjYjNlNGYwOWVjYzM1OGVjYWQ4YTU2MmJiZTkwNDNiZTcyOTNlYzE0MzE3ZmM0MzEwN2JhOWEzYzM0NmY3NzI3ZWYzMjc1MTY5YTg4ZmQ0OWIxYTkxZWYwNTI0N2ExYmZkNjI3ZDQxYjczMmYwNzA2NDY4ZGMyMDJiYTEyYTI4ZmJlOGI5MDUxYTljMmQxMjUwNWZkMGU0YTIzM2Y5ZDc3MGU1YTc0NGQ1ZDQ4ODQwMDgxMjFhNWQ4OTJlMjJjNmQxYjY5MmM5ZTIwY2I5ZmY1ZDVlMTVkZjVkMjYyYzcxYmYzYmIyMDUzNTI1YjJlODFhNDkyZTk5ZjQzZWZjNDM0M2ViNTE4N2RlZWEwYzY0ZmU2MjM4ZThlNGM2ZDc5YWY5NzZjMmZhZTRmMmNjNzhmN2I0YjRjMTA4MzNiODNjYzNhODM4MTY2ZmQ1OTlhMjljYjdmYTI1NDU1ZTUzMGU2NjNjMDhhMTk0MjI3YmIxNDNkMzJiNDRlNjIzZTQ2MjdhYzIxNjA3ZGQyZGMxMjJiMjM0ZmM1NzAwYzcwYzMzNzIyMTk2M2YwYmI0YWI3ZTJmYjgwYmU2MTJkMDVjM2M4NjZhNmZmMzY4ZmM1MmVkZTUyMDUzOTIwOGE2MzUxMTYwNGViOWVmMmQ1NTIwMDczY2Q3OGM1NGEwOTE5MzE0NDMwYzRmYzkxZjUzZDdkNmI5MTA4OWNmMDA0ZjIyZGJlNmYwOTJhNmRlNzI1ZTAzNzIyNGM4N2Q2OGY0M2M3MmI5MTNjMzlmNGJhNzkzMjNmYTI5YjNkZWIyMjA2YzU0ZmYwYmJmNmQyN2Q3MGIxZTRhZTA0NGE3MmI1ZWRjMTU5ODFkOTRkODBhYmE3MDJiYmYxMWE2ZWQyOGNiMTNiODhhNGQzNmZlY2MyYzU1OGUxYjk4NzNhMjA1YmFjYjg0ZDY2ODQxODU3M2ViODJmMDI5YzQwYTgyOTBhNzI4N2MxMDBhNWIxMTBjOGNiNzZmOTg5NDM2YzdlYmMyOWU1MTU5NzFhMzJiMGJiNDY4MzU1MjFiYjAxZjUzYzA3MDU1NWE1M2QyMTljNjZiYzI4YTI5ZWM4Mzg0ZWRiMTQ5MDVkOTZjNjY5YjFhODRiYjRhNGI0MDVkYTIzMmMyMDk1ODQwYzBhZjc2MzFmZmM0YzIxNmJmNjdlYjVhN2ViOGNkNmY2OGU3MmQ3ZDVjZGNmZTc1MGE1ZDk2YzhkZjIzNGM2MjQwNTJhODM0NWM2Mzk1MGQ1MGYzNzFmNGMyM2YyNDJjZjZjODhjNDUzZWFlNGNmOGY4NzVjNGFkZjEzMGYwZjFhNGRhZDU2Nzc2NGMxM2Y2ZjEyNDc4ZTlkNzhkNTgxMDliODZlYjE4ZDA2ZjI3OWQxMjFlOWMwMjgxOGI3YmZlOTE5M2ViMjU3Zjg0Njg5YWJlMDcwNjIwZWU4ZjYyZmI0MjA4MTZhM2NkNjFkNDI0OGI3YjJmYzhmMGFlMjJhNjc4MmYxZTA1MTJiZGVmN2Y4ZTA5OTFhOTZlNTAxYTk2OTBiNmQ0ZjBjMTUwNmFlNDZkZGYyMWU1MDA2NjRjNzkwMTIzYjZiMzJkZWY4OTE3ZGU1YWY3OGIxMmNiNTUyNWNkM2E3YmY2MDc3MjA3ZjQxMGU3YTdiYzJjNTY0MjMzNmJjYThkNDliYjIwYzk1ODgyM2Q3MDU2N2I5Y2M5ZjA0MzdmOTljNzY0NzVhMDZiMDE1YWRmMGY0MWYyMWQ2ZWM5OTMxNzc1NDVmNWFkNDk1ZDU2OTY2YjBiYzA1NjAyZmYzMjM3MGU5OTFmODIwM2YzNjM2NWE0NTczMTIwNDdmN2ZlYzI4NzgwNTBlYjlhZTYwNjIyOWNkZjhjYTMwMmRiNDU2ODVkYWM2YWYyMDgzYTA5NjIzYmIwYmJiZmQ4ZTM5YzI3MmI2MmNkZTQ5MTVhZGRmZmI3NzRlMTEzNmNhNTcxNjAyM2ZmYjE2YTA1ZWI0MjYzNmI4NjU0NmIwZmExYjY2NzY0NzlkNDM2ZmRiMWQ3NDQ2ZWY1ZDZkNDY4OTA0MTFjY2ZkNzk2MzcxODkwNDhmOTA1NjFiZTVlZTA0MDMxMzJlMjZkYzFlODk0YmQwMTE0ODY2N2VhNDk3MGQwN2Q5NGNlYmNlYWFiYjM4MTgzMDAxMmZjOTMzYTBkZjIyN2Y2ZjFkZThhZjkyYWJjZTM2YjQzN2QzMmM1NTUzNDkwYzE4NzJhZmQzMjlkZjUyMDk2NDIyMWFhZmJhZjQ0YzA0YTdhM2Q5NDg3ZDI5NjZiZTVkMTYzYWQ3Y2Q1NjFjYTRjZDJiMjg1M2I0YjE0MzRlOTMzYjA5YTc2ODE3ZmM2NTZkZDY5MzhjN2I5NDI4ZDEwZjUzYWVkNDJlYmZjN2EyNWQyNmZlZGQzNzMwNjE4NDVjMGQ0NmJiOWUyNzA0YzFmM2I4MTUwMzA3Y2ZkNmNmYjRkZjdlMDdkZDNiNWMxMjJjMzYwOTM5ODg0YTMxZTgzNmUyMjRmZjc4MDFiMzA2OWM1MWE2NjdkNGE3MThkODA4Mzc4NmM5YmY1MzAyMWU3MmUzZmE5YjljZmY2M2MyYWE4MTE4MzlkMTdmZWIxNTE0OTU1ZGE5ZTkxMmExNWJiMTk3Nzc5YTUyMGY2MzllYjVlYzE2MzA1OWZmN2FjMWZmOTM2OWJjOTQxZDc5OTljYWIxNjhlMDM5ZDRiZDg5MjJlOGM2ZjQ0MzRjNDdlNTg3OGNkNTAzOWUyOTUyMDEzNzU3YWFhNTI4MWZkM2NkY2RjMzhlYTg4ZjZkZTdhMjkxNDJmYTc1YTkzNjJjNGYyMTNiZDc1ZjA0NTQ2ZGNlNDUzMzZiZTAwZmY2YTRhYzUxOGE4N2U5ZTk1ODFhYzA0YjhkZDhjMDRlNjEyZWQxNjY4MmI2NGQ0N2VlMTBjNGI0M2Y5MzU4ZmI0YmNmMDVjOGI2YzM0N2QwNTRmNDYxOWRjOTVmZTliZjI5MjhkMDE1MmJlZjk5MWU4NDc1NDU4ZjYyMzI4YzQ2ZDViNDhlNjJlODFjMDgxMTcxNmE4ODMxYTQ1NTVkNDljMmI4MjQ1NWYzOTE4YjQyNGFiZDYwYzc4N2U3YzJkOGQ2ZjVjZDIwY2IzYzYzOTUxZWMxY2RkODllZmJhZTA4YWM1NTBmMmY1ZmFjMGYyMzE0YWMwY2ZhMmI2ZThjMTYwMTA2OGM3YTI1ZDg2YzU2NjJlNDA5Y2Y4YjFmNzRlMGQ4OGRkNDAwMTExZGU0ZTdhMGU3N2VhY2EzZDEwZWI1NzRlNzYxYmE0NThjMGFlY2RiZGY0ZGRjYTMzOTk0ODQyMDNhNGE0MjI3YTA0YjBlZGM5YzBmZDcwZTZiOGY3YTQ2MWNkMTkyZWJjYWI2MTgwNTYzNjI3ODU2MWQxMWRhYWUyZmY1ZDdhZjg2MjBiNzllMmUxNjJmMzAyMDQxN2MzYzFmNjA0OWQ4OTZkMTk1ZDBkNTNmOTdkMTVlMjIwZWM5MDk5YzBiYmRhMjM0NTYwMjI4OGVhYWYxZWRkMzU4ZDcxN2VjZWIxOWRjOTcwYjUwNWQwOWI4MjkwMjk4NTYwMzc0NmE0YmVjZjQ4ODhjYTU1ZTAxMWMyZmNjZTExMWM3NWZlYmFmZjE2NjQyYTA5YTAzNDExZmJhZjQwOWIwOWM0YTMxZGJhMmY0ZGI4MmEzZWYyY2QyYzUzNTM0M2M1MGU0MzJkZjU0ZDI0OWFmYzQzNjRjMTAwMTMyMzhmMWRjYTNkMGEzNzI4YzA1NTQxMWEyM2VlZjQ3MWI5NTNkYTMyNzdkZWQwZDUyOWUwZmYzNzRlOTdiZjZkNzNjZGRlOTZmYWIwMjIyZDczOTA0NTQ3MGMxMjI0ZTA3NmJiNGE1YmQzMDlkNWU5OTlmMjNmYmYzZTExZmI2NDY2ZDdiNjZlZmNiM2I1ZWU5YWY5ODQ1ODQ0NzNmYzQ5MDIwZTUxMjJkNzBlMDAzNGQzZTZhYjQ5YTU3NTczNGY0OGE0ZTYyYmI0MWFhNzljMDhiMTgyYWQxYzBiYjk1MDBmNGJiM2JlNjBlYzkzZmM3YzE4N2RkODBmYzhjMzI2OWQwNWU2ZDAyYjdkMGRmOWFkMGZjOGQxMTM3YjYwYTUzNTdlMTI2Nzg2NTY4OTEyOTYyM2E0ZWIyYjY4MmZkMTQ1MDc1MDQyZGIwYWY0OGRiMDUwN2I3MDNiMmFjMzAwMTljYjVmNTJkNjViMTBiYjFhMTQ4NTMwNWE0YmI5NDliMzQ2YzQyNzAyYmMyOTUyNTAyZDgxYTJhMzlkN2JlOWRiYmNlMDRmM2RmYzhiZjA3 + + diff --git a/tests/res/import/data_syspass_invalid.xml b/tests/res/import/data_syspass_invalid.xml index cbf4e586..c522072d 100644 --- a/tests/res/import/data_syspass_invalid.xml +++ b/tests/res/import/data_syspass_invalid.xml @@ -1,27 +1,4 @@ - - sysPass diff --git a/tests/res/import/data_syspass_valid_hash.xml b/tests/res/import/data_syspass_valid_hash.xml new file mode 100644 index 00000000..8b326db9 --- /dev/null +++ b/tests/res/import/data_syspass_valid_hash.xml @@ -0,0 +1,91 @@ + + + + sysPass + 300.18082201 + + admin + + aa38d7292f6a00f3c16a19f99dd2940f04a2026a + + + + AWS + + + + GCP + + + + SSH + + + + Web + + + + + + Amazon + + + + Apple + + + + Google + + + + + + Apache + + + Email + + + JBoss + + + SaaS + + + SSH + + + Tomcat + + + + + Amazon SES + 3 + 2 + admin + https://aws.amazon.com/ + Simple Email Service + def502008fde3a27bb1a6023f1b4ec524ba147c80ae78f90f9b3d0637af6809ad9263afaa36d34237ded5e8803b53f17121bd5e2a66919c0ce21d27c9360dfbc39d8151df9cbb4aadd1a0daa83ff59181ce1f1535c4b93d2701fa72c662115e919 + def10000def502002937bbb81177ff4f769aeae126108783a141170588f3482fcbab44ae3390e80f85ab38521bafa8ec19648d267c9d46062294f5068a16706dcdb9042ddbb5b23ef54b3a12e7c5723b15d32ab9d8f5559e1fbc658c0b547a2a88a34b2498ef934d55395f857f28c9e3314493f319ebd4140d4a1b968e678cc12b58b5d2d057530be80f5f58c592cedcd85a90529d0895b11d6c04768bfbf4f1527babf5ee563798d35886f1c1017d1a3221cfd317cb84b13302d7d71c33e6753bcdb913dacd8909e195387f47b136a2789f85c48c3600f4ac6433a26e2bd0cae74fa2c461e4495108d340d7120febc65cfe79a4e2acc046f9bac29a0ce35cda + + + + + + Google GCP + 1 + 1 + admin + https://cloud.google.com/ + Google Cloud + def50200894e22b540a4975a3efe7dae669760aa6337195c690ac79ebff28f03393ae1070c5c7a635fa5a9aee5059df912c1948c41d8198f24f9f892a728d400d12d200c184a793d03a3f13eebfa45614efd0004ad7ea83338d1a04e20e6846078 + def10000def50200f3d572936f4496e90369f6cc1feadce57c803b01a78c64b5987efd6369f7ecf526494a148d0e056feafe60d903bbb65ea9f79ad9b4f7ad42c7fe3c9c586f1807d252444c42667129da3727cf6f702a5aadf5db2391ba4a581f950df65262ae04b314b88d69d3174e6f226cb1f939f04d102799e58e0b6ed839fe2282056c58069e6298865c386e3d2114635621ed14eb199b1dad6dfcabc9b364ea2ae147c38352cd72bc0c79761a9df0f58690d5da1d1e3cc5e17261d740ca6863383a869b0253790d46ba2df032e741e8bb788033d8eb7b97d124d58b3c4310d15df7a4fd4d373dcc0ae111d46f6d623bac7ccf330520439736b223ae81 + + + + + +