chore: Implement AccountAclService tests.

Use scoped namespace for simple functions.

Signed-off-by: Rubén D <nuxsmin@syspass.org>
This commit is contained in:
Rubén D
2022-11-25 23:40:27 +01:00
parent a4c654f44c
commit 796ecbc5fb
46 changed files with 1865 additions and 2533 deletions

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -27,6 +27,7 @@ namespace SP\Modules\Cli\Commands\Crypt;
use Exception;
use Psr\Log\LoggerInterface;
use RuntimeException;
use SP\Domain\Account\AccountServiceInterface;
use SP\Domain\Account\Services\AccountService;
use SP\Domain\Config\ConfigInterface;
use SP\Domain\Config\ConfigServiceInterface;
@@ -71,7 +72,7 @@ final class UpdateMasterPasswordCommand extends CommandBase
public function __construct(
MasterPassServiceInterface $masterPassService,
AccountService $accountService,
AccountServiceInterface $accountService,
ConfigServiceInterface $configService,
LoggerInterface $logger,
ConfigInterface $config
@@ -301,4 +302,4 @@ final class UpdateMasterPasswordCommand extends CommandBase
return true;
}
}
}

View File

@@ -26,7 +26,6 @@ namespace SP\Modules\Web\Controllers\Account;
use SP\Core\Application;
use SP\Core\Context\ContextBase;
use SP\Domain\Account\Services\AccountAclService;
use SP\Modules\Web\Controllers\ControllerBase;
use SP\Mvc\Controller\WebControllerHelper;
@@ -65,9 +64,6 @@ abstract class AccountControllerBase extends ControllerBase
if (DEBUG === true && $this->session->getAppStatus() === ContextBase::APP_STATUS_RELOADED) {
$this->session->resetAppStatus();
// Reset de los datos de ACL de cuentas
AccountAclService::clearAcl($this->session->getUserData()->getId());
}
}
}
}

View File

@@ -27,9 +27,11 @@ namespace SP\Modules\Web\Controllers\Account;
use Exception;
use SP\Core\Application;
use SP\Core\Context\ContextBase;
use SP\Core\Events\Event;
use SP\Modules\Web\Controllers\Helpers\Account\AccountSearchHelper;
use SP\Mvc\Controller\WebControllerHelper;
use SP\Providers\Acl\AclHandler;
use SP\Util\ErrorUtil;
/**
@@ -73,4 +75,4 @@ final class IndexController extends AccountControllerBase
ErrorUtil::showExceptionInView($this->view, $e);
}
}
}
}

View File

@@ -1,9 +1,4 @@
{
"name": "syspass/syspass",
"description": "PHP web based Password Manager for business and personal use.",
"homepage": "https://syspass.org",
"minimum-stability": "stable",
"license": "GPL-3.0",
"authors": [
{
"name": "Rubén Domínguez",
@@ -12,11 +7,29 @@
"homepage": "https://syspass.org/"
}
],
"support": {
"issues": "https://github.com/nuxsmin/sysPass/issues",
"source": "https://github.com/nuxsmin/sysPass",
"docs": "https://doc.syspass.org"
"autoload": {
"psr-4": {
"SP\\": "lib/SP/",
"SP\\Modules\\Web\\": "app/modules/web/",
"SP\\Modules\\Api\\": "app/modules/api/",
"SP\\Modules\\Cli\\": "app/modules/cli/",
"SP\\Tests\\": "tests/SP/"
}
},
"config": {
"classmap-authoritative": false,
"platform": {
"php": "8.0"
},
"allow-plugins": {
"ocramius/package-versions": true
}
},
"description": "PHP web based Password Manager for business and personal use.",
"homepage": "https://syspass.org",
"license": "GPL-3.0",
"minimum-stability": "stable",
"name": "syspass/syspass",
"require": {
"php": "~8.0 || ~8.1",
"defuse/php-encryption": "^2.1",
@@ -56,32 +69,19 @@
"squizlabs/php_codesniffer": "^3",
"phpstan/phpstan": "^1.9"
},
"scripts": {
"phpcs": "phpcs --standard=PSR2 lib",
"phpstan": "vendor/bin/phpstan analyse lib tests --xdebug"
},
"suggest": {
"syspass/plugin-authenticator": "^v2.2",
"ext-ldap": "*",
"ext-curl": "*",
"ext-xdebug": "*"
},
"autoload": {
"psr-4": {
"SP\\": "lib/SP/",
"SP\\Modules\\Web\\": "app/modules/web/",
"SP\\Modules\\Api\\": "app/modules/api/",
"SP\\Modules\\Cli\\": "app/modules/cli/",
"SP\\Tests\\": "tests/SP/"
}
},
"config": {
"classmap-authoritative": false,
"platform": {
"php": "8.0"
},
"allow-plugins": {
"ocramius/package-versions": true
}
},
"scripts": {
"phpcs": "phpcs --standard=PSR2 lib",
"phpstan": "vendor/bin/phpstan analyse lib tests --xdebug"
"support": {
"issues": "https://github.com/nuxsmin/sysPass/issues",
"source": "https://github.com/nuxsmin/sysPass",
"docs": "https://doc.syspass.org"
}
}

43
composer.lock generated
View File

@@ -1394,16 +1394,16 @@
},
{
"name": "laminas/laminas-code",
"version": "4.7.0",
"version": "4.7.1",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-code.git",
"reference": "0337d9265bc2e6376babad8c511500821620cb30"
"reference": "91aabc066d5620428120800c0eafc0411e441a62"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-code/zipball/0337d9265bc2e6376babad8c511500821620cb30",
"reference": "0337d9265bc2e6376babad8c511500821620cb30",
"url": "https://api.github.com/repos/laminas/laminas-code/zipball/91aabc066d5620428120800c0eafc0411e441a62",
"reference": "91aabc066d5620428120800c0eafc0411e441a62",
"shasum": ""
},
"require": {
@@ -1456,7 +1456,7 @@
"type": "community_bridge"
}
],
"time": "2022-09-13T10:33:30+00:00"
"time": "2022-11-21T01:32:31+00:00"
},
{
"name": "laravel/serializable-closure",
@@ -4687,12 +4687,12 @@
"source": {
"type": "git",
"url": "https://github.com/Roave/SecurityAdvisories.git",
"reference": "ed33734832e5a87eaa4341be7ce580de54157460"
"reference": "0399700d159e09b16645945758b65b921d3491fe"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/ed33734832e5a87eaa4341be7ce580de54157460",
"reference": "ed33734832e5a87eaa4341be7ce580de54157460",
"url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/0399700d159e09b16645945758b65b921d3491fe",
"reference": "0399700d159e09b16645945758b65b921d3491fe",
"shasum": ""
},
"conflict": {
@@ -4716,6 +4716,7 @@
"asymmetricrypt/asymmetricrypt": ">=0,<9.9.99",
"awesome-support/awesome-support": "<=6.0.7",
"aws/aws-sdk-php": ">=3,<3.2.1",
"backdrop/backdrop": "<=1.23",
"badaso/core": "<2.6.1",
"bagisto/bagisto": "<0.1.5",
"barrelstrength/sprout-base-email": "<1.2.7",
@@ -4749,7 +4750,7 @@
"codeigniter4/shield": "= 1.0.0-beta",
"codiad/codiad": "<=2.8.4",
"composer/composer": "<1.10.26|>=2-alpha.1,<2.2.12|>=2.3,<2.3.5",
"concrete5/concrete5": ">= 9.0.0RC1, < 9.1.3|<9",
"concrete5/concrete5": "<9.1.3|>= 9.0.0RC1, < 9.1.3",
"concrete5/core": "<8.5.8|>=9,<9.1",
"contao-components/mediaelement": ">=2.14.2,<2.21.1",
"contao/contao": ">=4,<4.4.56|>=4.5,<4.9.18|>=4.10,<4.11.7|>=4.13,<4.13.3",
@@ -4775,7 +4776,7 @@
"doctrine/mongodb-odm": ">=1,<1.0.2",
"doctrine/mongodb-odm-bundle": ">=2,<3.0.1",
"doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4",
"dolibarr/dolibarr": "<16|= 12.0.5|>= 3.3.beta1, < 13.0.2",
"dolibarr/dolibarr": "<16|>=16.0.1,<16.0.3|= 12.0.5|>= 3.3.beta1, < 13.0.2",
"dompdf/dompdf": "<2.0.1",
"drupal/core": ">=7,<7.91|>=8,<9.3.19|>=9.4,<9.4.3",
"drupal/drupal": ">=7,<7.80|>=8,<8.9.16|>=9,<9.1.12|>=9.2,<9.2.4",
@@ -4814,7 +4815,7 @@
"fenom/fenom": "<=2.12.1",
"filegator/filegator": "<7.8",
"firebase/php-jwt": "<2",
"flarum/core": ">=1,<=1.0.1",
"flarum/core": ">=1,<=1.0.1|>=1.5,<1.6.2",
"flarum/sticky": ">=0.1-beta.14,<=0.1-beta.15",
"flarum/tags": "<=0.1-beta.13",
"fluidtypo3/vhs": "<5.1.1",
@@ -4870,6 +4871,7 @@
"ivankristianto/phpwhois": "<=4.3",
"jackalope/jackalope-doctrine-dbal": "<1.7.4",
"james-heinrich/getid3": "<1.9.21",
"jasig/phpcas": "<1.3.3",
"joomla/archive": "<1.1.12|>=2,<2.0.1",
"joomla/filesystem": "<1.6.2|>=2,<2.0.1",
"joomla/filter": "<1.4.4|>=2,<2.0.1",
@@ -4897,7 +4899,7 @@
"league/commonmark": "<0.18.3",
"league/flysystem": "<1.1.4|>=2,<2.1.1",
"lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3",
"librenms/librenms": "<=22.8",
"librenms/librenms": "<22.10",
"limesurvey/limesurvey": "<3.27.19",
"livehelperchat/livehelperchat": "<=3.91",
"livewire/livewire": ">2.2.4,<2.2.6",
@@ -4922,7 +4924,7 @@
"modx/revolution": "<= 2.8.3-pl|<2.8",
"mojo42/jirafeau": "<4.4",
"monolog/monolog": ">=1.8,<1.12",
"moodle/moodle": "<4.0.1",
"moodle/moodle": "<4.0.5",
"mustache/mustache": ">=2,<2.14.1",
"namshi/jose": "<2.2",
"neoan3-apps/template": "<1.1.1",
@@ -5022,12 +5024,12 @@
"shopware/storefront": "<=6.4.8.1",
"shopxo/shopxo": "<2.2.6",
"showdoc/showdoc": "<2.10.4",
"silverstripe/admin": ">=1,<1.8.1",
"silverstripe/assets": ">=1,<1.10.1",
"silverstripe/cms": "<4.3.6|>=4.4,<4.4.4",
"silverstripe/admin": ">=1,<1.11.3",
"silverstripe/assets": ">=1,<1.11.1",
"silverstripe/cms": "<4.11.3",
"silverstripe/comments": ">=1.3,<1.9.99|>=2,<2.9.99|>=3,<3.1.1",
"silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3",
"silverstripe/framework": "<4.10.9",
"silverstripe/framework": "<4.11.14",
"silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2|= 4.0.0-alpha1",
"silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1",
"silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1",
@@ -5036,6 +5038,7 @@
"silverstripe/subsites": ">=2,<2.1.1",
"silverstripe/taxonomy": ">=1.3,<1.3.1|>=2,<2.0.1",
"silverstripe/userforms": "<3",
"silverstripe/versioned-admin": ">=1,<1.11.1",
"simple-updates/phpwhois": "<=1",
"simplesamlphp/saml2": "<1.10.6|>=2,<2.3.8|>=3,<3.1.4",
"simplesamlphp/simplesamlphp": "<1.18.6",
@@ -5110,7 +5113,7 @@
"topthink/framework": "<=6.0.13",
"topthink/think": "<=6.0.9",
"topthink/thinkphp": "<=3.2.3",
"tribalsystems/zenario": "<9.2.55826",
"tribalsystems/zenario": "<=9.3.57186",
"truckersmp/phpwhois": "<=4.3.1",
"twig/twig": "<1.44.7|>=2,<2.15.3|>=3,<3.4.3",
"typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.29|>=10,<10.4.32|>=11,<11.5.16",
@@ -5146,7 +5149,7 @@
"yetiforce/yetiforce-crm": "<=6.4",
"yidashi/yii2cmf": "<=2",
"yii2mod/yii2-cms": "<1.9.2",
"yiisoft/yii": ">=1.1.14,<1.1.15",
"yiisoft/yii": "<1.1.27",
"yiisoft/yii2": "<2.0.38",
"yiisoft/yii2-bootstrap": "<2.0.4",
"yiisoft/yii2-dev": "<2.0.43",
@@ -5217,7 +5220,7 @@
"type": "tidelift"
}
],
"time": "2022-11-16T22:04:17+00:00"
"time": "2022-11-23T23:04:03+00:00"
},
{
"name": "sebastian/cli-parser",

View File

@@ -65,6 +65,7 @@ function logger(mixed $data, string $type = 'DEBUG'): void
$caller
);
/** @noinspection ForgottenDebugOutputInspection */
$useOwn = (!defined('LOG_FILE')
|| !@error_log($line, 3, LOG_FILE)
);
@@ -77,6 +78,7 @@ function logger(mixed $data, string $type = 'DEBUG'): void
$caller
);
/** @noinspection ForgottenDebugOutputInspection */
@error_log($line);
}
}

View File

@@ -5,7 +5,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -29,6 +29,8 @@ use SP\Core\Context\ContextInterface;
use SP\Core\Events\Event;
use SP\Core\Events\EventDispatcher;
use SP\Core\Events\EventMessage;
use function SP\__u;
use function SP\processException;
defined('APP_ROOT') || die();
@@ -50,10 +52,9 @@ class Acl implements ActionsInterface
*/
public function __construct(
ContextInterface $context,
EventDispatcher $eventDispatcher,
EventDispatcher $eventDispatcher,
Actions $actions = null
)
{
) {
$this->context = $context;
$this->eventDispatcher = $eventDispatcher;
@@ -77,8 +78,8 @@ class Acl implements ActionsInterface
/**
* Obtener el nombre de la acción indicada
*
* @param int $actionId El id de la acción
* @param bool $translate
* @param int $actionId El id de la acción
* @param bool $translate
*
* @return string
* @internal param bool $shortName Si se devuelve el nombre corto de la acción
@@ -132,18 +133,18 @@ class Acl implements ActionsInterface
return ($userData->getIsAdminAcc() || $userProfile->isAccFiles());
case self::ITEMS_MANAGE:
return ($userData->getIsAdminAcc()
|| $userProfile->isMgmCategories()
|| $userProfile->isMgmCustomers()
|| $userProfile->isMgmAccounts()
|| $userProfile->isMgmFiles()
|| $userProfile->isMgmTags()
|| $userProfile->isMgmCustomFields()
|| $userProfile->isMgmPublicLinks());
|| $userProfile->isMgmCategories()
|| $userProfile->isMgmCustomers()
|| $userProfile->isMgmAccounts()
|| $userProfile->isMgmFiles()
|| $userProfile->isMgmTags()
|| $userProfile->isMgmCustomFields()
|| $userProfile->isMgmPublicLinks());
case self::CONFIG:
return ($userProfile->isConfigGeneral()
|| $userProfile->isConfigEncryption()
|| $userProfile->isConfigBackup()
|| $userProfile->isConfigImport());
|| $userProfile->isConfigEncryption()
|| $userProfile->isConfigBackup()
|| $userProfile->isConfigImport());
case self::CONFIG_GENERAL:
case self::CONFIG_ACCOUNT:
case self::CONFIG_WIKI:
@@ -212,12 +213,12 @@ class Acl implements ActionsInterface
return $userProfile->isConfigBackup();
case self::ACCESS_MANAGE:
return ($userProfile->isMgmUsers()
|| $userProfile->isMgmGroups()
|| $userProfile->isMgmProfiles()
|| $userProfile->isMgmApiTokens());
|| $userProfile->isMgmGroups()
|| $userProfile->isMgmProfiles()
|| $userProfile->isMgmApiTokens());
case self::SECURITY_MANAGE:
return $userProfile->isEvl()
|| $userProfile->isMgmUsers();
|| $userProfile->isMgmUsers();
case self::USER:
case self::USER_SEARCH:
case self::USER_VIEW:
@@ -280,13 +281,17 @@ class Acl implements ActionsInterface
$actionName = __u('N/A');
}
$this->eventDispatcher->notifyEvent('acl.deny',
new Event($this, EventMessage::factory()
->addDescription(__u('Access denied'))
->addDetail(__u('Action'), $actionName)
->addDetail(__u('User'), $userData->getLogin()))
$this->eventDispatcher->notifyEvent(
'acl.deny',
new Event(
$this,
EventMessage::factory()
->addDescription(__u('Access denied'))
->addDetail(__u('Action'), $actionName)
->addDetail(__u('User'), $userData->getLogin())
)
);
return false;
}
}
}

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -24,6 +24,8 @@
namespace SP\Core\Context;
use function SP\__u;
/**
* Class ContextBase
*
@@ -31,13 +33,11 @@ namespace SP\Core\Context;
*/
abstract class ContextBase implements ContextInterface
{
public const APP_STATUS_UPDATED = 'updated';
public const APP_STATUS_RELOADED = 'reloaded';
public const APP_STATUS_INSTALLED = 'installed';
public const APP_STATUS_RELOADED = 'reloaded';
public const APP_STATUS_LOGGEDOUT = 'loggedout';
private ?ContextCollection $context = null;
private ContextCollection $trasient;
private ContextCollection $trasient;
/**
* ContextBase constructor.
@@ -56,7 +56,7 @@ abstract class ContextBase implements ContextInterface
public function setTrasientKey(string $key, $value)
{
// If the key starts with "_" it's a protected key, thus cannot be overwritten
if (strpos($key, '_') === 0
if (str_starts_with($key, '_')
&& $this->trasient->exists($key)
&& $this->trasient->get($key) !== $value
) {
@@ -101,6 +101,7 @@ abstract class ContextBase implements ContextInterface
if (!isset($context['context'])) {
$context['context'] = $this->context = new ContextCollection();
return;
}
@@ -128,6 +129,7 @@ abstract class ContextBase implements ContextInterface
{
$this->checkContext();
return is_numeric($default)
? (int)$this->context->get($key, $default)
: $this->context->get($key, $default);
@@ -146,12 +148,12 @@ abstract class ContextBase implements ContextInterface
/**
* Establecer una variable de contexto
*
* @param string $key El nombre de la variable
* @param mixed $value El valor de la variable
* @param string $key El nombre de la variable
* @param mixed $value El valor de la variable
*
* @throws ContextException
*/
protected function setContextKey(string $key, $value)
protected function setContextKey(string $key, mixed $value): mixed
{
$this->checkContext();
@@ -159,4 +161,4 @@ abstract class ContextBase implements ContextInterface
return $value;
}
}
}

View File

