* [ADD] Install CLI command tests.

* [MOD] Install CLI command refactoring.
* [MOD] Minor code tweaks.

Signed-off-by: Rubén D <nuxsmin@syspass.org>
This commit is contained in:
Rubén D
2021-09-19 21:32:34 +02:00
parent 33c381a1e1
commit 600c398bb8
35 changed files with 1476 additions and 589 deletions

1
.gitignore vendored
View File

@@ -61,7 +61,6 @@ doc/*
build/*
tests/_output/*
.phpstorm.meta.php
composer.phar
.env

5
.phpstorm.meta.php Normal file
View File

@@ -0,0 +1,5 @@
<?php
namespace PHPSTORM_META {
override(\Psr\Container\ContainerInterface::get(0), type(0));
}

View File

@@ -1,10 +1,10 @@
<?php
/**
/*
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2019, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -19,7 +19,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
define('APP_ROOT', __DIR__);

View File

@@ -1,4 +1,26 @@
<?php
/*
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
* sysPass is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sysPass is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SP\Modules\Cli\Commands;
@@ -6,12 +28,11 @@ use Psr\Log\LoggerInterface;
use SP\Config\Config;
use SP\Config\ConfigData;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Style\SymfonyStyle;
/**
* Class CommandBase
*
* @package SPDecrypter\Commands
* @package SP\Modules\Cli\Commands
*/
abstract class CommandBase extends Command
{
@@ -19,10 +40,7 @@ abstract class CommandBase extends Command
* @var LoggerInterface
*/
protected $logger;
/**
* @var SymfonyStyle
*/
protected $io;
/**
* @var Config
*/
@@ -36,19 +54,17 @@ abstract class CommandBase extends Command
* CommandBase constructor.
*
* @param LoggerInterface $logger
* @param SymfonyStyle $io
* @param Config $config
*/
public function __construct(
LoggerInterface $logger,
SymfonyStyle $io,
Config $config)
Config $config
)
{
parent::__construct();
$this->logger = $logger;
$this->io = $io;
$this->config = $config;
$this->configData = $this->config->getConfigData();
parent::__construct();
}
}

View File

@@ -24,18 +24,22 @@
namespace SP\Modules\Cli\Commands;
use Closure;
use Exception;
use Psr\Log\LoggerInterface;
use RuntimeException;
use SP\Config\Config;
use SP\Core\Exceptions\InstallError;
use SP\Core\Exceptions\InvalidArgumentException;
use SP\Core\Language;
use SP\Services\Install\InstallData;
use SP\Services\Install\Installer;
use SP\Util\Util;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\StyleInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
/**
@@ -45,6 +49,25 @@ use Symfony\Component\Console\Style\SymfonyStyle;
*/
final class InstallCommand extends CommandBase
{
/**
* @var string[]
*/
public static $envVarsMapping = [
'adminLogin' => 'ADMIN_LOGIN',
'adminPassword' => 'ADMIN_PASSWORD',
'databaseHost' => 'DATABASE_HOST',
'databaseName' => 'DATABASE_NAME',
'databaseUser' => 'DATABASE_USER',
'databasePassword' => 'DATABASE_PASSWORD',
'masterPassword' => 'MASTER_PASSWORD',
'hostingMode' => 'HOSTING_MODE',
'language' => 'LANGUAGE',
'forceInstall' => 'FORCE_INSTALL',
'install' => 'INSTALL'
];
/**
* @var string
*/
protected static $defaultName = 'sp:install';
/**
* @var Installer
@@ -52,30 +75,29 @@ final class InstallCommand extends CommandBase
private $installer;
public function __construct(LoggerInterface $logger,
SymfonyStyle $io,
Config $config,
Installer $installer)
Config $config,
Installer $installer)
{
parent::__construct($logger, $io, $config);
parent::__construct($logger, $config);
$this->installer = $installer;
}
protected function configure()
protected function configure(): void
{
$this->setDescription(__('Install sysPass.'))
->setHelp(__('This command installs sysPass.'))
$this->setDescription(__('Install sysPass'))
->setHelp(__('This command installs sysPass'))
->addArgument('adminLogin',
InputArgument::REQUIRED,
InputArgument::OPTIONAL,
__('Admin user to log into the application'))
->addArgument('databaseHost',
InputArgument::REQUIRED,
InputArgument::OPTIONAL,
__('Server name to install sysPass database'))
->addArgument('databaseName',
InputArgument::REQUIRED,
InputArgument::OPTIONAL,
__('Application database name. eg. syspass'))
->addArgument('databaseUser',
InputArgument::REQUIRED,
InputArgument::OPTIONAL,
__('An user with database administrative rights'))
->addOption('databasePassword',
null,
@@ -91,41 +113,79 @@ final class InstallCommand extends CommandBase
__('Master password to encrypt the passwords'))
->addOption('hostingMode',
null,
InputOption::VALUE_OPTIONAL,
__('It does not create or verify the user\'s permissions on the DB'),
false)
InputOption::VALUE_NONE,
__('It does not create or verify the user\'s permissions on the DB'))
->addOption('language',
null,
InputOption::VALUE_OPTIONAL,
__('Sets the global app language. You can set a per user language on preferences.'))
->addOption('force',
__('Sets the global app language. You can set a per user language on preferences'))
->addOption('forceInstall',
null,
InputOption::VALUE_OPTIONAL,
__('Force sysPass installation.'),
false);
InputOption::VALUE_NONE,
__('Force sysPass installation'))
->addOption('install',
null,
InputOption::VALUE_NONE,
__('Skip asking to confirm the installation'));
}
/**
* @param InputInterface $input
* @param OutputInterface $output
*
* @return int|void
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$force = (bool)$input->getOption('force');
$style = new SymfonyStyle($input, $output);
if ($this->configData->isInstalled() && $force === false) {
$this->logger->warning(__u('sysPass is already installed'));
try {
$installData = $this->getInstallData($input, $style);
$this->io->warning(__('sysPass is already installed. Use \'--force\' to install it again.'));
$forceInstall = $this->getForceInstall($input);
return self::FAILURE;
if (!$forceInstall || !$this->getInstall($input, $style)) {
$this->logger->debug(__u('Installation aborted'));
$style->info(__('Installation aborted'));
return self::FAILURE;
}
$this->installer->run($installData);
$this->logger->info(__('Installation finished'));
$style->success(__('Installation finished'));
return self::SUCCESS;
} catch (InstallError $e) {
$this->logger->error($e->getMessage());
$style->error(__($e->getMessage()));
} catch (InvalidArgumentException $e) {
$this->logger->warning($e->getMessage());
$style->warning(__($e->getMessage()));
} catch (Exception $e) {
$this->logger->error($e->getTraceAsString());
$this->logger->error($e->getMessage());
$style->error(__($e->getMessage()));
}
$adminPassword = $input->getOption('adminPassword');
return self::FAILURE;
}
$passNonEmptyValidator = function ($value) {
/**
* @param InputInterface $input
* @param StyleInterface $style
*
* @return InstallData
* @throws InstallError
*/
private function getInstallData(InputInterface $input, StyleInterface $style): InstallData
{
$passNotEmptyValidator = function ($value) {
if (empty($value)) {
throw new RuntimeException(__('Password cannot be blank'));
}
@@ -133,83 +193,258 @@ final class InstallCommand extends CommandBase
return $value;
};
if (empty($adminPassword)) {
$adminPassword = $this->getAdminPassword($input, $style, $passNotEmptyValidator);
$masterPassword = $this->getMasterPassword($input, $style, $passNotEmptyValidator);
$databasePassword = $this->getDatabasePassword($input, $style);
$language = $this->getLanguage($input, $style);
$hostingMode = $this->isHostingMode($input);
$adminLogin = self::getEnvVarOrArgument('adminLogin', $input);
$databaseUser = self::getEnvVarOrArgument('databaseUser', $input);
$databaseName = self::getEnvVarOrArgument('databaseName', $input);
$databaseHost = self::getEnvVarOrArgument('databaseHost', $input);
$installData = new InstallData();
$installData->setSiteLang($language);
$installData->setAdminLogin($adminLogin);
$installData->setAdminPass($adminPassword);
$installData->setMasterPassword($masterPassword);
$installData->setDbAdminUser($databaseUser);
$installData->setDbAdminPass($databasePassword);
$installData->setDbName($databaseName);
$installData->setDbHost($databaseHost);
$installData->setHostingMode($hostingMode);
return $installData;
}
/**
* @param InputInterface $input
* @param StyleInterface $style
* @param Closure $passNotEmptyValidator
*
* @return array|false|mixed|string
* @throws InstallError
*/
private function getAdminPassword(
InputInterface $input,
StyleInterface $style,
Closure $passNotEmptyValidator
)
{
$option = 'adminPassword';
$password =
self::getEnvVarForOption($option)
?: $input->getOption($option);
if (empty($password)) {
$this->logger->debug(__u('Ask for admin password'));
$adminPassword = $this->io->askHidden(__('Please provide sysPass admin\'s password'), $passNonEmptyValidator);
$adminPasswordRepeat = $this->io->askHidden(__('Please provide sysPass admin\'s password again'), $passNonEmptyValidator);
$password = $style->askHidden(
__('Please provide sysPass admin\'s password'),
$passNotEmptyValidator
);
if ($adminPassword !== $adminPasswordRepeat) {
$this->io->warning(__('Passwords do not match'));
$passwordRepeat = $style->askHidden(
__('Please provide sysPass admin\'s password again'),
$passNotEmptyValidator
);
return self::FAILURE;
if ($password !== $passwordRepeat) {
throw new InstallError(__u('Passwords do not match'));
} elseif (null === $password || null === $passwordRepeat) {
throw new InstallError(sprintf(__u('%s cannot be blank'), 'Admin password'));
}
}
$masterPassword = $input->getOption('masterPassword');
return $password;
}
if (empty($masterPassword)) {
/**
* @param InputInterface $input
* @param StyleInterface $style
* @param Closure $passNotEmptyValidator
*
* @return array|false|mixed|string
* @throws InstallError
*/
private function getMasterPassword(
InputInterface $input,
StyleInterface $style,
Closure $passNotEmptyValidator
)
{
$password = self::getEnvVarOrOption('masterPassword', $input);
if (empty($password)) {
$this->logger->debug(__u('Ask for master password'));
$masterPassword = $this->io->askHidden(__('Please provide sysPass master password'), $passNonEmptyValidator);
$masterPasswordRepeat = $this->io->askHidden(__('Please provide sysPass master password again'), $passNonEmptyValidator);
$password = $style->askHidden(
__('Please provide sysPass master password'),
$passNotEmptyValidator
);
$passwordRepeat = $style->askHidden(
__('Please provide sysPass master password again'),
$passNotEmptyValidator
);
if ($masterPassword !== $masterPasswordRepeat) {
$this->io->warning(__('Passwords do not match'));
return self::FAILURE;
if ($password !== $passwordRepeat) {
throw new InstallError(__u('Passwords do not match'));
} elseif (null === $password || null === $passwordRepeat) {
throw new InstallError(sprintf(__u('%s cannot be blank'), 'Master password'));
}
}
$databasePassword = $input->getOption('databasePassword');
return $password;
}
if (empty($databasePassword)) {
/**
* @param string $option
* @param InputInterface $input
*
* @return array|false|mixed|string
*/
private static function getEnvVarOrOption(
string $option,
InputInterface $input
)
{
return self::getEnvVarForOption($option)
?: $input->getOption($option);
}
/**
* @param string $option
*
* @return string|false
*/
public static function getEnvVarForOption(string $option)
{
return getenv(self::$envVarsMapping[$option]);
}
/**
* @param InputInterface $input
* @param StyleInterface $style
*
* @return array|false|mixed|string
*/
private function getDatabasePassword(
InputInterface $input,
StyleInterface $style
)
{
$password = self::getEnvVarOrOption('databasePassword', $input);
if (empty($password)) {
$this->logger->debug(__u('Ask for database password'));
$databasePassword = $this->io->askHidden(__('Please provide database admin password'));
$password = $style->askHidden(__('Please provide database admin password'));
}
$language = $input->getOption('language');
return $password;
}
/**
* @param InputInterface $input
* @param StyleInterface $style
*
* @return array|false|mixed|string
*/
private function getLanguage(
InputInterface $input,
StyleInterface $style
)
{
$language = self::getEnvVarOrOption('language', $input);
if (empty($language)) {
$this->logger->debug(__u('Ask for language'));
$language = $this->io->choice(__('Language'), array_keys(Language::getAvailableLanguages()), 'en_US');
$language = $style->choice(
__('Language'),
array_keys(Language::getAvailableLanguages()),
'en_US'
);
}
$install = $this->io->confirm(__('Install sysPass?'), false);
return $language;
}
if (!$install) {
$this->logger->debug(__u('Installation aborted'));
/**
* @param InputInterface $input
*
* @return bool
*/
private function isHostingMode(InputInterface $input): bool
{
$option = 'hostingMode';
return self::SUCCESS;
$envHostingMode = self::getEnvVarForOption($option);
return $envHostingMode !== false
? Util::boolval($envHostingMode)
: $input->getOption($option);
}
/**
* @param string $argument
* @param InputInterface $input
*
* @return array|false|mixed|string
*/
private static function getEnvVarOrArgument(
string $argument,
InputInterface $input
)
{
return self::getEnvVarForOption($argument)
?: $input->getArgument($argument);
}
/**
* @param InputInterface $input
*
* @return bool
* @throws InstallError
*/
private function getForceInstall(InputInterface $input): bool
{
$option = 'forceInstall';
$envForceInstall = self::getEnvVarForOption($option);
$force = $envForceInstall !== false
? Util::boolval($envForceInstall)
: $input->getOption($option);
if ($force === false && $this->configData->isInstalled()) {
throw new InstallError(__u('sysPass is already installed. Use \'--forceInstall\' to install it again.'));
}
$installData = new InstallData();
$installData->setSiteLang($language);
$installData->setAdminLogin($input->getArgument('adminLogin'));
$installData->setAdminPass($adminPassword);
$installData->setMasterPassword($masterPassword);
$installData->setDbAdminUser($input->getArgument('databaseUser'));
$installData->setDbAdminPass($databasePassword);
$installData->setDbName($input->getArgument('databaseName'));
$installData->setDbHost($input->getArgument('databaseHost'));
$installData->setHostingMode((bool)$input->getOption('hostingMode'));
return $force;
}
try {
$this->installer->run($installData);
/**
* @param InputInterface $input
* @param StyleInterface $style
*
* @return bool
*/
private function getInstall(InputInterface $input, StyleInterface $style): bool
{
$option = 'install';
$this->io->success(__('Installation finished'));
$envInstall = self::getEnvVarForOption($option);
$this->logger->info(__u('Installation finished'));
return self::SUCCESS;
} catch (InvalidArgumentException $e) {
$this->io->error(__($e->getMessage()));
} catch (Exception $e) {
$this->logger->error($e->getTraceAsString());
$this->logger->error($e->getMessage());
$install = $envInstall !== false
? Util::boolval($envInstall)
: $input->getOption($option);
if ($install === false) {
return $style->confirm(__('Install sysPass?'), false);
}
return self::FAILURE;
return true;
}
}

View File

@@ -24,20 +24,15 @@
namespace SP\Modules\Cli;
use Defuse\Crypto\Exception\EnvironmentIsBrokenException;
use DI\DependencyException;
use DI\NotFoundException;
use Exception;
use Psr\Container\ContainerInterface;
use SP\Core\Context\ContextException;
use SP\Core\Context\StatelessContext;
use SP\Core\Exceptions\InitializationException;
use SP\Core\Language;
use SP\Core\ModuleBase;
use SP\Modules\Cli\Commands\InstallCommand;
use SP\Services\Upgrade\UpgradeAppService;
use SP\Services\Upgrade\UpgradeDatabaseService;
use SP\Services\Upgrade\UpgradeUtil;
use SP\Storage\File\FileException;
use SP\Util\VersionUtil;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Input\InputInterface;
@@ -62,7 +57,7 @@ final class Init extends ModuleBase
*/
protected $language;
/**
* @var mixed|Application
* @var Application
*/
protected $application;
@@ -106,8 +101,9 @@ final class Init extends ModuleBase
/**
* @throws DependencyException
* @throws NotFoundException
* @throws Exception
*/
private function initCli()
private function initCli(): void
{
$this->application->setName('sysPass CLI');
$this->application->setVersion(implode('.', VersionUtil::getVersionArray()));
@@ -121,38 +117,4 @@ final class Init extends ModuleBase
$this->container->get(OutputInterface::class)
);
}
/**
* Comprueba que la aplicación esté instalada
* Esta función comprueba si la aplicación está instalada. Si no lo está, redirige al instalador.
*
* @throws InitializationException
*/
private function checkInstalled()
{
if (!$this->configData->isInstalled()) {
throw new InitializationException('Not installed');
}
}
/**
* Comprobar si es necesario actualizar componentes
*
* @throws EnvironmentIsBrokenException
* @throws FileException
* @throws InitializationException
*/
private function checkUpgrade()
{
UpgradeUtil::fixAppUpgrade($this->configData, $this->config);
if ($this->configData->getUpgradeKey()
|| (UpgradeDatabaseService::needsUpgrade($this->configData->getDatabaseVersion()) ||
UpgradeAppService::needsUpgrade($this->configData->getAppVersion()))
) {
$this->config->generateUpgradeKey();
throw new InitializationException(__u('Updating needed'));
}
}
}

View File

@@ -32,13 +32,11 @@ use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use function DI\autowire;
use function DI\create;
use function DI\factory;
return [
LoggerInterface::class => function (ContainerInterface $c) {
LoggerInterface::class => static function (ContainerInterface $c) {
$logger = $c->get(Logger::class);
$logger->pushHandler(new StreamHandler(LOG_FILE));
@@ -46,13 +44,7 @@ return [
},
Application::class => create(Application::class),
OutputInterface::class => create(ConsoleOutput::class)
->constructor(ConsoleOutput::VERBOSITY_NORMAL, true),
->constructor(OutputInterface::VERBOSITY_NORMAL, true),
InputInterface::class => create(ArgvInput::class),
SymfonyStyle::class => factory(function (ContainerInterface $c) {
return new SymfonyStyle(
$c->get(InputInterface::class),
$c->get(OutputInterface::class)
);
}),
InstallCommand::class => autowire()
];

View File

@@ -19,7 +19,7 @@
},
"require": {
"roave/security-advisories": "dev-master",
"php": "~7.3 || ~7.4",
"php": "~7.3 || ~7.4 || ~8.0",
"defuse/php-encryption": "^2.1",
"phpmailer/phpmailer": "^6.0",
"ademarre/binary-to-text-php": "dev-master",

892
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -54,12 +54,11 @@ return [
Request::class => create(Request::class)
->constructor(\Klein\Request::createFromGlobals()),
ContextInterface::class => function (ContainerInterface $c) {
switch (APP_MODULE) {
case 'web':
return $c->get(SessionContext::class);
default:
return $c->get(StatelessContext::class);
if (APP_MODULE === 'web') {
return $c->get(SessionContext::class);
}
return $c->get(StatelessContext::class);
},
Config::class => function (ContainerInterface $c) {
return new Config(

View File

@@ -46,7 +46,7 @@ final class Config
/**
* Cache file name
*/
const CONFIG_CACHE_FILE = CACHE_PATH . DIRECTORY_SEPARATOR . 'config.cache';
public const CONFIG_CACHE_FILE = CACHE_PATH . DIRECTORY_SEPARATOR . 'config.cache';
/**
* @var int
*/

View File

@@ -0,0 +1,35 @@
<?php
/*
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
* sysPass is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sysPass is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SP\Core\Exceptions;
/**
* Class InstallError
*
* @package SP\Core\Exceptions
*/
final class InstallError extends SPException
{
}

View File

@@ -71,7 +71,7 @@ class ItemPresetData extends DataModelBase implements HydratableInterface
*/
public function getId(): int
{
return $this->id !== null ? (int)$this->id : null;
return $this->id ?? 0;
}
/**

View File

@@ -25,7 +25,6 @@
namespace SP\Services\Install;
use Defuse\Crypto\Exception\EnvironmentIsBrokenException;
use Exception;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
@@ -60,9 +59,9 @@ final class Installer extends Service
/**
* sysPass' version and build number
*/
const VERSION = [3, 2, 0];
const VERSION_TEXT = '3.2';
const BUILD = 20062901;
public const VERSION = [3, 2, 0];
public const VERSION_TEXT = '3.2';
public const BUILD = 20062901;
/**
* @var DatabaseSetupInterface
@@ -203,7 +202,11 @@ final class Installer extends Service
*/
private function setupDbHost()
{
if (preg_match('/^(?:(?P<host>.*):(?P<port>\d{1,5}))|^(?:unix:(?P<socket>.*))/', $this->installData->getDbHost(), $match)) {
if (preg_match(
'/^(?:(?P<host>.*):(?P<port>\d{1,5}))|^(?:unix:(?P<socket>.*))/',
$this->installData->getDbHost(),
$match)
) {
if (!empty($match['socket'])) {
$this->installData->setDbSocket($match['socket']);
} else {

View File

@@ -26,6 +26,7 @@ namespace SP\Storage\Database;
use Exception;
use PDO;
use SP\Core\Exceptions\SPException;
defined('APP_ROOT') || die();
@@ -36,9 +37,9 @@ defined('APP_ROOT') || die();
*/
final class MySQLHandler implements DBStorageInterface
{
const STATUS_OK = 0;
const STATUS_KO = 1;
const PDO_OPTS = [
public const STATUS_OK = 0;
public const STATUS_KO = 1;
public const PDO_OPTS = [
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_FOUND_ROWS => true,
@@ -97,7 +98,7 @@ final class MySQLHandler implements DBStorageInterface
) {
throw new DatabaseException(
__u('Unable to connect to DB'),
DatabaseException::CRITICAL,
SPException::CRITICAL,
__u('Please, check the connection parameters'));
}
@@ -117,7 +118,7 @@ final class MySQLHandler implements DBStorageInterface
} catch (Exception $e) {
throw new DatabaseException(
__u('Unable to connect to DB'),
DatabaseException::CRITICAL,
SPException::CRITICAL,
sprintf('Error %s: %s', $e->getCode(), $e->getMessage()),
$e->getCode(),
$e
@@ -161,22 +162,29 @@ final class MySQLHandler implements DBStorageInterface
public function getConnectionSimple(): PDO
{
if (!$this->db) {
if (null === $this->connectionData->getDbHost() && null === $this->connectionData->getDbSocket()) {
if (null === $this->connectionData->getDbHost()
&& null === $this->connectionData->getDbSocket()
) {
throw new DatabaseException(
__u('Unable to connect to DB'),
DatabaseException::CRITICAL,
SPException::CRITICAL,
__u('Please, check the connection parameters'));
}
try {
$opts = [PDO::ATTR_EMULATE_PREPARES => true, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION];
$this->db = new PDO($this->getConnectionUri(), $this->connectionData->getDbUser(), $this->connectionData->getDbPass(), $opts);
$this->db = new PDO(
$this->getConnectionUri(),
$this->connectionData->getDbUser(),
$this->connectionData->getDbPass(),
$opts
);
$this->dbStatus = self::STATUS_OK;
} catch (Exception $e) {
throw new DatabaseException(
__u('Unable to connect to DB'),
DatabaseException::CRITICAL,
SPException::CRITICAL,
sprintf('Error %s: %s', $e->getCode(), $e->getMessage()),
$e->getCode(),
$e

View File

@@ -139,7 +139,7 @@ final class Util
// not strict? let the regular php bool check figure it out (will
// largely default to true)
return ($in ? true : false);
return (bool)$in;
}
/**

View File

@@ -1,10 +1,10 @@
<?php
/**
/*
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -19,7 +19,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SP\Tests;

View File

@@ -1,10 +1,10 @@
<?php
/**
/*
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -19,7 +19,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SP\Tests;
@@ -44,26 +44,31 @@ class DatabaseUtil
*
* @throws DatabaseException
*/
public static function createUser($user, $pass, $database, $host)
public static function createUser(
string $user,
string $pass,
string $database,
string $host
): void
{
$query = 'GRANT ALL PRIVILEGES ON `%s`.* TO \'%s\'@\'%s\' IDENTIFIED BY \'%s\'';
$conn = self::getConnection();
$conn->query(sprintf($query, $database, $user, SELF_IP_ADDRESS, $pass));
$conn->exec(sprintf($query, $database, $user, SELF_IP_ADDRESS, $pass));
// Long hostname returned on Travis CI
if (getenv('TRAVIS') === false) {
$conn->query(sprintf($query, $database, $user, SELF_HOSTNAME, $pass));
$conn->exec(sprintf($query, $database, $user, SELF_HOSTNAME, $pass));
}
$conn->query(sprintf($query, $database, $user, $host, $pass));
$conn->exec(sprintf($query, $database, $user, $host, $pass));
}
/**
* @return PDO
* @throws DatabaseException
*/
public static function getConnection()
public static function getConnection(): PDO
{
$data = (new DatabaseConnectionData())
->setDbHost(getenv('DB_SERVER'))
@@ -77,11 +82,11 @@ class DatabaseUtil
* @param string $user
* @param string $host
*/
public static function dropUser($user, $host)
public static function dropUser(string $user, string $host): void
{
try {
self::getConnection()
->query(sprintf('DROP USER \'%s\'@\'%s\'', $user, $host));
->exec(sprintf('DROP USER \'%s\'@\'%s\'', $user, $host));
} catch (Exception $e) {
processException($e);
}
@@ -92,10 +97,10 @@ class DatabaseUtil
*
* @throws DatabaseException
*/
public static function dropDatabase($database)
public static function dropDatabase(string $database): void
{
self::getConnection()
->query(sprintf('DROP DATABASE IF EXISTS `%s`', $database));
->exec(sprintf('DROP DATABASE IF EXISTS `%s`', $database));
}
/**
@@ -103,9 +108,9 @@ class DatabaseUtil
*
* @throws DatabaseException
*/
public static function createDatabase($database)
public static function createDatabase(string $database): void
{
self::getConnection()
->query(sprintf('CREATE DATABASE `%s`', $database));
->exec(sprintf('CREATE DATABASE `%s`', $database));
}
}

View File

@@ -2,9 +2,9 @@
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*

View File

@@ -2,9 +2,9 @@
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*

View File

@@ -0,0 +1,61 @@
<?php
/*
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
* sysPass is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sysPass is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SP\Tests\Modules\Cli;
use DI\ContainerBuilder;
use Exception;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
/**
* Class CliTestCase
*
* @package SP\Tests\Modules\Cli
*/
abstract class CliTestCase extends TestCase
{
/**
* @var ContainerInterface
*/
protected static $dic;
/**
* This method is called before the first test of this test class is run.
*
* @throws Exception
*/
public static function setUpBeforeClass(): void
{
parent::setUpBeforeClass();
$builder = new ContainerBuilder();
$builder->addDefinitions(
APP_ROOT . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'Definitions.php',
MODULES_PATH . DIRECTORY_SEPARATOR . 'cli' . DIRECTORY_SEPARATOR . 'definitions.php'
);
self::$dic = $builder->build();
}
}

View File

@@ -0,0 +1,382 @@
<?php
/*
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
* sysPass is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sysPass is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SP\Tests\Modules\Cli\Commands;
use DI\DependencyException;
use DI\NotFoundException;
use Exception;
use SP\Config\Config;
use SP\Modules\Cli\Commands\InstallCommand;
use SP\Storage\Database\DatabaseException;
use SP\Tests\DatabaseUtil;
use SP\Tests\Modules\Cli\CliTestCase;
use Symfony\Component\Console\Tester\CommandTester;
use function SP\Tests\getResource;
use function SP\Tests\recreateDir;
use function SP\Tests\saveResource;
/**
*
*/
class InstallCommandTest extends CliTestCase
{
/**
* @var string
*/
protected static $currentConfig;
/**
* @var string[]
*/
private static $commandInputData = [
'adminLogin' => 'Admin',
'databaseHost' => 'localhost',
'databaseName' => 'syspass-test-install',
'databaseUser' => 'syspass_user',
'--databasePassword' => 'test123',
'--adminPassword' => 'admin123',
'--masterPassword' => '12345678900',
'--install' => null,
];
/**
* This method is called before the first test of this test class is run.
*
* @throws Exception
*/
public static function setUpBeforeClass(): void
{
// Backup current config file content in a variable
self::$currentConfig = getResource('config', 'config.xml');
parent::setUpBeforeClass();
}
/**
* This method is called after the last test of this test class is run.
*/
public static function tearDownAfterClass(): void
{
// Replace config file with previously saved data
saveResource('config', 'config.xml', self::$currentConfig);
// Recreate cache directory to avoid unwanted behavior
recreateDir(CACHE_PATH);
parent::tearDownAfterClass();
}
/**
* @throws DependencyException
* @throws NotFoundException
*/
public function testInstallationIsAborted(): void
{
$commandTester = $this->executeCommandTest();
// the output of the command in the console
$output = $commandTester->getDisplay();
$this->assertStringContainsString('Installation aborted', $output);
}
/**
* @param array|null $inputData
* @param bool $useInputData
*
* @return CommandTester
* @throws DependencyException
* @throws NotFoundException
*/
private function executeCommandTest(
?array $inputData = null,
bool $useInputData = true
): CommandTester
{
$installCommand = self::$dic->get(InstallCommand::class);
if (null === $inputData && $useInputData) {
$inputData = self::$commandInputData;
}
$commandTester = new CommandTester($installCommand);
$commandTester->execute(
$inputData ?? [],
['interactive' => false]
);
return $commandTester;
}
/**
* @throws DependencyException
* @throws NotFoundException
*/
public function testNoDatabaseConnection(): void
{
$inputData = array_merge(
self::$commandInputData,
['--forceInstall' => null]
);
$commandTester = $this->executeCommandTest($inputData);
// the output of the command in the console
$output = $commandTester->getDisplay();
$this->assertStringContainsString('Unable to connect to DB', $output);
}
/**
* @throws DependencyException
* @throws NotFoundException
*/
public function testEmptyAdminPassword(): void
{
$inputData = array_merge(
self::$commandInputData,
['--adminPassword' => '']
);
$commandTester = $this->executeCommandTest($inputData);
// the output of the command in the console
$output = $commandTester->getDisplay();
$this->assertStringContainsString('Admin password cannot be blank', $output);
}
/**
* @throws DependencyException
* @throws NotFoundException
*/
public function testEmptyMasterPassword(): void
{
$inputData = array_merge(
self::$commandInputData,
['--masterPassword' => '']
);
$commandTester = $this->executeCommandTest($inputData);
// the output of the command in the console
$output = $commandTester->getDisplay();
$this->assertStringContainsString('Master password cannot be blank', $output);
}
/**
* @throws DependencyException
* @throws NotFoundException
* @throws DatabaseException
*/
public function testInstallIsSuccessful(): void
{
$inputData = array_merge(
self::$commandInputData,
[
'databaseHost' => getenv('DB_SERVER'),
'databaseUser' => getenv('DB_USER'),
'--databasePassword' => getenv('DB_PASS'),
'--forceInstall' => null
]
);
$commandTester = $this->executeCommandTest($inputData);
// the output of the command in the console
$output = $commandTester->getDisplay();
$this->assertStringContainsString('Installation finished', $output);
$configData = self::$dic->get(Config::class)->getConfigData();
// Cleanup database
DatabaseUtil::dropDatabase(self::$commandInputData['databaseName']);
DatabaseUtil::dropUser($configData->getDbUser(), SELF_IP_ADDRESS);
}
/**
* @throws DependencyException
* @throws NotFoundException
* @throws DatabaseException
*/
public function testInstallAndLanguageIsSet(): void
{
$inputData = array_merge(
self::$commandInputData,
[
'databaseHost' => getenv('DB_SERVER'),
'databaseUser' => getenv('DB_USER'),
'--databasePassword' => getenv('DB_PASS'),
'--language' => 'es_ES',
'--forceInstall' => null
]
);
$commandTester = $this->executeCommandTest($inputData);
// the output of the command in the console
$output = $commandTester->getDisplay();
$this->assertStringContainsString('Installation finished', $output);
$configData = self::$dic->get(Config::class)->getConfigData();
$this->assertEquals($configData->getSiteLang(), $inputData['--language']);
// Cleanup database
DatabaseUtil::dropDatabase(self::$commandInputData['databaseName']);
DatabaseUtil::dropUser($configData->getDbUser(), SELF_IP_ADDRESS);
}
/**
* @throws DependencyException
* @throws NotFoundException
* @throws DatabaseException
*/
public function testInstallAndHostingModeIsUsed(): void
{
$databaseUser = 'syspass';
$databasePassword = 'syspass123';
DatabaseUtil::createDatabase(self::$commandInputData['databaseName']);
DatabaseUtil::createUser(
$databaseUser,
$databasePassword,
self::$commandInputData['databaseName'],
getenv('DB_SERVER')
);
$inputData = array_merge(
self::$commandInputData,
[
'databaseHost' => getenv('DB_SERVER'),
'databaseUser' => $databaseUser,
'--databasePassword' => $databasePassword,
'--hostingMode' => null,
'--forceInstall' => null
]
);
$commandTester = $this->executeCommandTest($inputData);
// the output of the command in the console
$output = $commandTester->getDisplay();
$this->assertStringContainsString('Installation finished', $output);
$configData = self::$dic->get(Config::class)->getConfigData();
$this->assertEquals($configData->getDbUser(), $databaseUser);
$this->assertEquals($configData->getDbPass(), $databasePassword);
// Cleanup database
DatabaseUtil::dropDatabase(self::$commandInputData['databaseName']);
}
/**
* @throws DependencyException
* @throws NotFoundException
*/
public function testInstallFromEnvironmentVarIsAbort(): void
{
$this->setEnvironmentVariables();
$commandTester = $this->executeCommandTest(null, false);
// the output of the command in the console
$output = $commandTester->getDisplay();
$this->assertStringContainsString('Installation aborted', $output);
}
private function setEnvironmentVariables(): void
{
putenv(sprintf('%s=%s',
InstallCommand::$envVarsMapping['databaseHost'],
getenv('DB_SERVER'))
);
putenv(sprintf('%s=%s',
InstallCommand::$envVarsMapping['databaseUser'],
getenv('DB_USER'))
);
putenv(sprintf('%s=%s',
InstallCommand::$envVarsMapping['databasePassword'],
getenv('DB_PASS'))
);
putenv(sprintf('%s=%s',
InstallCommand::$envVarsMapping['databaseName'],
self::$commandInputData['databaseName'])
);
putenv(sprintf('%s=%s',
InstallCommand::$envVarsMapping['adminLogin'],
self::$commandInputData['adminLogin'])
);
putenv(sprintf('%s=%s',
InstallCommand::$envVarsMapping['adminPassword'],
self::$commandInputData['--adminPassword'])
);
putenv(sprintf('%s=%s',
InstallCommand::$envVarsMapping['masterPassword'],
self::$commandInputData['--masterPassword'])
);
}
/**
* @throws DependencyException
* @throws NotFoundException
*/
public function testInstallFromEnvironmentVarIsAbortedWithForce(): void
{
putenv(sprintf('%s=true',
InstallCommand::$envVarsMapping['forceInstall'])
);
$this->setEnvironmentVariables();
$commandTester = $this->executeCommandTest(null, false);
// the output of the command in the console
$output = $commandTester->getDisplay();
$this->assertStringContainsString('Installation aborted', $output);
}
/**
* @throws DatabaseException
* @throws DependencyException
* @throws NotFoundException
*/
public function testInstallFromEnvironmentVarIsSuccessful(): void
{
putenv(sprintf('%s=true',
InstallCommand::$envVarsMapping['forceInstall'])
);
putenv(sprintf('%s=true',
InstallCommand::$envVarsMapping['install'])
);
$this->setEnvironmentVariables();
$commandTester = $this->executeCommandTest(null, false);
// the output of the command in the console
$output = $commandTester->getDisplay();
$this->assertStringContainsString('Installation finished', $output);
// Cleanup database
DatabaseUtil::dropDatabase(self::$commandInputData['databaseName']);
}
}

View File

@@ -74,7 +74,7 @@ class AccountFileServiceTest extends DatabaseTestCase
*/
public function testCreate()
{
$file = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'imgs' . DIRECTORY_SEPARATOR . 'add.png';
$file = RESOURCE_PATH . DIRECTORY_SEPARATOR . 'imgs' . DIRECTORY_SEPARATOR . 'add.png';
$image = file_get_contents($file);
$data = new FileData();

View File

@@ -67,7 +67,7 @@ class XmlVerifyServiceTest extends TestCase
*/
public function testVerifyEncrypted()
{
$file = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_syspass_encrypted.xml';
$file = RESOURCE_PATH . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_syspass_encrypted.xml';
$result = self::$xmlVerifyService->verifyEncrypted($file, 'test_encrypt');
@@ -90,7 +90,7 @@ class XmlVerifyServiceTest extends TestCase
*/
public function testVerify()
{
$file = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_syspass.xml';
$file = RESOURCE_PATH . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_syspass.xml';
$result = self::$xmlVerifyService->verify($file);
@@ -109,17 +109,17 @@ class XmlVerifyServiceTest extends TestCase
public function testCheckXmlHash()
{
$dom = new DOMDocument();
$dom->load(RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_syspass_encrypted.xml');
$dom->load(RESOURCE_PATH . 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');
$dom->load(RESOURCE_PATH . 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');
$dom->load(RESOURCE_PATH . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_syspass_valid_hash.xml');
$this->assertTrue(XmlVerifyService::checkXmlHash($dom, $key));
}

View File

@@ -78,7 +78,7 @@ class CsvImportTest extends DatabaseTestCase
*/
public function testDoImport()
{
$file = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data.csv';
$file = RESOURCE_PATH . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data.csv';
$params = new ImportParams();
$params->setDefaultUser(1);
@@ -170,7 +170,7 @@ class CsvImportTest extends DatabaseTestCase
*/
public function testDoImportInvalidData()
{
$file = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_invalid.csv';
$file = RESOURCE_PATH . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_invalid.csv';
$params = new ImportParams();
$params->setDefaultUser(1);

View File

@@ -83,7 +83,7 @@ class KeepassImportTest extends DatabaseTestCase
*/
public function testDoImport()
{
$file = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_keepass.xml';
$file = RESOURCE_PATH . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_keepass.xml';
$params = new ImportParams();
$params->setDefaultUser(1);

View File

@@ -79,7 +79,7 @@ class SyspassImportTest extends DatabaseTestCase
*/
public function testDoImport()
{
$file = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_syspass.xml';
$file = RESOURCE_PATH . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_syspass.xml';
$params = new ImportParams();
$params->setDefaultUser(1);

View File

@@ -44,13 +44,13 @@ class XmlFileImportTest extends TestCase
*/
public function testDetectXMLFormat()
{
$file = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_syspass.xml';
$file = RESOURCE_PATH . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_syspass.xml';
$import = new XmlFileImport(FileImport::fromFilesystem($file));
$this->assertEquals('syspass', $import->detectXMLFormat());
$file = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_keepass.xml';
$file = RESOURCE_PATH . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_keepass.xml';
$import = new XmlFileImport(FileImport::fromFilesystem($file));
@@ -63,7 +63,7 @@ class XmlFileImportTest extends TestCase
*/
public function testInvalidFile()
{
$file = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data.csv';
$file = RESOURCE_PATH . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data.csv';
$this->expectException(ImportException::class);
@@ -76,7 +76,7 @@ class XmlFileImportTest extends TestCase
*/
public function testEmptyFile()
{
$file = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_empty.xml';
$file = RESOURCE_PATH . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_empty.xml';
$import = new XmlFileImport(FileImport::fromFilesystem($file));

View File

@@ -69,13 +69,13 @@ class XmlImportTest extends DatabaseTestCase
$params->setDefaultUser(1);
$params->setDefaultGroup(1);
$file = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_syspass.xml';
$file = RESOURCE_PATH . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_syspass.xml';
$import = new XmlImport(self::$dic, new XmlFileImport(FileImport::fromFilesystem($file)), $params);
$this->assertEquals(5, $import->doImport()->getCounter());
$file = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_keepass.xml';
$file = RESOURCE_PATH . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . 'data_keepass.xml';
$import = new XmlImport(self::$dic, new XmlFileImport(FileImport::fromFilesystem($file)), $params);

View File

@@ -50,7 +50,7 @@ class ArchiveHandlerTest extends TestCase
$archive = TMP_PATH . DIRECTORY_SEPARATOR . 'test_archive_file';
$handler = new ArchiveHandler($archive, new PhpExtensionChecker());
$handler->compressFile(RESOURCE_DIR . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'config.xml');
$handler->compressFile(RESOURCE_PATH . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'config.xml');
$this->assertFileExists($archive . ArchiveHandler::COMPRESS_EXTENSION);
}
@@ -66,7 +66,7 @@ class ArchiveHandlerTest extends TestCase
$archive = TMP_PATH . DIRECTORY_SEPARATOR . 'test_archive_file';
$handler = new ArchiveHandler($archive, new PhpExtensionChecker());
$handler->compressFile(RESOURCE_DIR . DIRECTORY_SEPARATOR . 'non_existant_file');
$handler->compressFile(RESOURCE_PATH . DIRECTORY_SEPARATOR . 'non_existant_file');
}
/**
@@ -78,7 +78,7 @@ class ArchiveHandlerTest extends TestCase
$archive = TMP_PATH . DIRECTORY_SEPARATOR . 'test_archive_dir';
$handler = new ArchiveHandler($archive, new PhpExtensionChecker());
$handler->compressDirectory(RESOURCE_DIR);
$handler->compressDirectory(RESOURCE_PATH);
$this->assertFileExists($archive . ArchiveHandler::COMPRESS_EXTENSION);
}
@@ -94,7 +94,7 @@ class ArchiveHandlerTest extends TestCase
$archive = TMP_PATH . DIRECTORY_SEPARATOR . 'test_archive_dir';
$handler = new ArchiveHandler($archive, new PhpExtensionChecker());
$handler->compressDirectory(RESOURCE_DIR . DIRECTORY_SEPARATOR . 'non_existant_dir');
$handler->compressDirectory(RESOURCE_PATH . DIRECTORY_SEPARATOR . 'non_existant_dir');
}
/**

View File

@@ -40,15 +40,15 @@ class FileHandlerTest extends TestCase
/**
* @var string Archvivo de prueba válido
*/
protected static $validFile = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'valid_file.test';
protected static $validFile = RESOURCE_PATH . DIRECTORY_SEPARATOR . 'valid_file.test';
/**
* @var string Archvivo de prueba inmutable
*/
protected static $immutableFile = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'immutable_file.test';
protected static $immutableFile = RESOURCE_PATH . DIRECTORY_SEPARATOR . 'immutable_file.test';
/**
* @var string Archivo de prueba no existente
*/
protected static $missingFile = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'missing_file.test';
protected static $missingFile = RESOURCE_PATH . DIRECTORY_SEPARATOR . 'missing_file.test';
/**
* Comprobar la escritura de texto en un archivo

View File

@@ -55,7 +55,7 @@ class XmlHandlerTest extends TestCase
public static function setUpBeforeClass(): void
{
$file = RESOURCE_DIR . DIRECTORY_SEPARATOR . 'config.xml';
$file = RESOURCE_PATH . DIRECTORY_SEPARATOR . 'config.xml';
self::$xmlHandler = new XmlHandler(new FileHandler($file));
self::$itemsData = new stdClass();

View File

@@ -1,10 +1,10 @@
<?php
/**
/*
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -19,7 +19,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SP\Tests;

View File

@@ -1,10 +1,10 @@
<?php
/**
/*
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -19,7 +19,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SP\Tests;
@@ -41,21 +41,23 @@ define('APP_MODULE', 'tests');
define('APP_ROOT', dirname(__DIR__, 2));
define('TEST_ROOT', dirname(__DIR__));
define('RESOURCE_DIR', TEST_ROOT . DIRECTORY_SEPARATOR . 'res');
define('CONFIG_PATH', RESOURCE_DIR . DIRECTORY_SEPARATOR . 'config');
define('RESOURCE_PATH', TEST_ROOT . DIRECTORY_SEPARATOR . 'res');
define('CONFIG_PATH', RESOURCE_PATH . DIRECTORY_SEPARATOR . 'config');
define('CONFIG_FILE', CONFIG_PATH . DIRECTORY_SEPARATOR . 'config.xml');
define('ACTIONS_FILE', CONFIG_PATH . DIRECTORY_SEPARATOR . 'actions.xml');
define('MODULES_PATH', APP_ROOT. DIRECTORY_SEPARATOR. 'app' . DIRECTORY_SEPARATOR . 'modules');
define('SQL_PATH', APP_ROOT . DIRECTORY_SEPARATOR . 'schemas');
define('CACHE_PATH', RESOURCE_DIR . DIRECTORY_SEPARATOR . 'cache');
define('CACHE_PATH', RESOURCE_PATH . DIRECTORY_SEPARATOR . 'cache');
define('TMP_PATH', TEST_ROOT . DIRECTORY_SEPARATOR . 'tmp');
define('XML_SCHEMA', APP_ROOT . DIRECTORY_SEPARATOR . 'schemas' . DIRECTORY_SEPARATOR . 'syspass.xsd');
define('LOG_FILE', TMP_PATH . DIRECTORY_SEPARATOR . 'test.log');
define('FIXTURE_FILES', [
RESOURCE_DIR . DIRECTORY_SEPARATOR . 'datasets' . DIRECTORY_SEPARATOR . 'truncate.sql',
RESOURCE_DIR . DIRECTORY_SEPARATOR . 'datasets' . DIRECTORY_SEPARATOR . 'syspass.sql'
RESOURCE_PATH . DIRECTORY_SEPARATOR . 'datasets' . DIRECTORY_SEPARATOR . 'truncate.sql',
RESOURCE_PATH . DIRECTORY_SEPARATOR . 'datasets' . DIRECTORY_SEPARATOR . 'syspass.sql'
]);
define('SELF_IP_ADDRESS', getRealIpAddress());
define('SELF_HOSTNAME', gethostbyaddr(SELF_IP_ADDRESS));
@@ -170,7 +172,7 @@ function getDbHandler(DatabaseConnectionData $connectionData = null): MySQLHandl
*/
function getResource($dir, $file): string
{
return file_get_contents(RESOURCE_DIR . DIRECTORY_SEPARATOR . $dir . DIRECTORY_SEPARATOR . $file) ?: '';
return file_get_contents(RESOURCE_PATH . DIRECTORY_SEPARATOR . $dir . DIRECTORY_SEPARATOR . $file) ?: '';
}
/**
@@ -182,7 +184,7 @@ function getResource($dir, $file): string
*/
function saveResource($dir, $file, $data): string
{
return file_put_contents(RESOURCE_DIR . DIRECTORY_SEPARATOR . $dir . DIRECTORY_SEPARATOR . $file, $data);
return file_put_contents(RESOURCE_PATH . DIRECTORY_SEPARATOR . $dir . DIRECTORY_SEPARATOR . $file, $data);
}
/**
@@ -193,7 +195,9 @@ function recreateDir($dir)
if (!is_dir($dir)) {
print 'Creating ' . $dir . PHP_EOL;
mkdir($dir);
if (!mkdir($dir) && !is_dir($dir)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $dir));
}
} else {
print 'Deleting ' . $dir . PHP_EOL;

View File

@@ -16,6 +16,9 @@
<testsuite name="Modules">
<directory suffix=".php">./SP/Modules</directory>
</testsuite>
<testsuite name="cli">
<directory suffix=".php">./SP/Modules/Cli</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">