@@ -29,6 +29,8 @@ use SP\DataModel\Dto\AccountCache;
use SP\DataModel\ProfileData;
use SP\Domain\Account\Search\AccountSearchFilter;
use SP\Domain\User\Services\UserLoginResponse;
use function SP\logger;
use function SP\processException;
/**
* Class Session
@@ -39,7 +41,7 @@ class SessionContext extends ContextBase
{
public const MAX_SID_TIME = 120;
private static bool $isReset = false;
private static bool $isReset = false;
private static bool $isLocked = false;
/**
@@ -79,8 +81,8 @@ class SessionContext extends ContextBase
/**
* Devolver una variable de sesión
*
* @param string $key
* @param mixed $default
* @param string $key
* @param mixed $default
*
* @return mixed
*/
@@ -108,16 +110,16 @@ class SessionContext extends ContextBase
/**
* Establecer una variable de sesión
*
* @param string $key El nombre de la variable
* @param mixed $value El valor de la variable
* @param string $key El nombre de la variable
* @param mixed $value El valor de la variable
*
* @return mixed
*/
protected function setContextKey(string $key, $value)
protected function setContextKey(string $key, mixed $value): mixed
{
try {
if (self::$isLocked) {
logger('Session locked; key=' . $key);
logger('Session locked; key='.$key);
} else {
parent::setContextKey($key, $value);
}
@@ -133,7 +135,7 @@ class SessionContext extends ContextBase
/**
* Establecer la hora de carga de la configuración
*
* @param int $time
* @param int $time
*/
public function setConfigTime(int $time): void
{
@@ -153,7 +155,7 @@ class SessionContext extends ContextBase
/**
* Establece los datos del usuario en la sesión.
*
* @param UserLoginResponse|null $userLoginResponse
* @param UserLoginResponse|null $userLoginResponse
*/
public function setUserData(UserLoginResponse $userLoginResponse = null): void
{
@@ -173,7 +175,7 @@ class SessionContext extends ContextBase
/**
* Establece el objeto de perfil de usuario en la sesión.
*
* @param ProfileData $ProfileData
* @param ProfileData $ProfileData
*/
public function setUserProfile(ProfileData $ProfileData): void
{
@@ -189,7 +191,7 @@ class SessionContext extends ContextBase
}
/**
* @param \SP\Domain\Account\Search\AccountSearchFilter $searchFilters
* @param \SP\Domain\Account\Search\AccountSearchFilter $searchFilters
*/
public function setSearchFilters(AccountSearchFilter $searchFilters): void
{
@@ -209,7 +211,7 @@ class SessionContext extends ContextBase
public function isLoggedIn(): bool
{
return self::$isReset === false && $this->getUserData()->getLogin()
&& is_object($this->getUserData()->getPreferences());
&& is_object($this->getUserData()->getPreferences());
}
/**
@@ -253,7 +255,7 @@ class SessionContext extends ContextBase
/**
* Sets a temporary master password
*
* @param string $password
* @param string $password
*/
public function setTemporaryMasterPass(string $password): void
{
@@ -293,7 +295,7 @@ class SessionContext extends ContextBase
/**
* Establecer el timeout de la sesión
*
* @param int $timeout El valor en segundos
* @param int $timeout El valor en segundos
*
* @return int
*/
@@ -365,7 +367,7 @@ class SessionContext extends ContextBase
/**
* Establece el color asociado a una cuenta
*
* @param array $color
* @param array $color
*/
public function setAccountColor(array $color): void
{
@@ -385,7 +387,7 @@ class SessionContext extends ContextBase
/**
* Establecer el estado de la aplicación
*
* @param string $status
* @param string $status
*/
public function setAppStatus(string $status): void
{
@@ -405,7 +407,7 @@ class SessionContext extends ContextBase
/**
* Set the CSRF key
*
* @param string $csrf
* @param string $csrf
*/
public function setCSRF(string $csrf): void
{
@@ -435,7 +437,7 @@ class SessionContext extends ContextBase
/**
* Establecer la clave maestra encriptada
*
* @param Vault $vault
* @param Vault $vault
*/
public function setVault(Vault $vault): void
{
@@ -445,7 +447,7 @@ class SessionContext extends ContextBase
/**
* Establece la cache de cuentas
*
* @param array $accountsCache
* @param array $accountsCache
*/
public function setAccountsCache(array $accountsCache): void
{
@@ -523,9 +525,9 @@ class SessionContext extends ContextBase
}
/**
* @param string $pluginName
* @param string $key
* @param mixed $value
* @param string $pluginName
* @param string $key
* @param mixed $value
*
* @return mixed
*/
@@ -540,8 +542,8 @@ class SessionContext extends ContextBase
}
/**
* @param string $pluginName
* @param string $key
* @param string $pluginName
* @param string $key
*
* @return mixed
*/

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -26,6 +26,7 @@ namespace SP\Core\Context;
use SP\DataModel\ProfileData;
use SP\Domain\User\Services\UserLoginResponse;
use function SP\processException;
/**
* Class ApiContext
@@ -37,7 +38,7 @@ class StatelessContext extends ContextBase
/**
* Establece los datos del usuario en la sesión.
*
* @param UserLoginResponse|null $userLoginResponse
* @param UserLoginResponse|null $userLoginResponse
*/
public function setUserData(UserLoginResponse $userLoginResponse = null): void
{
@@ -47,17 +48,15 @@ class StatelessContext extends ContextBase
/**
* Establecer una variable de sesión
*
* @param string $key El nombre de la variable
* @param mixed $value El valor de la variable
* @param string $key El nombre de la variable
* @param mixed $value El valor de la variable
*
* @return mixed
*/
protected function setContextKey(string $key, $value)
protected function setContextKey(string $key, mixed $value): mixed
{
try {
parent::setContextKey($key, $value);
return $value;
return parent::setContextKey($key, $value);
} catch (ContextException $e) {
processException($e);
}
@@ -68,7 +67,7 @@ class StatelessContext extends ContextBase
/**
* Obtiene el objeto de perfil de usuario de la sesión.
*
* @return ProfileData
* @return \SP\DataModel\ProfileData|null
*/
public function getUserProfile(): ?ProfileData
{
@@ -78,12 +77,12 @@ class StatelessContext extends ContextBase
/**
* Devolver una variable de sesión
*
* @param string $key
* @param mixed $default
* @param string $key
* @param mixed $default
*
* @return mixed
*/
protected function getContextKey(string $key, $default = null)
protected function getContextKey(string $key, $default = null): mixed
{
try {
return parent::getContextKey($key, $default);
@@ -97,7 +96,7 @@ class StatelessContext extends ContextBase
/**
* Establece el objeto de perfil de usuario en la sesión.
*
* @param ProfileData $profileData
* @param ProfileData $profileData
*/
public function setUserProfile(ProfileData $profileData): void
{
@@ -155,7 +154,7 @@ class StatelessContext extends ContextBase
/**
* Establecer el estado de la aplicación
*
* @param string $status
* @param string $status
*/
public function setAppStatus(string $status): void
{
@@ -184,7 +183,7 @@ class StatelessContext extends ContextBase
/**
* Establecer la hora de carga de la configuración
*
* @param int $time
* @param int $time
*/
public function setConfigTime(int $time): void
{
@@ -212,7 +211,7 @@ class StatelessContext extends ContextBase
/**
* Sets a temporary master password
*
* @param string $password
* @param string $password
*
* @throws ContextException
*/
@@ -222,9 +221,9 @@ class StatelessContext extends ContextBase
}
/**
* @param string $pluginName
* @param string $key
* @param mixed $value
* @param string $pluginName
* @param string $key
* @param mixed $value
*
* @return mixed
*/
@@ -238,8 +237,8 @@ class StatelessContext extends ContextBase
}
/**
* @param string $pluginName
* @param string $key
* @param string $pluginName
* @param string $key
*
* @return mixed
*/
@@ -249,4 +248,4 @@ class StatelessContext extends ContextBase
return $ctxKey[$pluginName][$key] ?? null;
}
}
}

View File

@@ -24,280 +24,32 @@
namespace SP\Core;
use ArrayAccess;
use ArrayIterator;
use Countable;
use IteratorAggregate;
use Traversable;
use ArrayObject;
/**
* Class DataCollection
*
* @package SP\Core\Context
*/
abstract class DataCollection implements IteratorAggregate, ArrayAccess, Countable
abstract class DataCollection extends ArrayObject
{
/**
* Collection of data attributes
*/
protected array $attributes = [];
/**
* Retrieve an external iterator
*
* @link http://php.net/manual/en/iteratoraggregate.getiterator.php
* @return Traversable An instance of an object implementing <b>Iterator</b> or
* <b>Traversable</b>
* @since 5.0.0
*/
public function getIterator(): Traversable
public function get(string $key, mixed $default = null): mixed
{
return new ArrayIterator($this->attributes);
if (!property_exists($this, $key)) {
return $default;
}
return $this->{$key};
}
/**
* Whether a offset exists
*
* @link http://php.net/manual/en/arrayaccess.offsetexists.php
*
* @param mixed $offset <p>
* An offset to check for.
* </p>
*
* @return boolean true on success or false on failure.
* </p>
* <p>
* The return value will be casted to boolean if non-boolean was returned.
* @since 5.0.0
*/
public function offsetExists($offset): bool
public function set(string $key, mixed $value): void
{
return $this->exists($offset);
$this->{$key} = $value;
}
/**
* See if an attribute exists in the collection
*
* @param string $key The name of the parameter
*
* @return boolean
*/
public function exists(string $key): bool
{
// Don't use "isset", since it returns false for null values
return array_key_exists($key, $this->attributes);
return property_exists($this, $key);
}
/**
* Offset to retrieve
*
* @link http://php.net/manual/en/arrayaccess.offsetget.php
*
* @param mixed $offset <p>
* The offset to retrieve.
* </p>
*
* @return mixed Can return all value types.
* @since 5.0.0
*/
public function offsetGet($offset): mixed
{
return $this->get($offset);
}
/**
* Return an attribute of the collection
*
* Return a default value if the key doesn't exist
*
* @param string $key The name of the parameter to return
* @param mixed $default_val The default value of the parameter if it contains no value
*
* @return mixed
*/
public function get(string $key, $default_val = null)
{
return $this->attributes[$key] ?? $default_val;
}
/**
* Offset to set
*
* @link http://php.net/manual/en/arrayaccess.offsetset.php
*
* @param mixed $offset <p>
* The offset to assign the value to.
* </p>
* @param mixed $value <p>
* The value to set.
* </p>
*
* @return void
* @since 5.0.0
*/
public function offsetSet($offset, $value): void
{
$this->set($offset, $value);
}
/**
* Set an attribute of the collection
*
* @param string $key The name of the parameter to set
* @param mixed $value The value of the parameter to set
*
* @return DataCollection
*/
public function set(string $key, $value): DataCollection
{
$this->attributes[$key] = $value;
return $this;
}
/**
* Offset to unset
*
* @link http://php.net/manual/en/arrayaccess.offsetunset.php
*
* @param mixed $offset <p>
* The offset to unset.
* </p>
*
* @return void
* @since 5.0.0
*/
public function offsetUnset($offset): void
{
$this->remove($offset);
}
/**
* Remove an attribute from the collection
*
* @param string $key The name of the parameter
*
* @return void
*/
public function remove(string $key): void
{
unset($this->attributes[$key]);
}
/**
* Count elements of an object
*
* @link http://php.net/manual/en/countable.count.php
* @return int The custom count as an integer.
* </p>
* <p>
* The return value is cast to an integer.
* @since 5.1.0
*/
public function count(): int
{
return count($this->attributes);
}
/**
* Clear the collection's contents
*
* Semantic alias of a no-argument `$this->replace` call
*
* @return DataCollection
*/
public function clear(): DataCollection
{
return $this->replace();
}
/**
* Replace the collection's attributes
*
* @param array $attributes The attributes to replace the collection's with
*
* @return DataCollection
*/
public function replace(array $attributes = array()): DataCollection
{
$this->attributes = $attributes;
return $this;
}
/**
* Check if the collection is empty
*
* @return boolean
*/
public function isEmpty(): bool
{
return count($this->attributes) === 0;
}
/**
* Magic "__get" method
*
* Allows the ability to arbitrarily request an attribute from
* this instance while treating it as an instance property
*
* @param string $key The name of the parameter to return
*
* @return mixed
* @see get()
*/
public function __get(string $key)
{
return $this->get($key);
}
/**
* Magic "__set" method
*
* Allows the ability to arbitrarily set an attribute from
* this instance while treating it as an instance property
*
* @param string $key The name of the parameter to set
* @param mixed $value The value of the parameter to set
*
* @return void
* @see set()
*/
public function __set(string $key, $value)
{
$this->set($key, $value);
}
/**
* Magic "__isset" method
*
* Allows the ability to arbitrarily check the existence of an attribute
* from this instance while treating it as an instance property
*
* @param string $key The name of the parameter
*
* @return boolean
* @see exists()
*/
public function __isset(string $key)
{
return $this->exists($key);
}
/**
* Magic "__unset" method
*
* Allows the ability to arbitrarily remove an attribute from
* this instance while treating it as an instance property
*
* @param string $key The name of the parameter
*
* @return void
* @see remove()
*
*/
public function __unset(string $key)
{
$this->remove($key);
}
}
}

View File

@@ -24,7 +24,6 @@
namespace SP\DataModel;
use SP\Domain\Common\Out\DataModelBase;
/**
@@ -34,570 +33,190 @@ use SP\Domain\Common\Out\DataModelBase;
*/
class AccountVData extends DataModelBase
{
/**
* @var int Id de la cuenta.
*/
public $id = 0;
/**
* @var int Id del usuario principal de la cuenta.
*/
public $userId = 0;
/**
* @var int Id del grupo principal de la cuenta.
*/
public $userGroupId = 0;
/**
* @var int Id del usuario que editó la cuenta.
*/
public $userEditId = 0;
/**
* @var string El nombre de la cuenta.
*/
public $name = '';
/**
* @var int Id del cliente de la cuenta.
*/
public $clientId = 0;
/**
* @var int Id de la categoría de la cuenta.
*/
public $categoryId = 0;
/**
* @var string El nombre de usuario de la cuenta.
*/
public $login = '';
/**
* @var string La URL de la cuenta.
*/
public $url = '';
/**
* @var string La clave de la cuenta.
*/
public $pass = '';
/**
* @var string La clave de encriptación de la cuenta
*/
public $key = '';
/**
* @var string Las nosta de la cuenta.
*/
public $notes = '';
/**
* @var int
*/
public $otherUserEdit = 0;
/**
* @var int
*/
public $otherUserGroupEdit = 0;
/**
* @var int
*/
public $dateAdd = 0;
/**
* @var int
*/
public $dateEdit = 0;
/**
* @var int
*/
public $countView = 0;
/**
* @var int
*/
public $countDecrypt = 0;
/**
* @var int
*/
public $isPrivate = 0;
/**
* @var int
*/
public $isPrivateGroup = 0;
/**
* @var int
*/
public $passDate = 0;
/**
* @var int
*/
public $passDateChange = 0;
/**
* @var int
*/
public $parentId = 0;
/**
* @var string
*/
public $categoryName = '';
/**
* @var string
*/
public $clientName = '';
/**
* @var string
*/
public $userGroupName = '';
/**
* @var string
*/
public $userName = '';
/**
* @var string
*/
public $userLogin = '';
/**
* @var string
*/
public $userEditName = '';
/**
* @var string
*/
public $userEditLogin = '';
/**
* @var string
*/
public $publicLinkHash = '';
protected ?int $id = null;
protected ?int $userId = null;
protected ?int $userGroupId = null;
protected ?int $userEditId = null;
protected ?string $name = null;
protected ?int $clientId = null;
protected ?int $categoryId = null;
protected ?string $login = null;
protected ?string $url = null;
protected ?string $pass = null;
protected ?string $key = null;
protected ?string $notes = null;
protected ?int $otherUserEdit = null;
protected ?int $otherUserGroupEdit = null;
protected ?int $dateAdd = null;
protected ?int $dateEdit = null;
protected ?int $countView = null;
protected ?int $countDecrypt = null;
protected ?int $isPrivate = null;
protected ?int $isPrivateGroup = null;
protected ?int $passDate = null;
protected ?int $passDateChange = null;
protected ?int $parentId = null;
protected ?string $categoryName = null;
protected ?string $clientName = null;
protected ?string $userGroupName = null;
protected ?string $userName = null;
protected ?string $userLogin = null;
protected ?string $userEditName = null;
protected ?string $userEditLogin = null;
protected ?string $publicLinkHash = null;
/**
* AccountData constructor.
*
* @param int $accountId
*/
public function __construct($accountId = 0)
public function getId(): ?int
{
$this->id = (int)$accountId;
return $this->id;
}
/**
* @return int
*/
public function getDateAdd()
public function getUserId(): ?int
{
return (int)$this->dateAdd;
return $this->userId;
}
/**
* @param int $dateAdd
*/
public function setDateAdd($dateAdd)
public function getUserGroupId(): ?int
{
$this->dateAdd = $dateAdd;
return $this->userGroupId;
}
/**
* @return int
*/
public function getDateEdit()
public function getUserEditId(): ?int
{
return (int)$this->dateEdit;
return $this->userEditId;
}
/**
* @param int $dateEdit
*/
public function setDateEdit($dateEdit)
{
$this->dateEdit = $dateEdit;
}
/**
* @return int
*/
public function getUserEditId()
{
return (int)$this->userEditId;
}
/**
* @param int $userEditId
*/
public function setUserEditId($userEditId)
{
$this->userEditId = (int)$userEditId;
}
/**
* @return string
*/
public function getPass()
{
return $this->pass;
}
/**
* @param string $pass
*/
public function setPass($pass)
{
$this->pass = $pass;
}
/**
* @return string
*/
public function getKey()
{
return $this->key;
}
/**
* @param string $key
*/
public function setKey($key)
{
$this->key = $key;
}
/**
* @return int|null
*/
public function getId()
{
return (int)$this->id;
}
/**
* @param int $id
*/
public function setId($id)
{
$this->id = (int)$id;
}
/**
* @return int
*/
public function getUserId()
{
return (int)$this->userId;
}
/**
* @param int $userId
*/
public function setUserId($userId)
{
$this->userId = (int)$userId;
}
/**
* @return int
*/
public function getUserGroupId()
{
return (int)$this->userGroupId;
}
/**
* @param int $userGroupId
*/
public function setUserGroupId($userGroupId)
{
$this->userGroupId = (int)$userGroupId;
}
/**
* @return int
*/
public function getOtherUserEdit()
{
return (int)$this->otherUserEdit;
}
/**
* @param bool $otherUserEdit
*/
public function setOtherUserEdit($otherUserEdit)
{
$this->otherUserEdit = (int)$otherUserEdit;
}
/**
* @return int
*/
public function getOtherUserGroupEdit()
{
return (int)$this->otherUserGroupEdit;
}
/**
* @param bool $otherUserGroupEdit
*/
public function setOtherUserGroupEdit($otherUserGroupEdit)
{
$this->otherUserGroupEdit = (int)$otherUserGroupEdit;
}
/**
* @return string
*/
public function getName()
public function getName(): ?string
{
return $this->name;
}
/**
* @param string $name
*/
public function setName($name)
public function getClientId(): ?int
{
$this->name = $name;
return $this->clientId;
}
/**
* @return int
*/
public function getCategoryId()
public function getCategoryId(): ?int
{
return (int)$this->categoryId;
return $this->categoryId;
}
/**
* @param int $categoryId
*/
public function setCategoryId($categoryId)
{
$this->categoryId = (int)$categoryId;
}
/**
* @return int
*/
public function getClientId()
{
return (int)$this->clientId;
}
/**
* @param int $clientId
*/
public function setClientId($clientId)
{
$this->clientId = (int)$clientId;
}
/**
* @return string
*/
public function getLogin()
public function getLogin(): ?string
{
return $this->login;
}
/**
* @param string $login
*/
public function setLogin($login)
{
$this->login = $login;
}
/**
* @return string
*/
public function getUrl()
public function getUrl(): ?string
{
return $this->url;
}
/**
* @param string $url
*/
public function setUrl($url)
public function getPass(): ?string
{
$this->url = $url;
return $this->pass;
}
/**
* @return string
*/
public function getNotes()
public function getKey(): ?string
{
return $this->key;
}
public function getNotes(): ?string
{
return $this->notes;
}
/**
* @param string $notes
*/
public function setNotes($notes)
public function getOtherUserEdit(): ?int
{
$this->notes = $notes;
return $this->otherUserEdit;
}
/**
* @return int
*/
public function getCountView()
public function getOtherUserGroupEdit(): ?int
{
return (int)$this->countView;
return $this->otherUserGroupEdit;
}
/**
* @param int $countView
*/
public function setCountView($countView)
public function getDateAdd(): ?int
{
$this->countView = (int)$countView;
return $this->dateAdd;
}
/**
* @return int
*/
public function getCountDecrypt()
public function getDateEdit(): ?int
{
return (int)$this->countDecrypt;
return $this->dateEdit;
}
/**
* @param int $countDecrypt
*/
public function setCountDecrypt($countDecrypt)
public function getCountView(): ?int
{
$this->countDecrypt = (int)$countDecrypt;
return $this->countView;
}
/**
* @return int
*/
public function getIsPrivate()
public function getCountDecrypt(): ?int
{
return (int)$this->isPrivate;
return $this->countDecrypt;
}
/**
* @param int $isPrivate
*/
public function setIsPrivate($isPrivate)
public function getIsPrivate(): ?int
{
$this->isPrivate = (int)$isPrivate;
return $this->isPrivate;
}
/**
* @return int
*/
public function getPassDate()
public function getIsPrivateGroup(): ?int
{
return (int)$this->passDate;
return $this->isPrivateGroup;
}
/**
* @param int $passDate
*/
public function setPassDate($passDate)
public function getPassDate(): ?int
{
$this->passDate = (int)$passDate;
return $this->passDate;
}
/**
* @return int
*/
public function getPassDateChange()
public function getPassDateChange(): ?int
{
return (int)$this->passDateChange;
return $this->passDateChange;
}
/**
* @param int $passDateChange
*/
public function setPassDateChange($passDateChange)
public function getParentId(): ?int
{
$this->passDateChange = (int)$passDateChange;
return $this->parentId;
}
/**
* @return int
*/
public function getParentId()
{
return (int)$this->parentId;
}
/**
* @param int $parentId
*/
public function setParentId($parentId)
{
$this->parentId = (int)$parentId;
}
/**
* @return int
*/
public function getIsPrivateGroup()
{
return (int)$this->isPrivateGroup;
}
/**
* @param int $isPrivateGroup
*/
public function setIsPrivateGroup($isPrivateGroup)
{
$this->isPrivateGroup = (int)$isPrivateGroup;
}
/**
* @return string
*/
public function getUserEditName()
{
return $this->userEditName;
}
/**
* @return string
*/
public function getUserEditLogin()
{
return $this->userEditLogin;
}
/**
* @return string
*/
public function getPublicLinkHash()
{
return $this->publicLinkHash;
}
/**
* @return string
*/
public function getCategoryName()
public function getCategoryName(): ?string
{
return $this->categoryName;
}
/**
* @return string
*/
public function getClientName()
public function getClientName(): ?string
{
return $this->clientName;
}
/**
* @return string
*/
public function getUserGroupName()
public function getUserGroupName(): ?string
{
return $this->userGroupName;
}
/**
* @return string
*/
public function getUserName()
public function getUserName(): ?string
{
return $this->userName;
}
/**
* @return string
*/
public function getUserLogin()
public function getUserLogin(): ?string
{
return $this->userLogin;
}
}
public function getUserEditName(): ?string
{
return $this->userEditName;
}
public function getUserEditLogin(): ?string
{
return $this->userEditLogin;
}
public function getPublicLinkHash(): ?string
{
return $this->publicLinkHash;
}
}

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -24,7 +24,6 @@
namespace SP\DataModel\Dto;
use SP\DataModel\AccountHistoryData;
use SP\DataModel\AccountSearchVData;
use SP\DataModel\ItemData;
@@ -35,140 +34,127 @@ use SP\DataModel\ItemData;
*/
final class AccountAclDto
{
/**
* @var int
*/
private $accountId;
/**
* @var int
*/
private $userId;
private int $accountId;
private int $userId;
private int $userGroupId;
private int $dateEdit;
/**
* @var ItemData[]
*/
private $usersId;
/**
* @var int
*/
private $userGroupId;
private array $usersId;
/**
* @var ItemData[]
*/
private $userGroupsId;
/**
* @var int
*/
private $dateEdit;
private array $userGroupsId;
private function __construct()
{
/**
* @param int $accountId
* @param int $userId
* @param array $usersId
* @param int $userGroupId
* @param array $userGroupsId
* @param int $dateEdit
*/
public function __construct(
int $accountId,
int $userId,
array $usersId,
int $userGroupId,
array $userGroupsId,
int $dateEdit
) {
$this->accountId = $accountId;
$this->userId = $userId;
$this->usersId = self::buildFromItemData($usersId);
$this->userGroupId = $userGroupId;
$this->userGroupsId = self::buildFromItemData($userGroupsId);
$this->dateEdit = $dateEdit;
}
/**
* @param AccountDetailsResponse $accountDetailsResponse
* @param ItemData[] $items
*
* @return array
*/
private static function buildFromItemData(array $items): array
{
return array_filter($items, static fn($value) => $value instanceof ItemData);
}
/**
* @param AccountDetailsResponse $accountDetailsResponse
*
* @return AccountAclDto
*/
public static function makeFromAccount(AccountDetailsResponse $accountDetailsResponse)
public static function makeFromAccount(AccountDetailsResponse $accountDetailsResponse): AccountAclDto
{
$dto = new self();
$dto->accountId = $accountDetailsResponse->getId();
$dto->userId = $accountDetailsResponse->getAccountVData()->getUserId();
$dto->usersId = $accountDetailsResponse->getUsers();
$dto->userGroupId = $accountDetailsResponse->getAccountVData()->getUserGroupId();
$dto->userGroupsId = $accountDetailsResponse->getUserGroups();
$dto->dateEdit = strtotime($accountDetailsResponse->getAccountVData()->getDateEdit());
return $dto;
return new self(
$accountDetailsResponse->getId(),
$accountDetailsResponse->getAccountVData()->getUserId(),
$accountDetailsResponse->getUsers(),
$accountDetailsResponse->getAccountVData()->getUserGroupId(),
$accountDetailsResponse->getUserGroups(),
strtotime($accountDetailsResponse->getAccountVData()->getDateEdit())
);
}
/**
* @param AccountHistoryData $accountHistoryData
*
* @param array $users
* @param array $userGroups
*
* @return AccountAclDto
*/
public static function makeFromAccountHistory(AccountHistoryData $accountHistoryData, array $users, array $userGroups)
{
$dto = new self();
$dto->accountId = $accountHistoryData->getId();
$dto->userId = $accountHistoryData->getUserId();
$dto->usersId = $users;
$dto->userGroupId = $accountHistoryData->getUserGroupId();
$dto->userGroupsId = $userGroups;
$dto->dateEdit = strtotime($accountHistoryData->getDateEdit());
return $dto;
}
/**
* @param AccountSearchVData $accountSearchVData
*
* @param array $users
* @param array $userGroups
*
* @return AccountAclDto
*/
public static function makeFromAccountSearch(AccountSearchVData $accountSearchVData, array $users, array $userGroups)
{
$dto = new self();
$dto->accountId = $accountSearchVData->getId();
$dto->userId = $accountSearchVData->getUserId();
$dto->usersId = $users;
$dto->userGroupId = $accountSearchVData->getUserGroupId();
$dto->userGroupsId = $userGroups;
$dto->dateEdit = strtotime($accountSearchVData->getDateEdit());
return $dto;
}
/**
* @return int
*/
public function getUserId()
public function getUserId(): int
{
return $this->userId;
}
/**
* @return ItemData[]
*/
public function getUsersId()
{
return $this->usersId;
}
/**
* @return int
*/
public function getUserGroupId()
public function getUserGroupId(): int
{
return $this->userGroupId;
}
/**
* @return ItemData[]
*/
public function getUserGroupsId()
{
return $this->userGroupsId;
}
/**
* @return int
*/
public function getDateEdit()
public function getDateEdit(): int
{
return $this->dateEdit;
}
/**
* @return int
* @param AccountSearchVData $accountSearchVData
*
* @param array $users
* @param array $userGroups
*
* @return AccountAclDto
*/
public function getAccountId()
public static function makeFromAccountSearch(
AccountSearchVData $accountSearchVData,
array $users,
array $userGroups
): AccountAclDto {
return new self(
$accountSearchVData->getId(),
$accountSearchVData->getUserId(),
$users,
$accountSearchVData->getUserGroupId(),
$userGroups,
strtotime($accountSearchVData->getDateEdit())
);
}
public function getAccountId(): int
{
return $this->accountId;
}
}
/**
* @return ItemData[]
*/
public function getUsersId(): array
{
return $this->usersId;
}
/**
* @return ItemData[]
*/
public function getUserGroupsId(): array
{
return $this->userGroupsId;
}
}

View File

@@ -34,8 +34,8 @@ use SP\Domain\Common\Out\DataModelInterface;
*/
class ItemData extends DataModelBase implements DataModelInterface
{
private ?int $id = null;
private ?string $name = null;
protected ?int $id = null;
protected ?string $name = null;
public function getId(): ?int
{

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -33,561 +33,541 @@ defined('APP_ROOT') || die();
*/
class ProfileData
{
/**
* @var bool
*/
protected $accView = false;
/**
* @var bool
*/
protected $accViewPass = false;
/**
* @var bool
*/
protected $accViewHistory = false;
/**
* @var bool
*/
protected $accEdit = false;
/**
* @var bool
*/
protected $accEditPass = false;
/**
* @var bool
*/
protected $accAdd = false;
/**
* @var bool
*/
protected $accDelete = false;
/**
* @var bool
*/
protected $accFiles = false;
/**
* @var bool
*/
protected $accPrivate = false;
/**
* @var bool
*/
protected $accPrivateGroup = false;
/**
* @var bool
*/
protected $accPermission = false;
/**
* @var bool
*/
protected $accPublicLinks = false;
/**
* @var bool
*/
protected $accGlobalSearch = false;
/**
* @var bool
*/
protected $configGeneral = false;
/**
* @var bool
*/
protected $configEncryption = false;
/**
* @var bool
*/
protected $configBackup = false;
/**
* @var bool
*/
protected $configImport = false;
/**
* @var bool
*/
protected $mgmUsers = false;
/**
* @var bool
*/
protected $mgmGroups = false;
/**
* @var bool
*/
protected $mgmProfiles = false;
/**
* @var bool
*/
protected $mgmCategories = false;
/**
* @var bool
*/
protected $mgmCustomers = false;
/**
* @var bool
*/
protected $mgmApiTokens = false;
/**
* @var bool
*/
protected $mgmPublicLinks = false;
/**
* @var bool
*/
protected $mgmAccounts = false;
/**
* @var bool
*/
protected $mgmTags = false;
/**
* @var bool
*/
protected $mgmFiles = false;
/**
* @var bool
*/
protected $mgmItemsPreset = false;
/**
* @var bool
*/
protected $evl = false;
/**
* @var bool
*/
protected $mgmCustomFields = false;
protected bool $accView = false;
protected bool $accViewPass = false;
protected bool $accViewHistory = false;
protected bool $accEdit = false;
protected bool $accEditPass = false;
protected bool $accAdd = false;
protected bool $accDelete = false;
protected bool $accFiles = false;
protected bool $accPrivate = false;
protected bool $accPrivateGroup = false;
protected bool $accPermission = false;
protected bool $accPublicLinks = false;
protected bool $accGlobalSearch = false;
protected bool $configGeneral = false;
protected bool $configEncryption = false;
protected bool $configBackup = false;
protected bool $configImport = false;
protected bool $mgmUsers = false;
protected bool $mgmGroups = false;
protected bool $mgmProfiles = false;
protected bool $mgmCategories = false;
protected bool $mgmCustomers = false;
protected bool $mgmApiTokens = false;
protected bool $mgmPublicLinks = false;
protected bool $mgmAccounts = false;
protected bool $mgmTags = false;
protected bool $mgmFiles = false;
protected bool $mgmItemsPreset = false;
protected bool $evl = false;
protected bool $mgmCustomFields = false;
/**
* @return boolean
*/
public function isAccView()
public function isAccView(): bool
{
return $this->accView;
}
/**
* @param boolean $accView
* @param bool $accView
*
* @return ProfileData
*/
public function setAccView($accView)
public function setAccView(bool $accView): ProfileData
{
$this->accView = $accView;
return $this;
}
/**
* @return boolean
*/
public function isAccViewPass()
public function isAccViewPass(): bool
{
return $this->accViewPass;
}
/**
* @param boolean $accViewPass
* @param bool $accViewPass
*
* @return ProfileData
*/
public function setAccViewPass($accViewPass)
public function setAccViewPass(bool $accViewPass): ProfileData
{
$this->accViewPass = $accViewPass;
return $this;
}
/**
* @return boolean
*/
public function isAccViewHistory()
public function isAccViewHistory(): bool
{
return $this->accViewHistory;
}
/**
* @param boolean $accViewHistory
* @param bool $accViewHistory
*
* @return ProfileData
*/
public function setAccViewHistory($accViewHistory)
public function setAccViewHistory(bool $accViewHistory): ProfileData
{
$this->accViewHistory = $accViewHistory;
return $this;
}
/**
* @return boolean
*/
public function isAccEdit()
public function isAccEdit(): bool
{
return $this->accEdit;
}
/**
* @param boolean $accEdit
* @param bool $accEdit
*
* @return ProfileData
*/
public function setAccEdit($accEdit)
public function setAccEdit(bool $accEdit): ProfileData
{
$this->accEdit = $accEdit;
return $this;
}
/**
* @return boolean
*/
public function isAccEditPass()
public function isAccEditPass(): bool
{
return $this->accEditPass;
}
/**
* @param boolean $accEditPass
* @param bool $accEditPass
*
* @return ProfileData
*/
public function setAccEditPass($accEditPass)
public function setAccEditPass(bool $accEditPass): ProfileData
{
$this->accEditPass = $accEditPass;
return $this;
}
/**
* @return boolean
*/
public function isAccAdd()
public function isAccAdd(): bool
{
return $this->accAdd;
}
/**
* @param boolean $accAdd
* @param bool $accAdd
*
* @return ProfileData
*/
public function setAccAdd($accAdd)
public function setAccAdd(bool $accAdd): ProfileData
{
$this->accAdd = $accAdd;
return $this;
}
/**
* @return boolean
*/
public function isAccDelete()
public function isAccDelete(): bool
{
return $this->accDelete;
}
/**
* @param boolean $accDelete
* @param bool $accDelete
*
* @return ProfileData
*/
public function setAccDelete($accDelete)
public function setAccDelete(bool $accDelete): ProfileData
{
$this->accDelete = $accDelete;
return $this;
}
/**
* @return boolean
*/
public function isAccFiles()
public function isAccFiles(): bool
{
return $this->accFiles;
}
/**
* @param boolean $accFiles
* @param bool $accFiles
*
* @return ProfileData
*/
public function setAccFiles($accFiles)
public function setAccFiles(bool $accFiles): ProfileData
{
$this->accFiles = $accFiles;
return $this;
}
public function isAccPrivate(): bool
{
return $this->accPrivate;
}
/**
* @return boolean
* @param bool $accPrivate
*
* @return ProfileData
*/
public function isAccPublicLinks()
public function setAccPrivate(bool $accPrivate): ProfileData
{
$this->accPrivate = $accPrivate;
return $this;
}
public function isAccPrivateGroup(): bool
{
return $this->accPrivateGroup;
}
/**
* @param bool $accPrivateGroup
*
* @return ProfileData
*/
public function setAccPrivateGroup(bool $accPrivateGroup): ProfileData
{
$this->accPrivateGroup = $accPrivateGroup;
return $this;
}
public function isAccPermission(): bool
{
return $this->accPermission;
}
/**
* @param bool $accPermission
*
* @return ProfileData
*/
public function setAccPermission(bool $accPermission): ProfileData
{
$this->accPermission = $accPermission;
return $this;
}
public function isAccPublicLinks(): bool
{
return $this->accPublicLinks;
}
/**
* @param boolean $accPublicLinks
* @param bool $accPublicLinks
*
* @return ProfileData
*/
public function setAccPublicLinks($accPublicLinks)
public function setAccPublicLinks(bool $accPublicLinks): ProfileData
{
$this->accPublicLinks = $accPublicLinks;
return $this;
}
public function isAccGlobalSearch(): bool
{
return $this->accGlobalSearch;
}
/**
* @return boolean
* @param bool $accGlobalSearch
*
* @return ProfileData
*/
public function isConfigGeneral()
public function setAccGlobalSearch(bool $accGlobalSearch): ProfileData
{
$this->accGlobalSearch = $accGlobalSearch;
return $this;
}
public function isConfigGeneral(): bool
{
return $this->configGeneral;
}
/**
* @param boolean $configGeneral
* @param bool $configGeneral
*
* @return ProfileData
*/
public function setConfigGeneral($configGeneral)
public function setConfigGeneral(bool $configGeneral): ProfileData
{
$this->configGeneral = $configGeneral;
return $this;
}
/**
* @return boolean
*/
public function isConfigEncryption()
public function isConfigEncryption(): bool
{
return $this->configEncryption;
}
/**
* @param boolean $configEncryption
* @param bool $configEncryption
*
* @return ProfileData
*/
public function setConfigEncryption($configEncryption)
public function setConfigEncryption(bool $configEncryption): ProfileData
{
$this->configEncryption = $configEncryption;
return $this;
}
/**
* @return boolean
*/
public function isConfigBackup()
public function isConfigBackup(): bool
{
return $this->configBackup;
}
/**
* @param boolean $configBackup
* @param bool $configBackup
*
* @return ProfileData
*/
public function setConfigBackup($configBackup)
public function setConfigBackup(bool $configBackup): ProfileData
{
$this->configBackup = $configBackup;
return $this;
}
/**
* @return boolean
*/
public function isConfigImport()
public function isConfigImport(): bool
{
return $this->configImport;
}
/**
* @param boolean $configImport
* @param bool $configImport
*
* @return ProfileData
*/
public function setConfigImport($configImport)
public function setConfigImport(bool $configImport): ProfileData
{
$this->configImport = $configImport;
return $this;
}
/**
* @return boolean
*/
public function isMgmUsers()
public function isMgmUsers(): bool
{
return $this->mgmUsers;
}
/**
* @param boolean $mgmUsers
* @param bool $mgmUsers
*
* @return ProfileData
*/
public function setMgmUsers($mgmUsers)
public function setMgmUsers(bool $mgmUsers): ProfileData
{
$this->mgmUsers = $mgmUsers;
return $this;
}
/**
* @return boolean
*/
public function isMgmGroups()
public function isMgmGroups(): bool
{
return $this->mgmGroups;
}
/**
* @param boolean $mgmGroups
* @param bool $mgmGroups
*
* @return ProfileData
*/
public function setMgmGroups($mgmGroups)
public function setMgmGroups(bool $mgmGroups): ProfileData
{
$this->mgmGroups = $mgmGroups;
return $this;
}
/**
* @return boolean
*/
public function isMgmProfiles()
public function isMgmProfiles(): bool
{
return $this->mgmProfiles;
}
/**
* @param boolean $mgmProfiles
* @param bool $mgmProfiles
*
* @return ProfileData
*/
public function setMgmProfiles($mgmProfiles)
public function setMgmProfiles(bool $mgmProfiles): ProfileData
{
$this->mgmProfiles = $mgmProfiles;
return $this;
}
/**
* @return boolean
*/
public function isMgmCategories()
public function isMgmCategories(): bool
{
return $this->mgmCategories;
}
/**
* @param boolean $mgmCategories
* @param bool $mgmCategories
*
* @return ProfileData
*/
public function setMgmCategories($mgmCategories)
public function setMgmCategories(bool $mgmCategories): ProfileData
{
$this->mgmCategories = $mgmCategories;
return $this;
}
/**
* @return boolean
*/
public function isMgmCustomers()
public function isMgmCustomers(): bool
{
return $this->mgmCustomers;
}
/**
* @param boolean $mgmCustomers
* @param bool $mgmCustomers
*
* @return ProfileData
*/
public function setMgmCustomers($mgmCustomers)
public function setMgmCustomers(bool $mgmCustomers): ProfileData
{
$this->mgmCustomers = $mgmCustomers;
return $this;
}
/**
* @return boolean
*/
public function isMgmApiTokens()
public function isMgmApiTokens(): bool
{
return $this->mgmApiTokens;
}
/**
* @param boolean $mgmApiTokens
* @param bool $mgmApiTokens
*
* @return ProfileData
*/
public function setMgmApiTokens($mgmApiTokens)
public function setMgmApiTokens(bool $mgmApiTokens): ProfileData
{
$this->mgmApiTokens = $mgmApiTokens;
return $this;
}
/**
* @return boolean
*/
public function isMgmPublicLinks()
public function isMgmPublicLinks(): bool
{
return $this->mgmPublicLinks;
}
/**
* @param boolean $mgmPublicLinks
* @param bool $mgmPublicLinks
*
* @return ProfileData
*/
public function setMgmPublicLinks($mgmPublicLinks)
public function setMgmPublicLinks(bool $mgmPublicLinks): ProfileData
{
$this->mgmPublicLinks = $mgmPublicLinks;
return $this;
}
public function isMgmAccounts(): bool
{
return $this->mgmAccounts;
}
/**
* @return boolean
* @param bool $mgmAccounts
*
* @return ProfileData
*/
public function isEvl()
public function setMgmAccounts(bool $mgmAccounts): ProfileData
{
$this->mgmAccounts = $mgmAccounts;
return $this;
}
public function isMgmTags(): bool
{
return $this->mgmTags;
}
/**
* @param bool $mgmTags
*
* @return ProfileData
*/
public function setMgmTags(bool $mgmTags): ProfileData
{
$this->mgmTags = $mgmTags;
return $this;
}
public function isMgmFiles(): bool
{
return $this->mgmFiles;
}
/**
* @param bool $mgmFiles
*
* @return ProfileData
*/
public function setMgmFiles(bool $mgmFiles): ProfileData
{
$this->mgmFiles = $mgmFiles;
return $this;
}
public function isMgmItemsPreset(): bool
{
return $this->mgmItemsPreset;
}
/**
* @param bool $mgmItemsPreset
*
* @return ProfileData
*/
public function setMgmItemsPreset(bool $mgmItemsPreset): ProfileData
{
$this->mgmItemsPreset = $mgmItemsPreset;
return $this;
}
public function isEvl(): bool
{
return $this->evl;
}
/**
* @param boolean $evl
* @param bool $evl
*
* @return ProfileData
*/
public function setEvl($evl)
public function setEvl(bool $evl): ProfileData
{
$this->evl = $evl;
return $this;
}
/**
* @return boolean
*/
public function isMgmCustomFields()
public function isMgmCustomFields(): bool
{
return $this->mgmCustomFields;
}
/**
* @param boolean $mgmCustomFields
* @param bool $mgmCustomFields
*
* @return ProfileData
*/
public function setMgmCustomFields($mgmCustomFields)
public function setMgmCustomFields(bool $mgmCustomFields): ProfileData
{
$this->mgmCustomFields = $mgmCustomFields;
@@ -608,181 +588,8 @@ class ProfileData
// Para realizar la conversión de nombre de propiedades que empiezan por _
foreach (get_object_vars($this) as $name => $value) {
if ($name[0] === '_') {
$newName = substr($name, 1);
$this->$newName = $value;
$this->{substr($name, 1)} = $value;
}
}
}
/**
* @return boolean
*/
public function isAccPrivate()
{
return $this->accPrivate;
}
/**
* @param boolean $accPrivate
*
* @return ProfileData
*/
public function setAccPrivate($accPrivate)
{
$this->accPrivate = $accPrivate;
return $this;
}
/**
* @return boolean
*/
public function isAccPermission()
{
return $this->accPermission;
}
/**
* @param boolean $accPermission
*
* @return ProfileData
*/
public function setAccPermission($accPermission)
{
$this->accPermission = $accPermission;
return $this;
}
/**
* @return boolean
*/
public function isMgmAccounts()
{
return $this->mgmAccounts;
}
/**
* @param boolean $mgmAccounts
*
* @return ProfileData
*/
public function setMgmAccounts($mgmAccounts)
{
$this->mgmAccounts = $mgmAccounts;
return $this;
}
/**
* @return boolean
*/
public function isMgmTags()
{
return $this->mgmTags;
}
/**
* @param boolean $mgmTags
*
* @return ProfileData
*/
public function setMgmTags($mgmTags)
{
$this->mgmTags = $mgmTags;
return $this;
}
/**
* @return boolean
*/
public function isMgmFiles()
{
return $this->mgmFiles;
}
/**
* @param boolean $mgmFiles
*
* @return ProfileData
*/
public function setMgmFiles($mgmFiles)
{
$this->mgmFiles = $mgmFiles;
return $this;
}
/**
* @return boolean
*/
public function isAccGlobalSearch()
{
return $this->accGlobalSearch;
}
/**
* @param boolean $accGlobalSearch
*
* @return ProfileData
*/
public function setAccGlobalSearch($accGlobalSearch)
{
$this->accGlobalSearch = $accGlobalSearch;
return $this;
}
/**
* @return bool
*/
public function isAccPrivateGroup()
{
return $this->accPrivateGroup;
}
/**
* @param bool $accPrivateGroup
*
* @return ProfileData
*/
public function setAccPrivateGroup($accPrivateGroup)
{
$this->accPrivateGroup = $accPrivateGroup;
return $this;
}
/**
* @return $this
*/
public function reset()
{
foreach ($this as $property => $value) {
$this->{$property} = false;
}
return $this;
}
/**
* @return bool
*/
public function isMgmItemsPreset(): bool
{
return $this->mgmItemsPreset;
}
/**
* @param bool $mgmItemsPreset
*
* @return ProfileData
*/
public function setMgmItemsPreset(bool $mgmItemsPreset)
{
$this->mgmItemsPreset = $mgmItemsPreset;
return $this;
}
}
}

View File

@@ -42,7 +42,7 @@ trait SerializedModel
* @return mixed|null
* @throws NoSuchPropertyException
*/
public function hydrate(?string $class = null, string $property = 'data')
public function hydrate(?string $class = null, string $property = 'data'): mixed
{
if (property_exists($this, $property)) {
if ($this->{$property} === null) {
@@ -58,4 +58,4 @@ trait SerializedModel
throw new NoSuchPropertyException($property);
}
}
}

View File

@@ -48,14 +48,6 @@ class UserProfileData extends DataModelBase implements DataModelInterface
return $this->name;
}
/**
* @param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* @return int|null
*/
@@ -65,26 +57,10 @@ class UserProfileData extends DataModelBase implements DataModelInterface
}
/**
* @param int $id
* @return \SP\DataModel\ProfileData|null
*/
public function setId($id)
{
$this->id = (int)$id;
}
/**
* @return ProfileData
*/
public function getProfile()
public function getProfile(): ?ProfileData
{
return $this->profile;
}
/**
* @param ProfileData $profile
*/
public function setProfile(ProfileData $profile)
{
$this->profile = $profile;
}
}
}

View File

@@ -30,7 +30,6 @@ use SP\DataModel\Dto\AccountAclDto;
use SP\DataModel\ProfileData;
use SP\Domain\Account\Services\AccountAcl;
use SP\Domain\User\Services\UserLoginResponse;
use SP\Infrastructure\File\FileCacheInterface;
/**
* Class AccountAclService
@@ -53,14 +52,14 @@ interface AccountAclServiceInterface
* Obtener la ACL de una cuenta
*
* @param int $actionId
* @param AccountAclDto|null $accountAclDto
* @param AccountAclDto $accountAclDto
* @param bool $isHistory
*
* @return AccountAcl
* @throws ConstraintException
* @throws QueryException
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public function getAcl(int $actionId, ?AccountAclDto $accountAclDto = null, bool $isHistory = false): AccountAcl;
public function getAcl(int $actionId, AccountAclDto $accountAclDto, bool $isHistory = false): AccountAcl;
/**
* Resturns an stored ACL
@@ -71,21 +70,4 @@ interface AccountAclServiceInterface
* @return \SP\Domain\Account\Services\AccountAcl|null
*/
public function getAclFromCache(int $accountId, int $actionId): ?AccountAcl;
/**
* @param int $accountId
* @param int $actionId
*
* @return string
*/
public function getCacheFileForAcl(int $accountId, int $actionId): string;
/**
* Saves the ACL
*
* @param AccountAcl $accountAcl
*
* @return null|FileCacheInterface
*/
public function saveAclInCache(AccountAcl $accountAcl): ?FileCacheInterface;
}

View File

@@ -24,21 +24,206 @@
namespace SP\Domain\Account;
use SP\Core\Exceptions\ConstraintException;
use SP\Core\Exceptions\NoSuchPropertyException;
use SP\Core\Exceptions\QueryException;
use SP\Core\Exceptions\SPException;
use SP\DataModel\AccountExtData;
use SP\DataModel\AccountHistoryData;
use SP\DataModel\Dto\AccountDetailsResponse;
use SP\DataModel\ItemSearchData;
use SP\Domain\Account\Out\AccountData;
use SP\Domain\Account\Out\AccountPassData;
use SP\Domain\Account\Services\AccountBulkRequest;
use SP\Domain\Account\Services\AccountPasswordRequest;
use SP\Domain\Account\Services\AccountRequest;
use SP\Domain\Common\Services\ServiceException;
use SP\Infrastructure\Common\Repositories\NoSuchItemException;
use SP\Infrastructure\Database\QueryResult;
/**
* Interface AccountServiceInterface
* Class AccountService
*
* @package SP\Domain\Account\Services
*/
interface AccountServiceInterface
{
/**
* @param int $id
* @throws QueryException
* @throws ConstraintException
*/
public function withUsersById(AccountDetailsResponse $accountDetailsResponse): AccountServiceInterface;
/**
* @throws QueryException
* @throws ConstraintException
*/
public function withUserGroupsById(AccountDetailsResponse $accountDetailsResponse): AccountServiceInterface;
/**
* @throws QueryException
* @throws ConstraintException
*/
public function withTagsById(AccountDetailsResponse $accountDetailsResponse): AccountServiceInterface;
/**
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public function incrementViewCounter(int $id): bool;
/**
* @throws QueryException
* @throws ConstraintException
*/
public function incrementDecryptCounter(int $id): bool;
/**
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
* @throws \SP\Infrastructure\Common\Repositories\NoSuchItemException
*/
public function getPasswordForId(int $id): AccountPassData;
/**
* @param \SP\DataModel\AccountHistoryData $data
*
* @return AccountDetailsResponse
* @return int
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public function createFromHistory(AccountHistoryData $data): int;
/**
* @throws QueryException
* @throws SPException
* @throws ConstraintException
* @throws NoSuchPropertyException
*/
public function create(AccountRequest $accountRequest): int;
/**
* Devolver los datos de la clave encriptados
*
* @throws \SP\Domain\Common\Services\ServiceException
*/
public function getPasswordEncrypted(string $pass, ?string $masterPass = null): array;
/**
* @throws QueryException
* @throws NoSuchItemException
* @throws ConstraintException
*/
public function getById(int $id): AccountDetailsResponse;
/**
* Updates external items for the account
*
* @param \SP\Domain\Account\Services\AccountRequest $accountRequest
*
* @throws \SP\Domain\Common\Services\ServiceException
*/
public function update(AccountRequest $accountRequest): void;
/**
* Update accounts in bulk mode
*
* @param \SP\Domain\Account\Services\AccountBulkRequest $request
*
* @throws \SP\Domain\Common\Services\ServiceException
*/
public function updateBulk(AccountBulkRequest $request): void;
/**
* @param \SP\Domain\Account\Services\AccountRequest $accountRequest
*
* @throws \SP\Domain\Common\Services\ServiceException
*/
public function editPassword(AccountRequest $accountRequest): void;
/**
* Updates an already encrypted password data from a master password changing action
*
* @throws ConstraintException
* @throws QueryException
*/
public function updatePasswordMasterPass(AccountPasswordRequest $accountRequest): bool;
/**
* @param int $historyId
* @param int $accountId
*
* @throws \SP\Domain\Common\Services\ServiceException
* @throws \SP\Infrastructure\Common\Repositories\NoSuchItemException
*/
public function editRestore(int $historyId, int $accountId): void;
/**
* @throws \SP\Domain\Common\Services\ServiceException
*/
public function delete(int $id): AccountServiceInterface;
/**
* @param int[] $ids
*
* @throws SPException
* @throws ServiceException
*/
public function deleteByIdBatch(array $ids): AccountServiceInterface;
/**
* @throws QueryException
* @throws ConstraintException
*/
public function getForUser(?int $accountId = null): array;
/**
* @throws QueryException
* @throws ConstraintException
*/
public function getLinked(int $accountId): array;
/**
* @throws QueryException
* @throws ConstraintException
* @throws NoSuchItemException
*/
public function getPasswordHistoryForId(int $id): AccountPassData;
/**
* @return AccountData[]
*/
public function getAllBasic(): array;
/**
* @param \SP\DataModel\ItemSearchData $itemSearchData
*
* @return \SP\Infrastructure\Database\QueryResult
*/
public function search(ItemSearchData $itemSearchData): QueryResult;
/**
* Devolver el número total de cuentas
*
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public function getTotalNumAccounts(): int;
/**
* Obtener los datos de una cuenta.
*
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
* @throws \SP\Infrastructure\Common\Repositories\NoSuchItemException
*/
public function getDataForLink(int $id): AccountExtData;
/**
* Obtener los datos relativos a la clave de todas las cuentas.
*
* @throws QueryException
* @throws ConstraintException
*/
public function getAccountsPassData(): array;
}

View File

@@ -135,6 +135,11 @@ final class AccountAcl
|| $this->actionId === ActionsInterface::ACCOUNT_DELETE);
}
/**
* @param bool $showDetails
*
* @return AccountAcl
*/
public function setShowDetails(bool $showDetails): AccountAcl
{
$this->showDetails = $showDetails;
@@ -148,6 +153,11 @@ final class AccountAcl
|| $this->actionId === ActionsInterface::ACCOUNT_COPY);
}
/**
* @param bool $showPass
*
* @return AccountAcl
*/
public function setShowPass(bool $showPass): AccountAcl
{
$this->showPass = $showPass;
@@ -194,6 +204,11 @@ final class AccountAcl
|| $this->actionId === ActionsInterface::ACCOUNT_COPY;
}
/**
* @param bool $showSave
*
* @return AccountAcl
*/
public function setShowSave(bool $showSave): AccountAcl
{
$this->showSave = $showSave;
@@ -394,18 +409,6 @@ final class AccountAcl
return $this;
}
public function isHistory(): bool
{
return $this->isHistory;
}
public function setIsHistory(bool $isHistory): AccountAcl
{
$this->isHistory = $isHistory;
return $this;
}
public function isCompiledShowAccess(): bool
{
return $this->compiledShowAccess;
@@ -432,7 +435,7 @@ final class AccountAcl
public function reset(): void
{
foreach ($this as $property => $value) {
foreach (get_class_vars(__CLASS__) as $property => $value) {
if (str_starts_with($property, 'show')) {
$this->{$property} = false;
}

View File

@@ -27,8 +27,9 @@ namespace SP\Domain\Account\Services;
use SP\Core\Acl\Acl;
use SP\Core\Acl\ActionsInterface;
use SP\Core\Application;
use SP\Core\Events\Event;
use SP\Core\Events\EventMessage;
use SP\Core\Exceptions\ConstraintException;
use SP\Core\Exceptions\FileNotFoundException;
use SP\Core\Exceptions\QueryException;
use SP\DataModel\Dto\AccountAclDto;
use SP\DataModel\ProfileData;
@@ -36,10 +37,9 @@ use SP\Domain\Account\AccountAclServiceInterface;
use SP\Domain\Common\Services\Service;
use SP\Domain\User\Services\UserLoginResponse;
use SP\Domain\User\UserToUserGroupServiceInterface;
use SP\Infrastructure\File\FileCache;
use SP\Infrastructure\File\FileCacheInterface;
use SP\Infrastructure\File\FileException;
use SP\Util\FileUtil;
use function SP\processException;
/**
* Class AccountAclService
@@ -52,92 +52,76 @@ final class AccountAclService extends Service implements AccountAclServiceInterf
* ACL's file base path
*/
public const ACL_PATH = CACHE_PATH.DIRECTORY_SEPARATOR.'accountAcl'.DIRECTORY_SEPARATOR;
public static bool $useCache = true;
private ?AccountAclDto $accountAclDto = null;
private ?AccountAcl $accountAcl = null;
private Acl $acl;
private ?FileCacheInterface $fileCache;
private UserToUserGroupServiceInterface $userToUserGroupService;
private UserLoginResponse $userData;
public function __construct(Application $application, Acl $acl, UserToUserGroupServiceInterface $userGroupService)
{
public function __construct(
Application $application,
Acl $acl,
UserToUserGroupServiceInterface $userGroupService,
?FileCacheInterface $fileCache = null
) {
parent::__construct($application);
$this->acl = $acl;
$this->userToUserGroupService = $userGroupService;
$this->userData = $this->context->getUserData();
}
/**
* @param $userId
*
* @return bool
*/
public static function clearAcl($userId): bool
{
logger(sprintf('Clearing ACL for user ID: %d', $userId));
try {
if (FileUtil::rmdir_recursive(self::ACL_PATH.$userId) === false) {
logger(sprintf('Unable to delete %s directory', self::ACL_PATH.$userId));
return false;
}
return true;
} catch (FileNotFoundException $e) {
processException($e);
}
return false;
$this->fileCache = $fileCache;
}
/**
* Obtener la ACL de una cuenta
*
* @param int $actionId
* @param AccountAclDto|null $accountAclDto
* @param AccountAclDto $accountAclDto
* @param bool $isHistory
*
* @return AccountAcl
* @throws ConstraintException
* @throws QueryException
*/
public function getAcl(int $actionId, ?AccountAclDto $accountAclDto = null, bool $isHistory = false): AccountAcl
public function getAcl(int $actionId, AccountAclDto $accountAclDto, bool $isHistory = false): AccountAcl
{
$this->accountAcl = new AccountAcl($actionId, $isHistory);
$this->accountAcl->setShowPermission(
self::getShowPermission($this->context->getUserData(), $this->context->getUserProfile())
);
if ($accountAclDto !== null) {
$this->accountAclDto = $accountAclDto;
$this->accountAclDto = $accountAclDto;
if (null !== $this->fileCache) {
$accountAcl = $this->getAclFromCache($accountAclDto->getAccountId(), $actionId);
if (self::$useCache && null !== $accountAcl) {
$this->accountAcl->setModified(
(
$accountAclDto->getDateEdit() > $accountAcl->getTime()
|| $this->userData->getLastUpdate() > $accountAcl->getTime()
)
);
if (null !== $accountAcl) {
$isModified = $accountAclDto->getDateEdit() > $accountAcl->getTime()
|| $this->userData->getLastUpdate() > $accountAcl->getTime();
if (!$this->accountAcl->isModified()) {
logger('Account ACL HIT');
if (!$isModified) {
$this->eventDispatcher->notifyEvent(
'get.acl',
new Event($this, EventMessage::factory()->addDescription('Account ACL HIT'))
);
return $accountAcl;
}
$this->accountAcl->setModified(true);
}
logger('Account ACL MISS');
$this->accountAcl->setAccountId($accountAclDto->getAccountId());
return $this->updateAcl();
}
return $this->accountAcl;
$this->eventDispatcher->notifyEvent(
'get.acl',
new Event($this, EventMessage::factory()->addDescription('Account ACL MISS'))
);
$this->accountAcl->setAccountId($accountAclDto->getAccountId());
return $this->buildAcl();
}
/**
@@ -161,18 +145,18 @@ final class AccountAclService extends Service implements AccountAclServiceInterf
* @param int $accountId
* @param int $actionId
*
* @return AccountAcl
* @return \SP\Domain\Account\Services\AccountAcl|null
*/
public function getAclFromCache(int $accountId, int $actionId): ?AccountAcl
{
try {
$acl = FileCache::factory($this->getCacheFileForAcl($accountId, $actionId))->load();
$acl = $this->fileCache->load($this->getCacheFileForAcl($accountId, $actionId));
if ($acl instanceof AccountAcl) {
return $acl;
}
} catch (FileException $e) {
logger($e->getMessage());
processException($e);
}
return null;
@@ -184,7 +168,7 @@ final class AccountAclService extends Service implements AccountAclServiceInterf
*
* @return string
*/
public function getCacheFileForAcl(int $accountId, int $actionId): string
private function getCacheFileForAcl(int $accountId, int $actionId): string
{
$userId = $this->context->getUserData()->getId();
@@ -197,41 +181,13 @@ final class AccountAclService extends Service implements AccountAclServiceInterf
.'.cache';
}
/**
* Actualizar la ACL
*
* @return AccountAcl
* @throws ConstraintException
* @throws QueryException
*/
private function updateAcl(): AccountAcl
{
if ($this->checkComponents()) {
$this->makeAcl();
}
if (self::$useCache) {
$this->saveAclInCache($this->accountAcl);
}
return $this->accountAcl;
}
/**
* @return bool
*/
private function checkComponents(): bool
{
return null !== $this->accountAclDto;
}
/**
* Crear la ACL de una cuenta
*
* @throws ConstraintException
* @throws QueryException
*/
private function makeAcl(): void
private function buildAcl(): AccountAcl
{
$this->compileAccountAccess();
$this->accountAcl->setCompiledAccountAccess(true);
@@ -240,6 +196,10 @@ final class AccountAclService extends Service implements AccountAclServiceInterf
$this->accountAcl->setCompiledShowAccess(true);
$this->accountAcl->setTime(time());
$this->saveAclInCache($this->accountAcl);
return $this->accountAcl;
}
/**
@@ -318,7 +278,7 @@ final class AccountAclService extends Service implements AccountAclServiceInterf
array_filter(
$this->accountAclDto->getUsersId(),
static function ($value) use ($userId) {
return (int)$value->id === $userId;
return (int)$value->getId() === $userId;
}
)
);
@@ -355,11 +315,11 @@ final class AccountAclService extends Service implements AccountAclServiceInterf
array_filter(
$this->accountAclDto->getUserGroupsId(),
static function ($value) use ($userGroupId, $isAccountFullGroupAccess, $userGroups) {
return (int)$value->id === $userGroupId
return (int)$value->getId() === $userGroupId
// o... permitir los grupos que no sean el principal del usuario?
|| ($isAccountFullGroupAccess
// Comprobar si el usuario está vinculado desde los grupos secundarios de la cuenta
&& in_array((int)$value->id, $userGroups, true));
&& in_array((int)$value->getId(), $userGroups, true));
}
)
);
@@ -406,16 +366,21 @@ final class AccountAclService extends Service implements AccountAclServiceInterf
*
* @param AccountAcl $accountAcl
*
* @return null|FileCacheInterface
* @return void
*/
public function saveAclInCache(AccountAcl $accountAcl): ?FileCacheInterface
private function saveAclInCache(AccountAcl $accountAcl): void
{
if (null === $this->fileCache) {
return;
}
try {
return FileCache::factory(
$this->fileCache->save(
$accountAcl,
$this->getCacheFileForAcl($accountAcl->getAccountId(), $accountAcl->getActionId())
)->save($accountAcl);
);
} catch (FileException $e) {
return null;
processException($e);
}
}
}
}

View File

@@ -33,6 +33,7 @@ use SP\Core\Events\EventMessage;
use SP\Core\Exceptions\SPException;
use SP\Domain\Account\AccountCryptServiceInterface;
use SP\Domain\Account\AccountHistoryServiceInterface;
use SP\Domain\Account\AccountServiceInterface;
use SP\Domain\Common\Services\Service;
use SP\Domain\Common\Services\ServiceException;
use SP\Domain\Crypt\Services\UpdateMasterPassRequest;
@@ -52,7 +53,7 @@ final class AccountCryptService extends Service implements AccountCryptServiceIn
public function __construct(
Application $application,
AccountService $accountService,
AccountServiceInterface $accountService,
AccountHistoryServiceInterface $accountHistoryService
) {
parent::__construct($application);
@@ -274,4 +275,4 @@ final class AccountCryptService extends Service implements AccountCryptServiceIn
);
}
}
}
}

View File

@@ -294,9 +294,6 @@ final class AccountSearchItem
public function isWikiMatch(string $wikiFilter): bool
{
return preg_match(
'/^'.$wikiFilter.'/i',
$this->accountSearchVData->getName()
) === 1;
return preg_match('/^'.$wikiFilter.'/i', $this->accountSearchVData->getName()) === 1;
}
}
}

View File

@@ -55,6 +55,8 @@ use SP\Domain\ItemPreset\ItemPresetInterface;
use SP\Domain\ItemPreset\ItemPresetServiceInterface;
use SP\Infrastructure\Common\Repositories\NoSuchItemException;
use SP\Infrastructure\Database\QueryResult;
use function SP\__u;
use function SP\logger;
/**
* Class AccountService
@@ -72,7 +74,6 @@ final class AccountService extends Service implements AccountServiceInterface
private ItemPresetServiceInterface $itemPresetService;
private AccountHistoryServiceInterface $accountHistoryService;
private ConfigServiceInterface $configService;
private AccountFilterUserInterface $accountFilterUser;
public function __construct(
Application $application,
@@ -83,7 +84,6 @@ final class AccountService extends Service implements AccountServiceInterface
ItemPresetServiceInterface $itemPresetService,
AccountHistoryServiceInterface $accountHistoryService,
ConfigServiceInterface $configService,
AccountFilterUserInterface $accountFilterUser
) {
$this->accountRepository = $accountRepository;
$this->accountToUserGroupRepository = $accountToUserGroupRepository;
@@ -92,7 +92,6 @@ final class AccountService extends Service implements AccountServiceInterface
$this->itemPresetService = $itemPresetService;
$this->accountHistoryService = $accountHistoryService;
$this->configService = $configService;
$this->accountFilterUser = $accountFilterUser;
parent::__construct($application);
}
@@ -101,7 +100,7 @@ final class AccountService extends Service implements AccountServiceInterface
* @throws QueryException
* @throws ConstraintException
*/
public function withUsersById(AccountDetailsResponse $accountDetailsResponse): AccountService
public function withUsersById(AccountDetailsResponse $accountDetailsResponse): AccountServiceInterface
{
$accountDetailsResponse->setUsers(
$this->accountToUserRepository->getUsersByAccountId($accountDetailsResponse->getId())
@@ -115,7 +114,7 @@ final class AccountService extends Service implements AccountServiceInterface
* @throws QueryException
* @throws ConstraintException
*/
public function withUserGroupsById(AccountDetailsResponse $accountDetailsResponse): AccountService
public function withUserGroupsById(AccountDetailsResponse $accountDetailsResponse): AccountServiceInterface
{
$accountDetailsResponse->setUserGroups(
$this->accountToUserGroupRepository->getUserGroupsByAccountId($accountDetailsResponse->getId())
@@ -129,7 +128,7 @@ final class AccountService extends Service implements AccountServiceInterface
* @throws QueryException
* @throws ConstraintException
*/
public function withTagsById(AccountDetailsResponse $accountDetailsResponse): AccountService
public function withTagsById(AccountDetailsResponse $accountDetailsResponse): AccountServiceInterface
{
$accountDetailsResponse->setTags(
$this->accountToTagRepository->getTagsByAccountId($accountDetailsResponse->getId())
@@ -177,6 +176,8 @@ final class AccountService extends Service implements AccountServiceInterface
* @param \SP\DataModel\AccountHistoryData $data
*
* @return int
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public function createFromHistory(AccountHistoryData $data): int
{
@@ -327,7 +328,6 @@ final class AccountService extends Service implements AccountServiceInterface
private function addItems(AccountRequest $accountRequest): void
{
try {
if ($accountRequest->changePermissions) {
if (is_array($accountRequest->userGroupsView)
&& count($accountRequest->userGroupsView) !== 0
@@ -380,29 +380,25 @@ final class AccountService extends Service implements AccountServiceInterface
$userData = $this->context->getUserData();
$accountPermission = $itemPresetData->hydrate(AccountPermission::class);
$accountRequest = new AccountRequest();
$accountRequest->id = $accountId;
$accountRequest->usersView = array_diff($accountPermission->getUsersView(), [$userData->getId()]);
$accountRequest->usersEdit = array_diff($accountPermission->getUsersEdit(), [$userData->getId()]);
$accountRequest->userGroupsView =
array_diff($accountPermission->getUserGroupsView(), [$userData->getUserGroupId()]);
$accountRequest->userGroupsEdit =
array_diff($accountPermission->getUserGroupsEdit(), [$userData->getUserGroupId()]);
$usersView = array_diff($accountPermission->getUsersView(), [$userData->getId()]);
$usersEdit = array_diff($accountPermission->getUsersEdit(), [$userData->getId()]);
$userGroupsView = array_diff($accountPermission->getUserGroupsView(), [$userData->getUserGroupId()]);
$userGroupsEdit = array_diff($accountPermission->getUserGroupsEdit(), [$userData->getUserGroupId()]);
if (!empty($accountRequest->usersView)) {
$this->accountToUserRepository->addByType($accountRequest, false);
if (count($usersView) !== 0) {
$this->accountToUserRepository->addByType($accountId, $usersView, false);
}
if (!empty($accountRequest->usersEdit)) {
$this->accountToUserRepository->addByType($accountRequest, true);
if (count($usersEdit) !== 0) {
$this->accountToUserRepository->addByType($accountId, $usersEdit, true);
}
if (!empty($accountRequest->userGroupsView)) {
$this->accountToUserGroupRepository->addByType($accountRequest, false);
if (count($userGroupsView) !== 0) {
$this->accountToUserGroupRepository->addByType($accountId, $userGroupsView, false);
}
if (!empty($accountRequest->userGroupsEdit)) {
$this->accountToUserGroupRepository->addByType($accountRequest, true);
if (count($userGroupsEdit) !== 0) {
$this->accountToUserGroupRepository->addByType($accountId, $userGroupsEdit, true);
}
}
}
@@ -642,13 +638,13 @@ final class AccountService extends Service implements AccountServiceInterface
/**
* @throws \SP\Domain\Common\Services\ServiceException
*/
public function delete(int $id): AccountService
public function delete(int $id): AccountServiceInterface
{
$this->accountRepository->transactionAware(
function () use ($id) {
$this->addHistory($id, 1);
if ($this->accountRepository->delete($id) === 0) {
if ($this->accountRepository->delete($id)) {
throw new NoSuchItemException(__u('Account not found'));
}
}
@@ -663,7 +659,7 @@ final class AccountService extends Service implements AccountServiceInterface
* @throws SPException
* @throws ServiceException
*/
public function deleteByIdBatch(array $ids): AccountService
public function deleteByIdBatch(array $ids): AccountServiceInterface
{
if ($this->accountRepository->deleteByIdBatch($ids) === 0) {
throw new ServiceException(__u('Error while deleting the accounts'));
@@ -708,8 +704,6 @@ final class AccountService extends Service implements AccountServiceInterface
/**
* @return AccountData[]
* @throws QueryException
* @throws ConstraintException
*/
public function getAllBasic(): array
{

View File

@@ -24,19 +24,16 @@
namespace SP\Domain\Common\Services;
use Closure;
use Defuse\Crypto\Exception\CryptoException;
use Exception;
use SP\Core\Application;
use SP\Core\Context\ContextException;
use SP\Core\Context\ContextInterface;
use SP\Core\Context\SessionContext;
use SP\Core\Crypt\Session;
use SP\Core\Events\Event;
use SP\Core\Events\EventDispatcher;
use SP\Core\Events\EventMessage;
use SP\Domain\Config\ConfigInterface;
use SP\Infrastructure\Database\DatabaseInterface;
use function SP\__u;
use function SP\logger;
/**
* Class Service
@@ -58,42 +55,6 @@ abstract class Service
$this->eventDispatcher = $application->getEventDispatcher();
}
/**
* Bubbles a Closure in a database transaction
*
* @param \Closure $closure
* @param \SP\Infrastructure\Database\DatabaseInterface $database
*
* @return mixed
* @throws \SP\Domain\Common\Services\ServiceException
* @throws \Exception
*/
protected function transactionAware(Closure $closure, DatabaseInterface $database)
{
if ($database->beginTransaction()) {
try {
$result = $closure->call($this);
$database->endTransaction();
return $result;
} catch (Exception $e) {
$database->rollbackTransaction();
logger('Transaction:Rollback');
$this->eventDispatcher->notifyEvent(
'database.rollback',
new Event($this, EventMessage::factory()->addDescription(__u('Rollback')))
);
throw $e;
}
} else {
throw new ServiceException(__u('Unable to start a transaction'));
}
}
/**
* @throws ServiceException
*/
@@ -135,4 +96,4 @@ abstract class Service
throw new ServiceException(__u('Error while setting master password in context'));
}
}
}
}

View File

@@ -48,7 +48,7 @@ final class ConfigData extends DataCollection implements JsonSerializable, Confi
public function getAttributes(): array
{
return $this->attributes;
return $this->getArrayCopy();
}
public function getLogEvents(): array
@@ -374,7 +374,7 @@ final class ConfigData extends DataCollection implements JsonSerializable, Confi
*/
public function setConfigHash(): ConfigDataInterface
{
$this->set(ConfigDataInterface::CONFIG_HASH, sha1(serialize($this->attributes)));
$this->set(ConfigDataInterface::CONFIG_HASH, sha1(serialize($this->getArrayCopy())));
return $this;
}
@@ -910,7 +910,7 @@ final class ConfigData extends DataCollection implements JsonSerializable, Confi
*/
public function jsonSerialize(): array
{
return $this->attributes;
return $this->getArrayCopy();
}
public function getConfigSaver(): ?string

View File

@@ -39,6 +39,7 @@ use SP\Infrastructure\File\FileException;
use SP\Infrastructure\File\XmlFileStorageInterface;
use SP\Util\PasswordUtil;
use function SP\logger;
use function SP\processException;
defined('APP_ROOT') || die();

View File

@@ -50,7 +50,7 @@ final class CustomFieldItem implements JsonSerializable
/**
* @inheritDoc
*/
public function jsonSerialize()
public function jsonSerialize(): array
{
return [
'required' => $this->required,
@@ -65,4 +65,4 @@ final class CustomFieldItem implements JsonSerializable
'isValueEncrypted' => $this->isValueEncrypted,
];
}
}
}

View File

@@ -48,6 +48,8 @@ use SP\Domain\User\UserServiceInterface;
use SP\Http\RequestInterface;
use SP\Infrastructure\Database\DatabaseConnectionData;
use SP\Util\VersionUtil;
use function SP\__u;
use function SP\processException;
defined('APP_ROOT') || die();
@@ -340,9 +342,7 @@ final class InstallerService implements InstallerServiceInterface
$userGroupData->setName('Admins');
$userGroupData->setDescription('sysPass Admins');
$userProfileData = new UserProfileData();
$userProfileData->setName('Admin');
$userProfileData->setProfile(new ProfileData());
$userProfileData = new UserProfileData(['name' => 'Admin', 'profile' => new ProfileData()]);
$userData = new UserData();
$userData->setUserGroupId($this->userGroupService->create($userGroupData));
@@ -374,4 +374,4 @@ final class InstallerService implements InstallerServiceInterface
);
}
}
}
}

View File

@@ -33,6 +33,10 @@ use SP\Infrastructure\Database\DatabaseUtil;
use SP\Infrastructure\Database\DbStorageInterface;
use SP\Infrastructure\File\FileException;
use SP\Util\PasswordUtil;
use function SP\__;
use function SP\__u;
use function SP\logger;
use function SP\processException;
/**
* Class MySQL
@@ -189,7 +193,6 @@ final class MysqlService implements DatabaseSetupInterface
public function createDatabase(?string $dbUser = null): void
{
if (!$this->installData->isHostingMode()) {
if ($this->checkDatabaseExists()) {
throw new SPException(
__u('The database already exists'),
@@ -401,4 +404,4 @@ final class MysqlService implements DatabaseSetupInterface
);
}
}
}
}

View File

@@ -29,21 +29,25 @@ namespace SP\Infrastructure\File;
*
* @package SP\Infrastructure\File;
*/
final class FileCache extends FileCacheBase
class FileCache extends FileCacheBase
{
/**
* @throws FileException
*/
public function load()
public function load(?string $path = null): mixed
{
$this->checkOrInitializePath($path);
/** @noinspection UnserializeExploitsInspection */
return unserialize($this->path->checkIsReadable()->readToString());
}
/**
* @throws FileException
*/
public function save($data): FileCacheInterface
public function save(mixed $data, ?string $path = null): FileCacheInterface
{
$this->checkOrInitializePath($path);
$this->createPath();
$this->path->checkIsWritable();
@@ -53,4 +57,4 @@ final class FileCache extends FileCacheBase
return $this;
}
}
}

View File

@@ -24,6 +24,7 @@
namespace SP\Infrastructure\File;
use function SP\__;
/**
* Class FileCacheBase
@@ -32,11 +33,13 @@ namespace SP\Infrastructure\File;
*/
abstract class FileCacheBase implements FileCacheInterface
{
protected FileHandler $path;
protected ?FileHandler $path = null;
public function __construct(string $path)
public function __construct(?string $path = null)
{
$this->path = new FileHandler($path);
if (null !== $path) {
$this->path = new FileHandler($path);
}
}
public static function factory(string $path): FileCacheBase
@@ -96,4 +99,18 @@ abstract class FileCacheBase implements FileCacheInterface
{
return file_exists($this->path->getFile());
}
}
/**
* @throws \SP\Infrastructure\File\FileException
*/
protected function checkOrInitializePath(?string $path = null): void
{
if (null === $path && null === $this->path) {
throw new FileException(__('Path is needed'));
}
if (null === $this->path || $this->path->getFile() !== $path) {
$this->path = new FileHandler($path);
}
}
}

View File

@@ -32,15 +32,17 @@ namespace SP\Infrastructure\File;
interface FileCacheInterface
{
/**
* @param string|null $path
*
* @return mixed
* @throws FileException
* @throws \SP\Infrastructure\File\FileException
*/
public function load();
public function load(?string $path = null): mixed;
/**
* @throws FileException
*/
public function save($data): FileCacheInterface;
public function save(mixed $data, ?string $path = null): FileCacheInterface;
public function delete(): FileCacheInterface;
@@ -57,4 +59,4 @@ interface FileCacheInterface
public function isExpiredDate(int $date): bool;
public function exists(): bool;
}
}

View File

@@ -37,8 +37,10 @@ final class FileCachePacked extends FileCacheBase
* @throws RuntimeException
* @throws FileException
*/
public function load()
public function load(?string $path = null): mixed
{
$this->checkOrInitializePath($path);
$this->path->checkIsReadable();
$dataUnpacked = gzuncompress($this->path->readToString());
@@ -63,8 +65,9 @@ final class FileCachePacked extends FileCacheBase
/**
* @throws FileException
*/
public function save($data): FileCacheInterface
public function save(mixed $data, ?string $path = null): FileCacheInterface
{
$this->checkOrInitializePath($path);
$this->createPath();
$data = gzcompress(serialize($data));
@@ -82,4 +85,4 @@ final class FileCachePacked extends FileCacheBase
return $this;
}
}
}

View File

@@ -25,6 +25,7 @@
namespace SP\Infrastructure\File;
use SP\Util\Util;
use function SP\logger;
/**
* Class FileHandler
@@ -339,4 +340,4 @@ final class FileHandler implements FileHandlerInterface
return filemtime($this->file) ?: 0;
}
}
}

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -28,6 +28,7 @@ use Exception;
use SP\Core\Application;
use SP\Core\Events\Event;
use SP\Core\Events\EventReceiver;
use SP\Core\Exceptions\FileNotFoundException;
use SP\Core\Exceptions\SPException;
use SP\Domain\Account\Services\AccountAclService;
use SP\Domain\User\Services\UserGroupService;
@@ -36,7 +37,11 @@ use SP\Domain\User\UserGroupServiceInterface;
use SP\Domain\User\UserProfileServiceInterface;
use SP\Providers\EventsTrait;
use SP\Providers\Provider;
use SP\Util\FileUtil;
use SplSubject;
use function SP\__u;
use function SP\logger;
use function SP\processException;
/**
* Class AclHandler
@@ -70,7 +75,6 @@ final class AclHandler extends Provider implements EventReceiver
parent::__construct($application);
}
/**
* Devuelve los eventos que implementa el observador
*
@@ -147,7 +151,7 @@ final class AclHandler extends Provider implements EventReceiver
if (isset($extra['userProfileId'])) {
foreach ($this->userProfileService->getUsersForProfile($extra['userProfileId'][0]) as $user) {
AccountAclService::clearAcl($user->id);
$this->clearAcl($user->id);
}
}
} catch (Exception $e) {
@@ -155,6 +159,30 @@ final class AclHandler extends Provider implements EventReceiver
}
}
/**
* @param $userId
*
* @return bool
*/
private function clearAcl($userId): bool
{
logger(sprintf('Clearing ACL for user ID: %d', $userId));
try {
if (FileUtil::rmdirRecursive(AccountAclService::ACL_PATH.$userId) === false) {
logger(sprintf('Unable to delete %s directory', AccountAclService::ACL_PATH.$userId));
return false;
}
return true;
} catch (FileNotFoundException $e) {
processException($e);
}
return false;
}
/**
* @throws \SP\Core\Exceptions\SPException
*/
@@ -170,7 +198,7 @@ final class AclHandler extends Provider implements EventReceiver
if (isset($extra['userId'])) {
foreach ($extra['userId'] as $id) {
AccountAclService::clearAcl($id);
$this->clearAcl($id);
}
}
}
@@ -188,7 +216,7 @@ final class AclHandler extends Provider implements EventReceiver
if (isset($extra['userGroupId'])) {
foreach ($this->userGroupService->getUsageByUsers($extra['userGroupId'][0]) as $user) {
AccountAclService::clearAcl($user->id);
$this->clearAcl($user->id);
}
}
} catch (Exception $e) {
@@ -201,4 +229,4 @@ final class AclHandler extends Provider implements EventReceiver
$this->events = $this->parseEventsToRegex(self::EVENTS);
$this->initialized = true;
}
}
}

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -35,7 +35,7 @@ use SP\DataModel\FileData;
*
* @package SP\Util
*/
final class FileUtil
class FileUtil
{
private const IMAGE_MIME = [
'image/jpeg',
@@ -50,7 +50,7 @@ final class FileUtil
* @throws \SP\Core\Exceptions\FileNotFoundException
* @see https://stackoverflow.com/a/7288067
*/
public static function rmdir_recursive(string $dir): bool
public static function rmdirRecursive(string $dir): bool
{
if (!is_dir($dir)) {
throw new FileNotFoundException('Directory does not exist');
@@ -79,4 +79,4 @@ final class FileUtil
{
return in_array(strtolower($fileData->getType()), self::IMAGE_MIME, true);
}
}
}

View File

@@ -1,3 +1,4 @@
parameters:
bootstrapFiles:
- lib/BaseFunctions.php
- lib/BaseFunctions.php
- lib/Base.php

View File

@@ -0,0 +1,834 @@
<?php
/*
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2022, 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\Domain\Account\Services;
use SP\Core\Acl\Acl;
use SP\Core\Acl\ActionsInterface;
use SP\Core\Exceptions\ConstraintException;
use SP\Core\Exceptions\QueryException;
use SP\DataModel\Dto\AccountAclDto;
use SP\DataModel\Dto\AccountDetailsResponse;
use SP\DataModel\ItemData;
use SP\Domain\Account\Services\AccountAcl;
use SP\Domain\Account\Services\AccountAclService;
use SP\Domain\Common\Out\SimpleModel;
use SP\Domain\User\UserToUserGroupServiceInterface;
use SP\Infrastructure\File\FileCacheInterface;
use SP\Infrastructure\File\FileException;
use SP\Tests\UnitaryTestCase;
/**
* Class AccountAclServiceTest
*
* @package SP\Tests\Services
*/
class AccountAclServiceTest extends UnitaryTestCase
{
private const ACTIONS = [
ActionsInterface::ACCOUNT_SEARCH,
ActionsInterface::ACCOUNT_VIEW,
ActionsInterface::ACCOUNT_VIEW_PASS,
ActionsInterface::ACCOUNT_HISTORY_VIEW,
ActionsInterface::ACCOUNT_CREATE,
ActionsInterface::ACCOUNT_EDIT,
ActionsInterface::ACCOUNT_EDIT_PASS,
ActionsInterface::ACCOUNT_EDIT_RESTORE,
ActionsInterface::ACCOUNT_COPY,
ActionsInterface::ACCOUNT_COPY_PASS,
ActionsInterface::ACCOUNT_DELETE,
];
private static array $accounts;
protected AccountDetailsResponse $account;
private AccountAclService $accountAclService;
public static function setUpBeforeClass(): void
{
parent::setUpBeforeClass();
self::$accounts = [
1 => [
'userGroupId' => 1,
'userId' => 1,
'isPrivate' => 0,
'isPrivateGroup' => 0,
'otherUserGroupEdit' => 0,
'otherUserEdit' => 0,
'users' => [new ItemData(['id' => 3, 'isEdit' => 1])],
'groups' => [new ItemData(['id' => 2, 'isEdit' => 1])],
],
2 => [
'userGroupId' => 1,
'userId' => 1,
'isPrivate' => 0,
'isPrivateGroup' => 0,
'otherUserGroupEdit' => 0,
'otherUserEdit' => 0,
'users' => [],
'groups' => [
new ItemData(['id' => 2, 'isEdit' => 1]),
new ItemData(['id' => 3, 'isEdit' => 1]),
],
],
3 => [
'userGroupId' => 3,
'userId' => 3,
'isPrivate' => 1,
'isPrivateGroup' => 0,
'otherUserGroupEdit' => 0,
'otherUserEdit' => 0,
'users' => [],
'groups' => [],
],
4 => [
'userGroupId' => 3,
'userId' => 3,
'isPrivate' => 0,
'isPrivateGroup' => 1,
'otherUserGroupEdit' => 0,
'otherUserEdit' => 0,
'users' => [],
'groups' => [],
],
];
}
/**
* @group acl:admin
*
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public function testGetAclForAdminApp(): void
{
$this->context
->getUserProfile()
->setAccAdd(true)
->setAccView(true)
->setAccViewPass(true)
->setAccEdit(true)
->setAccEditPass(true)
->setAccFiles(true)
->setAccDelete(true)
->setAccPermission(true)
->setAccViewHistory(true);
$this->checkForUserByExample(
$this->setUpAccountEnvironment(
self::$faker->numberBetween(1, 4),
self::$faker->randomNumber(),
self::$faker->randomNumber(),
1,
0
),
$this->getExampleAclForAdmin()
);
}
/**
* @param AccountAclDto $accountAclDto The ACL dto to compile the ACL for the user
* @param AccountAcl $example An example ACL to test against the compiled ACL
*
* @throws ConstraintException
* @throws QueryException
*/
private function checkForUserByExample(AccountAclDto $accountAclDto, AccountAcl $example): void
{
foreach (self::ACTIONS as $action) {
$example->setActionId($action);
$aclUnderTest = $this->accountAclService->getAcl($action, $accountAclDto);
$this->assertTrue($aclUnderTest->isCompiledAccountAccess());
$this->assertTrue($aclUnderTest->isCompiledShowAccess());
$this->assertEquals($example->isResultView(), $aclUnderTest->isResultView());
$this->assertEquals($example->isResultEdit(), $aclUnderTest->isResultEdit());
$this->assertEquals($example->isShowPermission(), $aclUnderTest->isShowPermission());
if ($action !== ActionsInterface::ACCOUNT_CREATE
&& $action !== ActionsInterface::ACCOUNT_COPY_PASS
) {
$this->assertEquals($example->checkAccountAccess($action), $aclUnderTest->checkAccountAccess($action));
}
if ($action === ActionsInterface::ACCOUNT_VIEW
|| $action === ActionsInterface::ACCOUNT_HISTORY_VIEW
|| $action === ActionsInterface::ACCOUNT_DELETE
) {
$this->assertEquals($example->isShowDetails(), $aclUnderTest->isShowDetails());
}
if ($action === ActionsInterface::ACCOUNT_CREATE
|| $action === ActionsInterface::ACCOUNT_COPY
) {
$this->assertEquals($example->isShowPass(), $aclUnderTest->isShowPass());
}
if ($action === ActionsInterface::ACCOUNT_EDIT
|| $action === ActionsInterface::ACCOUNT_VIEW
|| $action === ActionsInterface::ACCOUNT_HISTORY_VIEW
) {
$this->assertEquals($example->isShowFiles(), $aclUnderTest->isShowFiles());
}
if ($action === ActionsInterface::ACCOUNT_SEARCH
|| $action === ActionsInterface::ACCOUNT_VIEW
|| $action === ActionsInterface::ACCOUNT_VIEW_PASS
|| $action === ActionsInterface::ACCOUNT_HISTORY_VIEW
|| $action === ActionsInterface::ACCOUNT_EDIT
) {
$this->assertEquals($example->isShowViewPass(), $aclUnderTest->isShowViewPass());
}
if ($action === ActionsInterface::ACCOUNT_EDIT
|| $action === ActionsInterface::ACCOUNT_CREATE
|| $action === ActionsInterface::ACCOUNT_COPY
) {
$this->assertEquals($example->isShowSave(), $aclUnderTest->isShowSave());
}
if ($action === ActionsInterface::ACCOUNT_SEARCH
|| $action === ActionsInterface::ACCOUNT_VIEW
) {
$this->assertEquals($example->isShowEdit(), $aclUnderTest->isShowEdit());
}
if ($action === ActionsInterface::ACCOUNT_EDIT
|| $action === ActionsInterface::ACCOUNT_VIEW
) {
$this->assertEquals($example->isShowEditPass(), $aclUnderTest->isShowEditPass());
}
if ($action === ActionsInterface::ACCOUNT_SEARCH
|| $action === ActionsInterface::ACCOUNT_DELETE
|| $action === ActionsInterface::ACCOUNT_EDIT
) {
$this->assertEquals($example->isShowDelete(), $aclUnderTest->isShowDelete());
}
if ($action === ActionsInterface::ACCOUNT_HISTORY_VIEW) {
$this->assertEquals($example->isShowRestore(), $aclUnderTest->isShowRestore());
}
$this->assertEquals($example->isShowLink(), $aclUnderTest->isShowLink());
if ($action === ActionsInterface::ACCOUNT_VIEW
|| $action === ActionsInterface::ACCOUNT_HISTORY_VIEW
) {
$this->assertEquals($example->isShowHistory(), $aclUnderTest->isShowHistory());
}
if ($action === ActionsInterface::ACCOUNT_SEARCH
|| $action === ActionsInterface::ACCOUNT_VIEW
|| $action === ActionsInterface::ACCOUNT_EDIT
) {
$this->assertEquals($example->isShowCopy(), $aclUnderTest->isShowCopy());
}
}
}
/**
* @param int $accountId
* @param int $userId
* @param int $groupId
*
* @param bool $isAdminApp
* @param bool|int $isAdminAcc
*
* @return AccountAclDto
*/
private function setUpAccountEnvironment(
int $accountId,
int $userId,
int $groupId,
bool $isAdminApp = false,
bool $isAdminAcc = false
): AccountAclDto {
$this->context
->getUserData()
->setId($userId)
->setUserGroupId($groupId)
->setIsAdminApp($isAdminApp)
->setIsAdminAcc($isAdminAcc);
return new AccountAclDto(
$accountId,
self::$accounts[$accountId]['userId'],
self::$accounts[$accountId]['users'],
self::$accounts[$accountId]['userGroupId'],
self::$accounts[$accountId]['groups'],
self::$faker->unixTime
);
}
/**
* @group acl:admin
*
* @return \SP\Domain\Account\Services\AccountAcl
*/
private function getExampleAclForAdmin(): AccountAcl
{
return (new AccountAcl(0))
->setCompiledAccountAccess(true)
->setCompiledShowAccess(true)
->setResultView(true)
->setResultEdit(true)
->setResultView(true)
->setResultEdit(true)
->setShowCopy(true)
->setShowPermission(true)
->setShowLink(true)
->setShowView(true)
->setShowViewPass(true)
->setShowRestore(true)
->setShowHistory(true)
->setShowDelete(true)
->setShowEdit(true)
->setShowEditPass(true)
->setShowFiles(true)
->setShowDetails(true)
->setShowPass(true);
}
/**
* @group acl:admin
*
* @throws \SP\Core\Exceptions\QueryException
* @throws \SP\Core\Exceptions\ConstraintException
*/
public function testGetAclForAdminAcc(): void
{
$this->context
->getUserProfile()
->setAccAdd(true)
->setAccView(true)
->setAccViewPass(true)
->setAccEdit(true)
->setAccEditPass(true)
->setAccFiles(true)
->setAccDelete(true)
->setAccPermission(true)
->setAccViewHistory(true);
$exampleAcl = $this->getExampleAclForAdmin()->setShowLink(false);
$this->checkForUserByExample(
$this->setUpAccountEnvironment(
self::$faker->numberBetween(1, 4),
self::$faker->randomNumber(),
self::$faker->randomNumber(),
0,
1
),
$exampleAcl
);
}
/**
* @group acl:action
* @dataProvider accountPropertiesProvider
*
* @param int $accountId
* @param int $userId
* @param int $groupId
* @param bool $shouldView
* @param bool $shouldEdit
*
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public function testCheckViewPass(
int $accountId,
int $userId,
int $groupId,
bool $shouldView = true,
bool $shouldEdit = true
): void {
$shouldViewOrEdit = $shouldView || $shouldEdit;
$this->context
->getUserProfile()
->setAccViewPass($shouldView);
$example = (new AccountAcl(0))
->setCompiledAccountAccess(true)
->setCompiledShowAccess(true)
->setResultView($shouldViewOrEdit)
->setResultEdit($shouldEdit)
->setShowViewPass($shouldView);
$this->checkForUserByExample($this->setUpAccountEnvironment($accountId, $userId, $groupId), $example);
}
/**
* @group acl:action
* @dataProvider accountPropertiesProvider
*
* @param int $accountId
* @param int $userId
* @param int $groupId
* @param bool $shouldView
* @param bool $shouldEdit
*
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public function testCheckDelete(
int $accountId,
int $userId,
int $groupId,
bool $shouldView = true,
bool $shouldEdit = true
): void {
$shouldViewOrEdit = $shouldView || $shouldEdit;
$this->context
->getUserProfile()
->setAccDelete($shouldView);
$example = (new AccountAcl(0))
->setCompiledAccountAccess(true)
->setCompiledShowAccess(true)
->setResultView($shouldViewOrEdit)
->setResultEdit($shouldEdit)
->setShowDelete($shouldEdit);
$this->checkForUserByExample($this->setUpAccountEnvironment($accountId, $userId, $groupId), $example);
}
/**
* @group acl:action
* @dataProvider accountPropertiesProvider
*
* @param int $accountId
* @param int $userId
* @param int $groupId
* @param bool $shouldView
* @param bool $shouldEdit
*
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public function testEditPass(
int $accountId,
int $userId,
int $groupId,
bool $shouldView = true,
bool $shouldEdit = true
): void {
$shouldViewOrEdit = $shouldView || $shouldEdit;
$this->context
->getUserProfile()
->setAccEditPass($shouldEdit);
$example = (new AccountAcl(0))
->setCompiledAccountAccess(true)
->setCompiledShowAccess(true)
->setResultView($shouldViewOrEdit)
->setResultEdit($shouldEdit)
->setShowEditPass($shouldEdit);
$this->checkForUserByExample($this->setUpAccountEnvironment($accountId, $userId, $groupId), $example);
}
/**
* @group acl:action
* @dataProvider accountPropertiesProvider
*
* @param int $accountId
* @param int $userId
* @param int $groupId
* @param bool $shouldView
* @param bool $shouldEdit
*
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public function testEditAndRestore(
int $accountId,
int $userId,
int $groupId,
bool $shouldView = true,
bool $shouldEdit = true
): void {
$shouldViewOrEdit = $shouldView || $shouldEdit;
$this->context
->getUserProfile()
->setAccEdit($shouldEdit);
$example = (new AccountAcl(0))
->setCompiledAccountAccess(true)
->setCompiledShowAccess(true)
->setResultView($shouldViewOrEdit)
->setResultEdit($shouldEdit)
->setShowEdit($shouldEdit)
->setShowRestore($shouldEdit);
$this->checkForUserByExample($this->setUpAccountEnvironment($accountId, $userId, $groupId), $example);
}
/**
* @group acl:action
* @dataProvider accountPropertiesProvider
*
* @param int $accountId
* @param int $userId
* @param int $groupId
* @param bool $shouldView
* @param bool $shouldEdit
*
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public function testCheckPermission(
int $accountId,
int $userId,
int $groupId,
bool $shouldView = true,
bool $shouldEdit = true
): void {
$shouldViewOrEdit = $shouldView || $shouldEdit;
$this->context
->getUserProfile()
->setAccPermission($shouldEdit);
$example = (new AccountAcl(0))
->setCompiledAccountAccess(true)
->setCompiledShowAccess(true)
->setResultView($shouldViewOrEdit)
->setResultEdit($shouldEdit)
->setShowPermission($shouldEdit);
$this->checkForUserByExample($this->setUpAccountEnvironment($accountId, $userId, $groupId), $example);
}
/**
* @group acl:action
* @dataProvider accountPropertiesProvider
*
* @param int $accountId
* @param int $userId
* @param int $groupId
* @param bool $shouldView
* @param bool $shouldEdit
*
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public function testViewFiles(
int $accountId,
int $userId,
int $groupId,
bool $shouldView = true,
bool $shouldEdit = true
): void {
$shouldViewOrEdit = $shouldView || $shouldEdit;
$this->context
->getUserProfile()
->setAccFiles($shouldEdit);
$example = (new AccountAcl(0))
->setCompiledAccountAccess(true)
->setCompiledShowAccess(true)
->setResultView($shouldViewOrEdit)
->setResultEdit($shouldEdit)
->setShowFiles($shouldView);
$this->checkForUserByExample($this->setUpAccountEnvironment($accountId, $userId, $groupId), $example);
}
/**
* @group acl:action
* @dataProvider accountPropertiesProvider
*
* @param int $accountId
* @param int $userId
* @param int $groupId
* @param bool $shouldView
* @param bool $shouldEdit
*
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public function testCheckView(
int $accountId,
int $userId,
int $groupId,
bool $shouldView = true,
bool $shouldEdit = true
): void {
$shouldViewOrEdit = $shouldView || $shouldEdit;
$this->context
->getUserProfile()
->setAccView($shouldViewOrEdit)
->setAccEdit($shouldEdit);
$example = (new AccountAcl(0))
->setCompiledAccountAccess(true)
->setCompiledShowAccess(true)
->setResultView($shouldViewOrEdit)
->setResultEdit($shouldEdit)
->setShowView($shouldViewOrEdit)
->setShowEdit($shouldEdit)
->setShowRestore($shouldEdit)
->setShowDetails($shouldViewOrEdit)
->setShowPermission(
AccountAclService::getShowPermission($this->context->getUserData(), $this->context->getUserProfile())
);
$this->checkForUserByExample($this->setUpAccountEnvironment($accountId, $userId, $groupId), $example);
}
/**
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public function testCacheIsUsedWithHit(): void
{
$dto = new AccountAclDto(
self::$faker->randomNumber(),
1,
[],
self::$faker->randomNumber(),
[],
self::$faker->unixTime
);
$userToUserGroupService = $this->createMock(UserToUserGroupServiceInterface::class);
$userToUserGroupService->method('getGroupsForUser')->willReturn([]);
$fileCache = $this->createMock(FileCacheInterface::class);
$accountAclService = new AccountAclService(
$this->application,
new Acl($this->context, $this->application->getEventDispatcher()),
$userToUserGroupService,
$fileCache
);
$this->context->getUserData()->setLastUpdate($dto->getDateEdit() + 10);
$acl = new AccountAcl(self::$faker->randomNumber());
$acl->setTime($dto->getDateEdit() + 10);
$fileCache->expects(self::once())
->method('load')
->with(self::callback((static fn($path) => is_string($path))))
->willReturn($acl);
$accountAclService->getAcl(self::$faker->randomNumber(), $dto);
}
/**
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public function testCacheIsUsedWithMiss(): void
{
$dto = new AccountAclDto(
self::$faker->randomNumber(),
1,
[],
self::$faker->randomNumber(),
[],
self::$faker->unixTime
);
$userToUserGroupService = $this->createMock(UserToUserGroupServiceInterface::class);
$userToUserGroupService->method('getGroupsForUser')->willReturn([]);
$fileCache = $this->createMock(FileCacheInterface::class);
$accountAclService = new AccountAclService(
$this->application,
new Acl($this->context, $this->application->getEventDispatcher()),
$userToUserGroupService,
$fileCache
);
$acl = new AccountAcl(self::$faker->randomNumber());
$fileCache->expects(self::once())
->method('load')
->with(self::callback((static fn($path) => is_string($path))))
->willReturn($acl);
$fileCache->expects(self::once())
->method('save')
->with(
self::callback((static fn($acl) => $acl instanceof AccountAcl)),
self::callback((static fn($path) => is_string($path)))
);
$accountAclService->getAcl(self::$faker->randomNumber(), $dto);
}
/**
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public function testCacheLoadThrowsExceptionAndLogged(): void
{
$dto = new AccountAclDto(
self::$faker->randomNumber(),
1,
[],
self::$faker->randomNumber(),
[],
self::$faker->unixTime
);
$userToUserGroupService = $this->createMock(UserToUserGroupServiceInterface::class);
$userToUserGroupService->method('getGroupsForUser')->willReturn([]);
$fileCache = $this->createMock(FileCacheInterface::class);
$accountAclService = new AccountAclService(
$this->application,
new Acl($this->context, $this->application->getEventDispatcher()),
$userToUserGroupService,
$fileCache
);
$fileCache->expects(self::once())
->method('load')
->with(self::callback((static fn($path) => is_string($path))))
->willThrowException(new FileException('test'));
$accountAclService->getAcl(self::$faker->randomNumber(), $dto);
}
/**
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public function testCacheSaveThrowsExceptionAndLogged(): void
{
$dto = new AccountAclDto(
self::$faker->randomNumber(),
1,
[],
self::$faker->randomNumber(),
[],
self::$faker->unixTime
);
$userToUserGroupService = $this->createMock(UserToUserGroupServiceInterface::class);
$userToUserGroupService->method('getGroupsForUser')->willReturn([]);
$fileCache = $this->createMock(FileCacheInterface::class);
$accountAclService = new AccountAclService(
$this->application,
new Acl($this->context, $this->application->getEventDispatcher()),
$userToUserGroupService,
$fileCache
);
$fileCache->expects(self::once())
->method('save')
->with(
self::callback((static fn($acl) => $acl instanceof AccountAcl)),
self::callback((static fn($path) => is_string($path)))
)
->willThrowException(new FileException('test'));
$accountAclService->getAcl(self::$faker->randomNumber(), $dto);
}
protected function setUp(): void
{
parent::setUp();
$acl = new Acl($this->context, $this->application->getEventDispatcher());
$userToUserGroupService = $this->createMock(UserToUserGroupServiceInterface::class);
$userToUserGroupService->method('getGroupsForUser')
->willReturnMap([
[1, [new SimpleModel(['userGroupId' => 2])]],
[2, [new SimpleModel(['userGroupId' => 1])]],
[3, [new SimpleModel(['userGroupId' => 2])]],
[4, []],
]);
$this->accountAclService = new AccountAclService(
$this->application,
$acl,
$userToUserGroupService
);
}
private function accountPropertiesProvider(): array
{
/**
* Account |View |Edit
* 1 |u=3 g=1,2 |u=3 g=1,2
* 2 |g=1,2,3 |g=1,2,3
* 3 |u=3 g=3 |u=3 g=3
* 4 |u=3 |u=3
*
* User | Group
* 1 | 2
* 2 | 1
* 3 | 2
* 4 | None
* Matrix: Account | UserId | GroupId | ShouldView | ShouldEdit
*/
return [
[1, 2, 2, true, true],
[1, 3, 0, true, true],
[1, 3, 1, true, true],
[1, 3, 2, true, true],
[1, 4, 0, false, false],
[1, 4, 3, false, false],
[1, 4, 4, false, false],
[2, 2, 1, true, true],
[2, 2, 2, true, true],
[2, 2, 3, true, true],
[2, 3, 0, false, false],
[2, 3, 3, true, true],
[2, 4, 0, false, false],
[2, 4, 1, true, true],
[2, 4, 2, true, true],
[2, 4, 3, true, true],
[2, 4, 4, false, false],
[3, 1, 1, false, false],
[3, 1, 2, false, false],
[3, 1, 3, true, true],
[3, 2, 1, false, false],
[3, 2, 2, false, false],
[3, 2, 3, true, true],
[3, 3, 0, true, true],
[3, 3, 1, true, true],
[3, 3, 2, true, true],
[3, 3, 3, true, true],
[4, 3, 0, true, true],
[4, 3, 1, true, true],
[4, 3, 2, true, true],
[4, 3, 3, true, true],
];
}
}

View File

@@ -35,6 +35,8 @@ use SP\Infrastructure\Database\DbStorageInterface;
use SP\Infrastructure\File\FileException;
use SP\Tests\Stubs\Pdo;
use SP\Tests\UnitaryTestCase;
use function SP\__;
use function SP\__u;
/**
* Class MySQLTest

View File

@@ -1,809 +0,0 @@
<?php
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, 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\Services\Account;
use Closure;
use DI\DependencyException;
use DI\NotFoundException;
use SP\Core\Acl\Acl;
use SP\Core\Acl\ActionsInterface;
use SP\Core\Application;
use SP\Core\Context\ContextException;
use SP\Core\Context\ContextInterface;
use SP\Core\Context\StatelessContext;
use SP\Core\Exceptions\ConstraintException;
use SP\Core\Exceptions\QueryException;
use SP\DataModel\Dto\AccountAclDto;
use SP\DataModel\Dto\AccountDetailsResponse;
use SP\Domain\Account\AccountAclServiceInterface;
use SP\Domain\Account\Services\AccountAcl;
use SP\Domain\Account\Services\AccountAclService;
use SP\Domain\Account\Services\AccountService;
use SP\Domain\User\Services\UserLoginResponse;
use SP\Infrastructure\Common\Repositories\NoSuchItemException;
use SP\Tests\DatabaseTestCase;
use function SP\Tests\setupContext;
/**
* Class AccountAclServiceTest
*
* @package SP\Tests\Services
*/
class AccountAclServiceTest extends DatabaseTestCase
{
private static Closure $service;
private static AccountService $accountService;
private static StatelessContext $context;
private static array $actions = [
ActionsInterface::ACCOUNT_SEARCH,
ActionsInterface::ACCOUNT_VIEW,
ActionsInterface::ACCOUNT_VIEW_PASS,
ActionsInterface::ACCOUNT_HISTORY_VIEW,
ActionsInterface::ACCOUNT_CREATE,
ActionsInterface::ACCOUNT_EDIT,
ActionsInterface::ACCOUNT_EDIT_PASS,
ActionsInterface::ACCOUNT_EDIT_RESTORE,
ActionsInterface::ACCOUNT_COPY,
ActionsInterface::ACCOUNT_COPY_PASS,
ActionsInterface::ACCOUNT_DELETE,
];
protected AccountDetailsResponse $account;
/**
* @throws NotFoundException
* @throws ContextException
* @throws DependencyException
*/
public static function setUpBeforeClass(): void
{
$dic = setupContext();
self::$loadFixtures = true;
self::$context = $dic->get(ContextInterface::class);
// Es necesario utilizar una función anónima para evitar la fijación
// de los datos del contexto
self::$service = static function () use ($dic) {
return new AccountAclService($dic, $dic->get(Application::class));
};
self::$accountService = $dic->get(AccountService::class);
}
/**
* testSaveAclInCache
*/
public function testSaveAclInCache()
{
/** @var AccountAclServiceInterface $service */
$service = self::$service->call($this);
$accountAcl = new AccountAcl(10);
$accountAcl->setAccountId(1);
$accountAcl->setCompiledAccountAccess(true);
$accountAcl->setCompiledShowAccess(true);
$accountAcl->setResultView(true);
$accountAcl->setResultEdit(true);
$accountAcl->setShowCopy(true);
$accountAcl->setShowPermission(true);
$accountAcl->setShowLink(false);
$accountAcl->setShowView(true);
$accountAcl->setShowViewPass(true);
$accountAcl->setShowRestore(true);
$accountAcl->setShowHistory(true);
$accountAcl->setShowDelete(true);
$accountAcl->setShowEdit(true);
$accountAcl->setShowEditPass(true);
$accountAcl->setShowFiles(true);
$accountAcl->setShowDetails(true);
$accountAcl->setShowPass(true);
$service->saveAclInCache($accountAcl);
$result = $service->getAclFromCache(1, 10);
$this->assertInstanceOf(AccountAcl::class, $result);
$this->assertEquals($accountAcl, $result);
$accountAcl->reset();
$this->assertNotEquals($accountAcl, $result);
}
/**
* testClearAcl
*/
public function testClearAcl()
{
/** @var \SP\Domain\Account\AccountAclServiceInterface $service */
$service = self::$service->call($this);
$accountAcl = new AccountAcl(10);
$accountAcl->setAccountId(1);
$service->saveAclInCache($accountAcl);
$this->assertTrue(AccountAclService::clearAcl(1));
$this->assertFalse(AccountAclService::clearAcl(2));
}
/**
* @throws ConstraintException
* @throws QueryException
* @throws NoSuchItemException
*/
public function testGetAclAdmin()
{
$this->checkAllowAll($this->setUpAccountEnvironment(1, 1, 1, 1));
$this->checkAllowAll($this->setUpAccountEnvironment(2, 1, 1, 1));
$accountAcl = new AccountAcl(0);
$accountAcl->setCompiledAccountAccess(true);
$accountAcl->setCompiledShowAccess(true);
$accountAcl->setResultView(true);
$accountAcl->setResultEdit(true);
$accountAcl->setShowCopy(true);
$accountAcl->setShowPermission(true);
$accountAcl->setShowLink(false);
$accountAcl->setShowView(true);
$accountAcl->setShowViewPass(true);
$accountAcl->setShowRestore(true);
$accountAcl->setShowHistory(true);
$accountAcl->setShowDelete(true);
$accountAcl->setShowEdit(true);
$accountAcl->setShowEditPass(true);
$accountAcl->setShowFiles(true);
$accountAcl->setShowDetails(true);
$accountAcl->setShowPass(true);
$this->checkForUserByExample($this->setUpAccountEnvironment(1, 1, 1, 0, 1), $accountAcl);
$this->checkForUserByExample($this->setUpAccountEnvironment(2, 1, 1, 0, 1), $accountAcl);
}
/**
* @param AccountAclDto $accountAclDto
*
* @param bool $should
*
* @throws ConstraintException
* @throws QueryException
*/
private function checkAllowAll(AccountAclDto $accountAclDto, $should = true)
{
self::$context
->getUserProfile()
->reset()
->setAccAdd($should)
->setAccView($should)
->setAccViewPass($should)
->setAccEdit($should)
->setAccEditPass($should)
->setAccFiles($should)
->setAccDelete($should)
->setAccPermission($should)
->setAccViewHistory($should);
$accountAcl = (new AccountAcl(0))
->setCompiledAccountAccess(true)
->setCompiledShowAccess(true)
->setResultView($should)
->setResultEdit($should)
->setResultView(true)
->setResultEdit(true)
->setShowCopy(true)
->setShowPermission(true)
->setShowLink(true)
->setShowView(true)
->setShowViewPass(true)
->setShowRestore(true)
->setShowHistory(true)
->setShowDelete(true)
->setShowEdit(true)
->setShowEditPass(true)
->setShowFiles(true)
->setShowDetails(true)
->setShowPass(true);
$this->checkForUserByExample($accountAclDto, $accountAcl);
}
/**
* @param AccountAclDto $accountAclDto
*
* @param AccountAcl $accountAclExample
*
* @throws ConstraintException
* @throws QueryException
*/
private function checkForUserByExample(AccountAclDto $accountAclDto, AccountAcl $accountAclExample)
{
/** @var AccountAclServiceInterface $service */
$service = self::$service->call($this);
foreach (self::$actions as $action) {
$accountAclExample->setActionId($action);
$accountAcl = $service->getAcl($action, $accountAclDto);
$this->assertInstanceOf(AccountAcl::class, $accountAcl);
$this->assertTrue($accountAcl->isCompiledAccountAccess());
$this->assertTrue($accountAcl->isCompiledShowAccess());
$this->assertEquals($accountAclExample->isResultView(), $accountAcl->isResultView());
$this->assertEquals($accountAclExample->isResultEdit(), $accountAcl->isResultEdit());
if ($action !== Acl::ACCOUNT_CREATE
&& $action !== Acl::ACCOUNT_COPY_PASS
) {
$this->assertEquals(
$accountAclExample->checkAccountAccess($action),
$accountAcl->checkAccountAccess($action)
);
}
if ($action === Acl::ACCOUNT_VIEW
|| $action === Acl::ACCOUNT_HISTORY_VIEW
|| $action === Acl::ACCOUNT_DELETE
) {
$this->assertEquals($accountAclExample->isShowDetails(), $accountAcl->isShowDetails());
}
if ($action === Acl::ACCOUNT_CREATE
|| $action === Acl::ACCOUNT_COPY
) {
$this->assertEquals($accountAclExample->isShowPass(), $accountAcl->isShowPass());
}
if ($action === Acl::ACCOUNT_EDIT
|| $action === Acl::ACCOUNT_VIEW
|| $action === Acl::ACCOUNT_HISTORY_VIEW
) {
$this->assertEquals($accountAclExample->isShowFiles(), $accountAcl->isShowFiles());
}
if ($action === Acl::ACCOUNT_SEARCH
|| $action === Acl::ACCOUNT_VIEW
|| $action === Acl::ACCOUNT_VIEW_PASS
|| $action === Acl::ACCOUNT_HISTORY_VIEW
|| $action === Acl::ACCOUNT_EDIT
) {
$this->assertEquals($accountAclExample->isShowViewPass(), $accountAcl->isShowViewPass());
}
if ($action === Acl::ACCOUNT_EDIT
|| $action === Acl::ACCOUNT_CREATE
|| $action === Acl::ACCOUNT_COPY
) {
$this->assertEquals($accountAclExample->isShowSave(), $accountAcl->isShowSave());
}
if ($action === Acl::ACCOUNT_SEARCH
|| $action === Acl::ACCOUNT_VIEW
) {
$this->assertEquals($accountAclExample->isShowEdit(), $accountAcl->isShowEdit());
}
if ($action === Acl::ACCOUNT_EDIT
|| $action === Acl::ACCOUNT_VIEW
) {
$this->assertEquals($accountAclExample->isShowEditPass(), $accountAcl->isShowEditPass());
}
if ($action === Acl::ACCOUNT_SEARCH
|| $action === Acl::ACCOUNT_DELETE
|| $action === Acl::ACCOUNT_EDIT
) {
$this->assertEquals($accountAclExample->isShowDelete(), $accountAcl->isShowDelete());
}
if ($action === Acl::ACCOUNT_HISTORY_VIEW) {
$this->assertEquals($accountAclExample->isShowRestore(), $accountAcl->isShowRestore());
}
$this->assertEquals($accountAclExample->isShowLink(), $accountAcl->isShowLink());
if ($action === Acl::ACCOUNT_VIEW
|| $action === Acl::ACCOUNT_HISTORY_VIEW
) {
$this->assertEquals($accountAclExample->isShowHistory(), $accountAcl->isShowHistory());
}
if ($action === Acl::ACCOUNT_SEARCH
|| $action === Acl::ACCOUNT_VIEW
|| $action === Acl::ACCOUNT_EDIT
) {
$this->assertEquals($accountAclExample->isShowCopy(), $accountAcl->isShowCopy());
}
}
}
/**
* @param $accountId
* @param $userId
* @param $groupId
*
* @param int $isAdminApp
* @param int $isAdminAcc
*
* @return AccountAclDto
* @throws ConstraintException
* @throws QueryException
* @throws NoSuchItemException
*/
private function setUpAccountEnvironment($accountId, $userId, $groupId, $isAdminApp = false, $isAdminAcc = false)
{
AccountAclService::$useCache = false;
if ($this->account === null || $this->account->getId() !== $accountId) {
$this->account = self::$accountService->getById($accountId);
self::$accountService->withUsersById($this->account);
self::$accountService->withUserGroupsById($this->account);
}
$userData = new UserLoginResponse();
$userData->setId($userId);
$userData->setIsAdminApp($isAdminApp);
$userData->setIsAdminAcc($isAdminAcc);
$userData->setUserGroupId($groupId);
self::$context->setUserData($userData);
return AccountAclDto::makeFromAccount($this->account);
}
/**
* @throws ConstraintException
* @throws QueryException
* @throws NoSuchItemException
*/
public function testGetAclUser()
{
$accountAclDto = $this->setUpAccountEnvironment(1, 2, 2);
$this->checkView($accountAclDto);
$this->checkViewPass($accountAclDto);
$this->checkDelete($accountAclDto);
$this->checkEditPass($accountAclDto);
$this->checkEditAndRestore($accountAclDto);
$this->checkPermissions($accountAclDto);
$this->checkViewFiles($accountAclDto);
$accountAclDto = $this->setUpAccountEnvironment(1, 3, 3);
$this->checkView($accountAclDto);
$this->checkViewPass($accountAclDto);
$this->checkDelete($accountAclDto);
$this->checkEditPass($accountAclDto);
$this->checkEditAndRestore($accountAclDto);
$this->checkPermissions($accountAclDto);
$this->checkViewFiles($accountAclDto);
$accountAclDto = $this->setUpAccountEnvironment(1, 4, 3);
$should = ['view' => false, 'edit' => false];
$this->checkView($accountAclDto, $should);
$this->checkViewPass($accountAclDto, $should);
$this->checkDelete($accountAclDto, $should);
$this->checkEditPass($accountAclDto, $should);
$this->checkEditAndRestore($accountAclDto, $should);
$this->checkPermissions($accountAclDto, $should);
$this->checkViewFiles($accountAclDto, $should);
$accountAclDto = $this->setUpAccountEnvironment(2, 1, 1);
$this->checkView($accountAclDto);
$this->checkViewPass($accountAclDto);
$this->checkDelete($accountAclDto);
$this->checkEditPass($accountAclDto);
$this->checkEditAndRestore($accountAclDto);
$this->checkPermissions($accountAclDto);
$this->checkViewFiles($accountAclDto);
$accountAclDto = $this->setUpAccountEnvironment(2, 2, 2);
$should = ['view' => true, 'edit' => false];
$this->checkView($accountAclDto, $should);
$this->checkViewPass($accountAclDto, $should);
$this->checkDelete($accountAclDto, $should);
$this->checkEditPass($accountAclDto, $should);
$this->checkEditAndRestore($accountAclDto, $should);
$this->checkPermissions($accountAclDto, $should);
$this->checkViewFiles($accountAclDto, $should);
$accountAclDto = $this->setUpAccountEnvironment(2, 3, 3);
$should = ['view' => true, 'edit' => false];
$this->checkView($accountAclDto, $should);
$this->checkViewPass($accountAclDto, $should);
$this->checkDelete($accountAclDto, $should, true, false);
$this->checkEditPass($accountAclDto, $should, true, false);
$this->checkEditAndRestore($accountAclDto, $should, true, false);
$this->checkPermissions($accountAclDto, $should);
$this->checkViewFiles($accountAclDto, $should);
$accountAclDto = $this->setUpAccountEnvironment(2, 4, 3);
$should = ['view' => true, 'edit' => false];
$this->checkView($accountAclDto, $should);
$this->checkViewPass($accountAclDto, $should);
$this->checkDelete($accountAclDto, $should, true, false);
$this->checkEditPass($accountAclDto, $should, true, false);
$this->checkEditAndRestore($accountAclDto, $should, true, false);
$this->checkPermissions($accountAclDto, $should);
$this->checkViewFiles($accountAclDto, $should);
$accountAclDto = $this->setUpAccountEnvironment(2, 5, 4);
$should = ['view' => false, 'edit' => false];
$this->checkView($accountAclDto, $should);
$this->checkViewPass($accountAclDto, $should);
$this->checkDelete($accountAclDto, $should);
$this->checkEditPass($accountAclDto, $should);
$this->checkEditAndRestore($accountAclDto, $should);
$this->checkPermissions($accountAclDto, $should);
$this->checkViewFiles($accountAclDto, $should);
$accountAclDto = $this->setUpAccountEnvironment(2, 1, 1);
$this->checkView($accountAclDto);
$this->checkViewPass($accountAclDto);
$this->checkDelete($accountAclDto);
$this->checkEditPass($accountAclDto);
$this->checkEditAndRestore($accountAclDto);
$this->checkPermissions($accountAclDto);
$this->checkViewFiles($accountAclDto);
}
/**
* @param AccountAclDto $accountAclDto
*
* @param array $should Sets view and edit status
* @param bool $profile Sets profile action status
* @param bool $acl Sets ACL expected result
*
* @throws ConstraintException
* @throws QueryException
*/
private function checkView(
AccountAclDto $accountAclDto,
$should = ['view' => true, 'edit' => true],
$profile = true,
$acl = true
) {
$userProfile = self::$context
->getUserProfile()
->reset()
->setAccView($profile);
$accountAcl = (new AccountAcl(0))
->setCompiledAccountAccess(true)
->setCompiledShowAccess(true)
->setResultView($should['view'])
->setResultEdit($should['edit'])
->setShowDetails($acl);
$this->checkForUserByExample($accountAclDto, $accountAcl);
// Checks if ACL returns false when profile action is granted and account access is denied
if ($should['view'] === false && $should['edit'] === false) {
$userProfile->setAccView(true);
$accountAcl->setShowDetails(false);
$this->checkForUserByExample($accountAclDto, $accountAcl);
} elseif ($profile === true) { // Checks ACL when profile action is denied
$userProfile->setAccView(false);
$accountAcl->setShowDetails(false);
$this->checkForUserByExample($accountAclDto, $accountAcl);
}
}
/**
* @param AccountAclDto $accountAclDto
*
* @param array $should
*
* @param bool $profile
* @param bool $acl
*
* @throws ConstraintException
* @throws QueryException
*/
private function checkViewPass(
AccountAclDto $accountAclDto,
$should = ['view' => true, 'edit' => true],
$profile = true,
$acl = true
) {
$userProfile = self::$context
->getUserProfile()
->reset()
->setAccViewPass($profile);
$accountAcl = (new AccountAcl(0))
->setCompiledAccountAccess(true)
->setCompiledShowAccess(true)
->setResultView($should['view'])
->setResultEdit($should['edit'])
->setShowViewPass($acl);
$this->checkForUserByExample($accountAclDto, $accountAcl);
// Checks if ACL returns false when profile action is granted and account access is denied
if ($should['view'] === false && $should['edit'] === false) {
$userProfile->setAccViewPass(true);
$accountAcl->setShowViewPass(false);
$this->checkForUserByExample($accountAclDto, $accountAcl);
} elseif ($profile === true && $acl === true) { // Checks ACL when profile action is denied
$userProfile->setAccViewPass(false);
$accountAcl->setShowViewPass(false);
$this->checkForUserByExample($accountAclDto, $accountAcl);
}
}
/**
* @param AccountAclDto $accountAclDto
*
* @param array $should
*
* @param bool $profile
* @param bool $acl
*
* @throws ConstraintException
* @throws QueryException
*/
private function checkDelete(
AccountAclDto $accountAclDto,
$should = ['view' => true, 'edit' => true],
$profile = true,
$acl = true
) {
$userProfile = self::$context
->getUserProfile()
->reset()
->setAccDelete($profile);
$accountAcl = (new AccountAcl(0))
->setCompiledAccountAccess(true)
->setCompiledShowAccess(true)
->setResultView($should['view'])
->setResultEdit($should['edit'])
->setShowDelete($acl);
$this->checkForUserByExample($accountAclDto, $accountAcl);
// Checks if ACL returns false when profile action is granted and account access is denied
if ($should['view'] === false && $should['edit'] === false) {
$userProfile->setAccDelete(true);
$accountAcl->setShowDelete(false);
$this->checkForUserByExample($accountAclDto, $accountAcl);
} elseif ($profile === true) { // Checks ACL when profile action is denied
$userProfile->setAccDelete(false);
$accountAcl->setShowDelete(false);
$this->checkForUserByExample($accountAclDto, $accountAcl);
}
}
/**
* @param AccountAclDto $accountAclDto
*
* @param array $should
*
* @param bool $profile
* @param bool $acl
*
* @throws ConstraintException
* @throws QueryException
*/
private function checkEditPass(
AccountAclDto $accountAclDto,
$should = ['view' => true, 'edit' => true],
$profile = true,
$acl = true
) {
$userProfile = self::$context
->getUserProfile()
->reset()
->setAccEditPass($profile);
$accountAcl = (new AccountAcl(0))
->setCompiledAccountAccess(true)
->setCompiledShowAccess(true)
->setResultView($should['view'])
->setResultEdit($should['edit'])
->setShowEditPass($acl);
$this->checkForUserByExample($accountAclDto, $accountAcl);
// Checks if ACL returns false when profile action is granted and account access is denied
if ($should['view'] === false && $should['edit'] === false) {
$userProfile->setAccEditPass(true);
$accountAcl->setShowEditPass(false);
$this->checkForUserByExample($accountAclDto, $accountAcl);
} elseif ($profile === true) { // Checks ACL when profile action is denied
$userProfile->setAccEditPass(false);
$accountAcl->setShowEditPass(false);
$this->checkForUserByExample($accountAclDto, $accountAcl);
}
}
/**
* @param AccountAclDto $accountAclDto
*
* @param array $should
*
* @param bool $profile
* @param bool $acl
*
* @throws ConstraintException
* @throws QueryException
*/
private function checkEditAndRestore(
AccountAclDto $accountAclDto,
$should = ['view' => true, 'edit' => true],
$profile = true,
$acl = true
) {
$userProfile = self::$context
->getUserProfile()
->reset()
->setAccEdit($profile);
$accountAcl = (new AccountAcl(0))
->setCompiledAccountAccess(true)
->setCompiledShowAccess(true)
->setResultView($should['view'])
->setResultEdit($should['edit'])
->setShowEdit($acl)
->setShowRestore($acl);
$this->checkForUserByExample($accountAclDto, $accountAcl);
// Checks if ACL returns false when profile action is granted and account access is denied
if ($should['view'] === false && $should['edit'] === false) {
$userProfile->setAccEdit(true);
$accountAcl->setShowEdit(false)
->setShowRestore(false);
$this->checkForUserByExample($accountAclDto, $accountAcl);
} elseif ($profile === true) { // Checks ACL when profile action is denied
$userProfile->setAccEdit(false);
$accountAcl->setShowEdit(false)
->setShowRestore(false);
$this->checkForUserByExample($accountAclDto, $accountAcl);
}
}
/**
* @param AccountAclDto $accountAclDto
*
* @param array $should
*
* @param bool $profile
* @param bool $acl
*
* @throws ConstraintException
* @throws QueryException
*/
private function checkPermissions(
AccountAclDto $accountAclDto,
$should = ['view' => true, 'edit' => true],
$profile = true,
$acl = true
) {
$userProfile = self::$context
->getUserProfile()
->reset()
->setAccPermission($profile);
$accountAcl = (new AccountAcl(0))
->setCompiledAccountAccess(true)
->setCompiledShowAccess(true)
->setResultView($should['view'])
->setResultEdit($should['edit'])
->setShowPermission($acl);
$this->checkForUserByExample($accountAclDto, $accountAcl);
// Checks if ACL returns false when profile action is granted and account access is denied
if ($should['view'] === false && $should['edit'] === false) {
$userProfile->setAccPermission(true);
$accountAcl->setShowPermission(false);
$this->checkForUserByExample($accountAclDto, $accountAcl);
} elseif ($profile === true) { // Checks ACL when profile action is denied
$userProfile->setAccPermission(false);
$accountAcl->setShowPermission(false);
$this->checkForUserByExample($accountAclDto, $accountAcl);
}
}
/**
* @param AccountAclDto $accountAclDto
*
* @param array $should
*
* @param bool $profile
* @param bool $acl
*
* @throws ConstraintException
* @throws QueryException
*/
private function checkViewFiles(
AccountAclDto $accountAclDto,
$should = ['view' => true, 'edit' => true],
$profile = true,
$acl = true
) {
$userProfile = self::$context
->getUserProfile()
->reset()
->setAccFiles($profile);
$accountAcl = (new AccountAcl(0))
->setCompiledAccountAccess(true)
->setCompiledShowAccess(true)
->setResultView($should['view'])
->setResultEdit($should['edit'])
->setShowFiles($acl);
$this->checkForUserByExample($accountAclDto, $accountAcl);
// Checks if ACL returns false when profile action is granted and account access is denied
if ($should['view'] === false && $should['edit'] === false) {
$userProfile->setAccFiles(true);
$accountAcl->setShowFiles(false);
$this->checkForUserByExample($accountAclDto, $accountAcl);
} elseif ($profile === true) { // Checks ACL when profile action is denied
$userProfile->setAccFiles(false);
$accountAcl->setShowFiles(false);
$this->checkForUserByExample($accountAclDto, $accountAcl);
}
}
/**
* testGetAclFromCache
*/
public function testGetAclFromCache()
{
/** @var AccountAclServiceInterface $service */
$service = self::$service->call($this);
$this->assertNull($service->getAclFromCache(1, 10));
}
}

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-2022, 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\Services\Account;
@@ -32,6 +32,7 @@ use SP\Core\Crypt\Crypt;
use SP\Core\Exceptions\ConstraintException;
use SP\Core\Exceptions\QueryException;
use SP\Domain\Account\AccountCryptServiceInterface;
use SP\Domain\Account\AccountServiceInterface;
use SP\Domain\Account\Services\AccountCryptService;
use SP\Domain\Account\Services\AccountService;
use SP\Domain\Common\Services\ServiceException;
@@ -51,7 +52,7 @@ class AccountCryptServiceTest extends DatabaseTestCase
const NEW_MASTERPASS = '00123456789';
const CURRENT_HASH = '$2y$10$xtsuN2PUvgSH/0mrfBlsbOActVgCjYcqDqC6L3T9QraNxZC4RXGYa';
/**
* @var AccountService
* @var \SP\Domain\Account\AccountServiceInterface
*/
private static $accountService;
/**

View File

@@ -40,8 +40,9 @@ use SP\DataModel\AccountVData;
use SP\DataModel\ItemSearchData;
use SP\DataModel\ProfileData;
use SP\Domain\Account\AccountHistoryServiceInterface;
use SP\Domain\Account\Search\AccountSearchFilter;
use SP\Domain\Account\AccountServiceInterface;
use SP\Domain\Account\Out\AccountData;
use SP\Domain\Account\Search\AccountSearchFilter;
use SP\Domain\Account\Services\AccountBulkRequest;
use SP\Domain\Account\Services\AccountHistoryService;
use SP\Domain\Account\Services\AccountPasswordRequest;
@@ -72,7 +73,7 @@ class AccountServiceTest extends DatabaseTestCase
*/
private static $context;
/**
* @var AccountService
* @var \SP\Domain\Account\AccountServiceInterface
*/
private static $service;

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-2022, 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\Services\Crypt;
@@ -32,6 +32,7 @@ use SP\Core\Context\ContextException;
use SP\Core\Crypt\Crypt;
use SP\Core\Exceptions\ConstraintException;
use SP\Core\Exceptions\QueryException;
use SP\Domain\Account\AccountServiceInterface;
use SP\Domain\Account\Services\AccountService;
use SP\Domain\Crypt\Services\MasterPassService;
use SP\Domain\Crypt\Services\UpdateMasterPassRequest;
@@ -53,7 +54,7 @@ class MasterPassServiceTest extends DatabaseTestCase
*/
private static $customFieldService;
/**
* @var AccountService
* @var \SP\Domain\Account\AccountServiceInterface
*/
private static $accountService;
/**

View File

@@ -32,6 +32,7 @@ use SP\Core\Application;
use SP\Core\Context\ContextInterface;
use SP\Core\Context\StatelessContext;
use SP\Core\Events\EventDispatcher;
use SP\DataModel\ProfileData;
use SP\Domain\Config\ConfigInterface;
use SP\Domain\Config\Services\ConfigBackupService;
use SP\Domain\Config\Services\ConfigFileService;
@@ -61,6 +62,11 @@ abstract class UnitaryTestCase extends TestCase
parent::setUpBeforeClass();
}
public static function getRandomNumbers(int $count): array
{
return array_map(static fn() => self::$faker->randomNumber(), range(0, $count - 1));
}
/**
* @throws \SP\Core\Exceptions\ConfigException
* @throws \SP\Core\Context\ContextException
@@ -89,6 +95,7 @@ abstract class UnitaryTestCase extends TestCase
$this->context = new StatelessContext();
$this->context->initialize();
$this->context->setUserData($userLogin);
$this->context->setUserProfile(new ProfileData());
$config = new ConfigFileService(
$this->createStub(XmlHandler::class),
@@ -99,9 +106,4 @@ abstract class UnitaryTestCase extends TestCase
return new Application($config, $this->createStub(EventDispatcher::class), $this->context);
}
public static function getRandomNumbers(int $count): array
{
return array_map(static fn() => self::$faker->randomNumber(), range(0, $count - 1));
}
}
}

View File

@@ -49,30 +49,30 @@ const APP_DEFINITIONS_FILE = APP_ROOT.DIRECTORY_SEPARATOR.'lib'.DIRECTORY_SEPARA
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('LOCALES_PATH', APP_ROOT . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'locales');
define('MODULES_PATH', APP_ROOT . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'modules');
define('SQL_PATH', APP_ROOT . DIRECTORY_SEPARATOR . 'schemas');
define('CACHE_PATH', RESOURCE_PATH . DIRECTORY_SEPARATOR . 'cache');
define('TMP_PATH', TEST_ROOT . DIRECTORY_SEPARATOR . 'tmp');
define('CONFIG_FILE', CONFIG_PATH.DIRECTORY_SEPARATOR.'config.xml');
define('ACTIONS_FILE', CONFIG_PATH.DIRECTORY_SEPARATOR.'actions.xml');
define('LOCALES_PATH', APP_ROOT.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'locales');
define('MODULES_PATH', APP_ROOT.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'modules');
define('SQL_PATH', APP_ROOT.DIRECTORY_SEPARATOR.'schemas');
define('CACHE_PATH', RESOURCE_PATH.DIRECTORY_SEPARATOR.'cache');
define('TMP_PATH', TEST_ROOT.DIRECTORY_SEPARATOR.'tmp');
define('BACKUP_PATH', TMP_PATH);
define('PLUGINS_PATH', TMP_PATH);
define('XML_SCHEMA', APP_ROOT . DIRECTORY_SEPARATOR . 'schemas' . DIRECTORY_SEPARATOR . 'syspass.xsd');
define('LOG_FILE', TMP_PATH . DIRECTORY_SEPARATOR . 'test.log');
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_PATH . DIRECTORY_SEPARATOR . 'datasets' . DIRECTORY_SEPARATOR . 'truncate.sql',
RESOURCE_PATH . 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));
require_once APP_ROOT . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
require_once APP_ROOT . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'BaseFunctions.php';
require_once APP_ROOT.DIRECTORY_SEPARATOR.'vendor'.DIRECTORY_SEPARATOR.'autoload.php';
require_once APP_ROOT.DIRECTORY_SEPARATOR.'lib'.DIRECTORY_SEPARATOR.'BaseFunctions.php';
logger('APP_ROOT=' . APP_ROOT);
logger('TEST_ROOT=' . TEST_ROOT);
logger('SELF_IP_ADDRESS=' . SELF_IP_ADDRESS);
logger('APP_ROOT='.APP_ROOT);
logger('TEST_ROOT='.TEST_ROOT);
logger('SELF_IP_ADDRESS='.SELF_IP_ADDRESS);
// Setup directories
try {
@@ -85,7 +85,7 @@ try {
if (is_dir(CONFIG_PATH)
&& decoct(fileperms(CONFIG_PATH) & 0777) !== '750'
) {
print 'Setting permissions for ' . CONFIG_PATH . PHP_EOL;
print 'Setting permissions for '.CONFIG_PATH.PHP_EOL;
chmod(CONFIG_PATH, 0750);
}
@@ -156,7 +156,7 @@ function getDbHandler(?DatabaseConnectionData $connectionData = null): MysqlHand
function getResource(string $dir, string $file): string
{
return file_get_contents(RESOURCE_PATH . DIRECTORY_SEPARATOR . $dir . DIRECTORY_SEPARATOR . $file) ?: '';
return file_get_contents(RESOURCE_PATH.DIRECTORY_SEPARATOR.$dir.DIRECTORY_SEPARATOR.$file) ?: '';
}
function saveResource(string $dir, string $file, string $data): bool|int
@@ -172,12 +172,12 @@ function recreateDir(string $dir): void
if (is_dir($dir)) {
logger('Deleting '.$dir);
FileUtil::rmdir_recursive($dir);
FileUtil::rmdirRecursive($dir);
}
logger('Creating '.$dir.PHP_EOL);
logger('Creating '.$dir);
if (!mkdir($dir) && !is_dir($dir)) {
throw new RuntimeException(sprintf('Directory "%s" was not created', $dir));
}
}
}