chore: Create AccountAdapter tests

Signed-off-by: Rubén D <nuxsmin@syspass.org>
This commit is contained in:
Rubén D
2022-11-26 13:04:38 +01:00
parent f9d16dd76f
commit 07437ffda0
25 changed files with 535 additions and 222 deletions

View File

@@ -30,7 +30,7 @@ use League\Fractal\Resource\Item;
use SP\Core\Acl\ActionsInterface;
use SP\Core\Events\Event;
use SP\Core\Events\EventMessage;
use SP\DataModel\Dto\AccountDetailsResponse;
use SP\DataModel\Dto\AccountEnrichedDto;
use SP\Domain\Api\Services\ApiResponse;
use SP\Util\Util;
@@ -59,7 +59,7 @@ final class ViewController extends AccountBase
$this->accountService->incrementViewCounter($id);
$accountResponse = new AccountDetailsResponse($id, $accountDetails);
$accountResponse = new AccountEnrichedDto($accountDetails);
$this->accountService
->withUsersById($accountResponse)
@@ -91,4 +91,4 @@ final class ViewController extends AccountBase
processException($e);
}
}
}
}

View File

@@ -33,7 +33,7 @@ use SP\Core\Exceptions\ConstraintException;
use SP\Core\Exceptions\QueryException;
use SP\Core\Exceptions\SPException;
use SP\DataModel\Dto\AccountAclDto;
use SP\DataModel\Dto\AccountDetailsResponse;
use SP\DataModel\Dto\AccountEnrichedDto;
use SP\DataModel\ItemPreset\AccountPermission;
use SP\DataModel\ItemPreset\AccountPrivate;
use SP\DataModel\ProfileData;
@@ -125,7 +125,7 @@ final class AccountHelper extends AccountHelperBase
/**
* Sets account's view variables
*
* @param AccountDetailsResponse $accountDetailsResponse
* @param AccountEnrichedDto $accountDetailsResponse
* @param int $actionId
*
* @throws \SP\Core\Acl\AccountPermissionException
@@ -138,7 +138,7 @@ final class AccountHelper extends AccountHelperBase
* @throws \SP\Infrastructure\Common\Repositories\NoSuchItemException
*/
public function setViewForAccount(
AccountDetailsResponse $accountDetailsResponse,
AccountEnrichedDto $accountDetailsResponse,
int $actionId
): void {
$this->accountId = $accountDetailsResponse->getAccountVData()->getId();
@@ -288,14 +288,14 @@ final class AccountHelper extends AccountHelperBase
/**
* Comprobar si el usuario dispone de acceso al módulo
*
* @param AccountDetailsResponse $accountDetailsResponse
* @param AccountEnrichedDto $accountDetailsResponse
*
* @return AccountAcl
* @throws AccountPermissionException
* @throws ConstraintException
* @throws QueryException
*/
protected function checkAccess(AccountDetailsResponse $accountDetailsResponse): AccountAcl
protected function checkAccess(AccountEnrichedDto $accountDetailsResponse): AccountAcl
{
$accountAcl = $this->accountAclService->getAcl(
$this->actionId,
@@ -459,4 +459,4 @@ final class AccountHelper extends AccountHelperBase
$this->setViewCommon();
}
}
}

View File

@@ -25,7 +25,7 @@
namespace SP\Modules\Web\Controllers\Helpers\Account;
use SP\DataModel\Dto\AccountDetailsResponse;
use SP\DataModel\Dto\AccountEnrichedDto;
use SP\Domain\Account\Services\AccountAcl;
/**
@@ -36,7 +36,7 @@ final class AccountRequestHelper extends AccountHelperBase
/**
* Sets account's view variables
*
* @param AccountDetailsResponse $accountDetailsResponse
* @param AccountEnrichedDto $accountDetailsResponse
* @param int $actionId
*
* @return bool
@@ -46,7 +46,7 @@ final class AccountRequestHelper extends AccountHelperBase
* @throws \SP\Domain\User\Services\UpdatedMasterPassException
*/
public function setViewForRequest(
AccountDetailsResponse $accountDetailsResponse,
AccountEnrichedDto $accountDetailsResponse,
int $actionId
): bool {
$this->accountId = $accountDetailsResponse->getAccountVData()->getId();
@@ -73,4 +73,4 @@ final class AccountRequestHelper extends AccountHelperBase
return true;
}
}
}

View File

@@ -51,8 +51,8 @@
"ext-zlib": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"league/fractal": "^0.19.2",
"symfony/console": "^v5.1.2",
"league/fractal": "^0.20",
"symfony/console": "^v5.1",
"symfony/lock": "^v5.0",
"ocramius/proxy-manager": "~2.0",
"aura/sqlquery": "~2.8"

26
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "3208d5c05083a6ccc17baff9dfde8070",
"content-hash": "6fb2448797e2a31979571f067d57d035",
"packages": [
{
"name": "ademarre/binary-to-text-php",
@@ -1520,28 +1520,30 @@
},
{
"name": "league/fractal",
"version": "0.19.2",
"version": "0.20.1",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/fractal.git",
"reference": "06dc15f6ba38f2dde2f919d3095d13b571190a7c"
"reference": "8b9d39b67624db9195c06f9c1ffd0355151eaf62"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/fractal/zipball/06dc15f6ba38f2dde2f919d3095d13b571190a7c",
"reference": "06dc15f6ba38f2dde2f919d3095d13b571190a7c",
"url": "https://api.github.com/repos/thephpleague/fractal/zipball/8b9d39b67624db9195c06f9c1ffd0355151eaf62",
"reference": "8b9d39b67624db9195c06f9c1ffd0355151eaf62",
"shasum": ""
},
"require": {
"php": ">=5.4"
"php": ">=7.4"
},
"require-dev": {
"doctrine/orm": "^2.5",
"illuminate/contracts": "~5.0",
"mockery/mockery": "~0.9",
"mockery/mockery": "^1.3",
"pagerfanta/pagerfanta": "~1.0.0",
"phpunit/phpunit": "^4.8.35 || ^7.5",
"squizlabs/php_codesniffer": "~1.5|~2.0|~3.4",
"phpstan/phpstan": "^1.4",
"phpunit/phpunit": "^9.5",
"squizlabs/php_codesniffer": "~3.4",
"vimeo/psalm": "^4.22",
"zendframework/zend-paginator": "~2.3"
},
"suggest": {
@@ -1552,7 +1554,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "0.13-dev"
"dev-master": "0.20.x-dev"
}
},
"autoload": {
@@ -1582,9 +1584,9 @@
],
"support": {
"issues": "https://github.com/thephpleague/fractal/issues",
"source": "https://github.com/thephpleague/fractal/tree/0.19.2"
"source": "https://github.com/thephpleague/fractal/tree/0.20.1"
},
"time": "2020-01-24T23:17:29+00:00"
"time": "2022-04-11T12:47:17+00:00"
},
{
"name": "monolog/monolog",

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.
*
@@ -36,52 +36,35 @@ class SPException extends Exception
/**
* Constantes para tipos de excepción
*/
const OK = 0;
const CRITICAL = 1;
const WARNING = 2;
const ERROR = 3;
const INFO = 4;
/**
* @var int Tipo de excepción
*/
protected $type;
/**
* @var string Ayuda de la excepción
*/
protected $hint;
public const OK = 0;
public const CRITICAL = 1;
public const WARNING = 2;
public const ERROR = 3;
public const INFO = 4;
protected int $type;
protected ?string $hint;
/**
* SPException constructor.
*
* @param string $message
* @param int $type
* @param string $hint
* @param int $code
* @param Exception|null $previous
* @param string $message
* @param int $type
* @param string|null $hint
* @param int $code
* @param Exception|null $previous
*/
public function __construct($message, $type = self::ERROR, $hint = null, $code = 0, Exception $previous = null)
{
public function __construct(
string $message,
int $type = self::ERROR,
?string $hint = null,
int $code = 0,
Exception $previous = null
) {
$this->type = $type;
$this->hint = $hint;
parent::__construct($message, (int)$code, $previous);
}
/**
* @param $type
*
* @return mixed
*/
public static function getExceptionTypeName($type)
{
$typeName = [
self::OK => 'ok',
self::CRITICAL => 'critical',
self::WARNING => 'warning',
self::ERROR => 'error'
];
return $typeName[$type];
parent::__construct($message, $code, $previous);
}
/**
@@ -89,13 +72,10 @@ class SPException extends Exception
*/
public function __toString()
{
return __CLASS__ . ": [{$this->code}]: {$this->message} ({$this->hint})\n";
return __CLASS__.": [{$this->code}]: {$this->message} ({$this->hint})\n";
}
/**
* @return string
*/
public function getHint()
public function getHint(): ?string
{
return $this->hint;
}
@@ -103,8 +83,8 @@ class SPException extends Exception
/**
* @return int|string
*/
public function getType()
public function getType(): int|string
{
return $this->type;
}
}
}

View File

@@ -82,11 +82,11 @@ final class AccountAclDto
}
/**
* @param AccountDetailsResponse $accountDetailsResponse
* @param AccountEnrichedDto $accountDetailsResponse
*
* @return AccountAclDto
*/
public static function makeFromAccount(AccountDetailsResponse $accountDetailsResponse): AccountAclDto
public static function makeFromAccount(AccountEnrichedDto $accountDetailsResponse): AccountAclDto
{
return new self(
$accountDetailsResponse->getId(),

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,11 +28,11 @@ use SP\DataModel\AccountVData;
use SP\DataModel\ItemData;
/**
* Class AccountDetailsResponse
* Class AccountEnrichedDto
*/
class AccountDetailsResponse
class AccountEnrichedDto
{
private int $id;
private int $id;
private AccountVData $accountVData;
/**
* @var ItemData[] Los usuarios secundarios de la cuenta.
@@ -50,15 +50,22 @@ class AccountDetailsResponse
/**
* AccountDetailsResponse constructor.
*
* @param int $id
* @param AccountVData $accountVData
* @param AccountVData $accountVData
*/
public function __construct(int $id, AccountVData $accountVData)
public function __construct(AccountVData $accountVData)
{
$this->id = $id;
$this->id = $accountVData->getId();
$this->accountVData = $accountVData;
}
/**
* @return int
*/
public function getId(): int
{
return $this->id;
}
/**
* @return ItemData[]
*/
@@ -68,7 +75,7 @@ class AccountDetailsResponse
}
/**
* @param ItemData[] $users
* @param ItemData[] $users
*/
public function setUsers(array $users): void
{
@@ -84,7 +91,7 @@ class AccountDetailsResponse
}
/**
* @param ItemData[] $userGroups
* @param ItemData[] $userGroups
*/
public function setUserGroups(array $userGroups): void
{
@@ -100,7 +107,7 @@ class AccountDetailsResponse
}
/**
* @param ItemData[] $tags
* @param ItemData[] $tags
*/
public function setTags(array $tags): void
{
@@ -114,12 +121,4 @@ class AccountDetailsResponse
{
return $this->accountVData;
}
/**
* @return int
*/
public function getId(): int
{
return $this->id;
}
}
}

View File

@@ -30,7 +30,7 @@ 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\Dto\AccountEnrichedDto;
use SP\DataModel\ItemSearchData;
use SP\Domain\Account\Out\AccountData;
use SP\Domain\Account\Out\AccountPassData;
@@ -52,19 +52,19 @@ interface AccountServiceInterface
* @throws QueryException
* @throws ConstraintException
*/
public function withUsersById(AccountDetailsResponse $accountDetailsResponse): AccountServiceInterface;
public function withUsersById(AccountEnrichedDto $accountDetailsResponse): AccountServiceInterface;
/**
* @throws QueryException
* @throws ConstraintException
*/
public function withUserGroupsById(AccountDetailsResponse $accountDetailsResponse): AccountServiceInterface;
public function withUserGroupsById(AccountEnrichedDto $accountDetailsResponse): AccountServiceInterface;
/**
* @throws QueryException
* @throws ConstraintException
*/
public function withTagsById(AccountDetailsResponse $accountDetailsResponse): AccountServiceInterface;
public function withTagsById(AccountEnrichedDto $accountDetailsResponse): AccountServiceInterface;
/**
* @throws \SP\Core\Exceptions\ConstraintException
@@ -114,7 +114,7 @@ interface AccountServiceInterface
* @throws NoSuchItemException
* @throws ConstraintException
*/
public function getById(int $id): AccountDetailsResponse;
public function getById(int $id): AccountEnrichedDto;
/**
* Updates external items for the account

View File

@@ -26,8 +26,9 @@ namespace SP\Domain\Account\Out;
use League\Fractal\Resource\Collection;
use SP\Core\Acl\ActionsInterface;
use SP\DataModel\Dto\AccountDetailsResponse;
use SP\DataModel\Dto\AccountEnrichedDto;
use SP\Domain\Common\Out\AdapterBase;
use SP\Domain\Config\In\ConfigDataInterface;
use SP\Domain\CustomField\CustomFieldServiceInterface;
use SP\Domain\CustomField\Out\CustomFieldAdapter;
use SP\Mvc\Controller\ItemTrait;
@@ -37,13 +38,23 @@ use SP\Util\Link;
/**
* Class AccountAdapter
*
* @package SP\Domain\Account\Out
* @template T of AccountEnrichedDto
* @template-implements AccountAdapterInterface<T>
*/
final class AccountAdapter extends AdapterBase implements AccountAdapterInterface
{
use ItemTrait;
protected $availableIncludes = ['customFields'];
protected array $availableIncludes = ['customFields'];
private CustomFieldServiceInterface $customFieldService;
public function __construct(ConfigDataInterface $configData, CustomFieldServiceInterface $customFieldService)
{
parent::__construct($configData);
$this->customFieldService = $customFieldService;
}
/**
* @throws \SP\Core\Exceptions\ConstraintException
@@ -51,17 +62,15 @@ final class AccountAdapter extends AdapterBase implements AccountAdapterInterfac
* @throws \SP\Core\Exceptions\SPException
* @throws \SP\Domain\Common\Services\ServiceException
*/
public function includeCustomFields(
AccountDetailsResponse $data,
CustomFieldServiceInterface $customFieldService
): Collection {
public function includeCustomFields(AccountEnrichedDto $data,): Collection
{
return $this->collection(
$this->getCustomFieldsForItem(ActionsInterface::ACCOUNT, $data->getId(), $customFieldService),
$this->getCustomFieldsForItem(ActionsInterface::ACCOUNT, $data->getId(), $this->customFieldService),
new CustomFieldAdapter($this->configData)
);
}
public function transform(AccountDetailsResponse $data): array
public function transform(AccountEnrichedDto $data): array
{
$account = $data->getAccountVData();

View File

@@ -25,13 +25,10 @@
namespace SP\Domain\Account\Out;
use League\Fractal\Resource\Collection;
use SP\DataModel\Dto\AccountDetailsResponse;
use SP\Domain\CustomField\CustomFieldServiceInterface;
use SP\DataModel\Dto\AccountEnrichedDto;
/**
* Class AccountAdapter
*
* @package SP\Adapters
*/
interface AccountAdapterInterface
{
@@ -41,10 +38,7 @@ interface AccountAdapterInterface
* @throws \SP\Core\Exceptions\SPException
* @throws \SP\Domain\Common\Services\ServiceException
*/
public function includeCustomFields(
AccountDetailsResponse $data,
CustomFieldServiceInterface $customFieldService
): Collection;
public function includeCustomFields(AccountEnrichedDto $data,): Collection;
public function transform(AccountDetailsResponse $data): array;
public function transform(AccountEnrichedDto $data): array;
}

View File

@@ -33,7 +33,7 @@ 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\Dto\AccountEnrichedDto;
use SP\DataModel\Dto\AccountHistoryCreateDto;
use SP\DataModel\ItemPreset\AccountPermission;
use SP\DataModel\ItemPreset\AccountPrivate;
@@ -100,7 +100,7 @@ final class AccountService extends Service implements AccountServiceInterface
* @throws QueryException
* @throws ConstraintException
*/
public function withUsersById(AccountDetailsResponse $accountDetailsResponse): AccountServiceInterface
public function withUsersById(AccountEnrichedDto $accountDetailsResponse): AccountServiceInterface
{
$accountDetailsResponse->setUsers(
$this->accountToUserRepository->getUsersByAccountId($accountDetailsResponse->getId())
@@ -114,7 +114,7 @@ final class AccountService extends Service implements AccountServiceInterface
* @throws QueryException
* @throws ConstraintException
*/
public function withUserGroupsById(AccountDetailsResponse $accountDetailsResponse): AccountServiceInterface
public function withUserGroupsById(AccountEnrichedDto $accountDetailsResponse): AccountServiceInterface
{
$accountDetailsResponse->setUserGroups(
$this->accountToUserGroupRepository->getUserGroupsByAccountId($accountDetailsResponse->getId())
@@ -128,7 +128,7 @@ final class AccountService extends Service implements AccountServiceInterface
* @throws QueryException
* @throws ConstraintException
*/
public function withTagsById(AccountDetailsResponse $accountDetailsResponse): AccountServiceInterface
public function withTagsById(AccountEnrichedDto $accountDetailsResponse): AccountServiceInterface
{
$accountDetailsResponse->setTags(
$this->accountToTagRepository->getTagsByAccountId($accountDetailsResponse->getId())
@@ -311,7 +311,7 @@ final class AccountService extends Service implements AccountServiceInterface
* @throws NoSuchItemException
* @throws ConstraintException
*/
public function getById(int $id): AccountDetailsResponse
public function getById(int $id): AccountEnrichedDto
{
$result = $this->accountRepository->getById($id);
@@ -319,7 +319,7 @@ final class AccountService extends Service implements AccountServiceInterface
throw new NoSuchItemException(__u('The account doesn\'t exist'));
}
return new AccountDetailsResponse($id, $result->getData());
return new AccountEnrichedDto($result->getData());
}
/**

View File

@@ -25,6 +25,7 @@
namespace SP\Domain\Common\Out;
use League\Fractal\TransformerAbstract;
use RuntimeException;
use SP\Domain\Config\In\ConfigDataInterface;
/**
@@ -39,5 +40,9 @@ abstract class AdapterBase extends TransformerAbstract
public function __construct(ConfigDataInterface $configData)
{
$this->configData = $configData;
if (!method_exists(static::class, 'transform')) {
throw new RuntimeException('\'transform\' method must be implemented');
}
}
}

View File

@@ -70,4 +70,12 @@ abstract class DataModelBase
return property_exists($this, $name) || isset($this->properties[$name]);
}
final public function toArray(): array
{
if (count($this->properties) !== 0) {
return $this->properties;
}
return get_object_vars($this);
}
}

View File

@@ -24,7 +24,6 @@
namespace SP\Domain\CustomField\Out;
use SP\Domain\Common\Out\AdapterBase;
use SP\Domain\CustomField\Services\CustomFieldItem;
@@ -48,4 +47,4 @@ final class CustomFieldAdapter extends AdapterBase implements CustomFieldAdapter
'required' => $data->required,
];
}
}
}

View File

@@ -35,4 +35,4 @@ use SP\Domain\CustomField\Services\CustomFieldItem;
interface CustomFieldAdapterInterface
{
public function transform(CustomFieldItem $data): array;
}
}

View File

@@ -33,11 +33,10 @@ use SP\Domain\CustomField\Services\CustomFieldItem;
use SP\Domain\CustomField\Services\CustomFieldService;
use SP\Http\RequestInterface;
use SP\Util\Filter;
use function SP\__u;
/**
* Trait ItemTrait
*
* @package SP\Modules\Web\Controllers\Traits
*/
trait ItemTrait
{
@@ -83,7 +82,7 @@ trait ItemTrait
$customFields[] = $customField;
} catch (CryptoException $e) {
throw new SPException(__u('Internal error'), SPException::ERROR);
throw new SPException(__u('Internal error'), SPException::ERROR, null, 0, $e);
}
}
@@ -106,11 +105,11 @@ trait ItemTrait
*/
protected function addCustomFieldsForItem(
int $moduleId,
$itemId,
int|array $itemId,
RequestInterface $request,
CustomFieldServiceInterface $customFieldService
): void {
$customFields = $this->getCustomFieldsFromRequest($request);
$customFields = self::getCustomFieldsFromRequest($request);
if (!empty($customFields)) {
try {
@@ -124,11 +123,24 @@ trait ItemTrait
$customFieldService->create($customFieldData);
}
} catch (CryptoException $e) {
throw new SPException(__u('Internal error'), SPException::ERROR);
throw new SPException(__u('Internal error'), SPException::ERROR, null, 0, $e);
}
}
}
/**
* @param \SP\Http\RequestInterface $request
*
* @return array|null
*/
private static function getCustomFieldsFromRequest(RequestInterface $request): ?array
{
return $request->analyzeArray(
'customfield',
fn($values) => array_map(static fn($value) => Filter::getString($value), $values)
);
}
/**
* Eliminar los campos personalizados del elemento
*
@@ -142,7 +154,7 @@ trait ItemTrait
*/
protected function deleteCustomFieldsForItem(
int $moduleId,
$itemId,
array|int $itemId,
CustomFieldServiceInterface $customFieldService
): void {
if (is_array($itemId)) {
@@ -166,11 +178,11 @@ trait ItemTrait
*/
protected function updateCustomFieldsForItem(
int $moduleId,
$itemId,
int|array $itemId,
RequestInterface $request,
CustomFieldServiceInterface $customFieldService
): void {
$customFields = $this->getCustomFieldsFromRequest($request);
$customFields = self::getCustomFieldsFromRequest($request);
if (!empty($customFields)) {
try {
@@ -186,7 +198,7 @@ trait ItemTrait
}
}
} catch (CryptoException $e) {
throw new SPException(__u('Internal error'), SPException::ERROR);
throw new SPException(__u('Internal error'), SPException::ERROR, null, 0, $e);
}
}
}
@@ -208,17 +220,4 @@ trait ItemTrait
{
return $request->analyzeArray('items');
}
/**
* @param \SP\Http\RequestInterface $request
*
* @return array|null
*/
private static function getCustomFieldsFromRequest(RequestInterface $request): ?array
{
return $request->analyzeArray(
'customfield',
fn($values) => array_map(static fn($value) => Filter::getString($value), $values)
);
}
}
}

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.
*
@@ -36,26 +36,26 @@ interface ItemAdapterInterface
*
* @return array
*/
public function getItemsFromModel();
public function getItemsFromModel(): array;
/**
* Returns a JSON like collection of items for a select component
*
* @return string
*/
public function getJsonItemsFromModel();
public function getJsonItemsFromModel(): string;
/**
* Returns a collection of items for a select component
*
* @return array
*/
public function getItemsFromArray();
public function getItemsFromArray(): array;
/**
* Returns a collection of items for a select component
*
* @return string
*/
public function getJsonItemsFromArray();
}
public function getJsonItemsFromArray(): string;
}

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,20 +33,20 @@ use JsonSerializable;
*/
final class SelectItem implements JsonSerializable
{
protected $id;
protected string $name;
protected $item;
protected bool $selected = false;
protected bool $skip = false;
protected int|string $id;
protected string $name;
protected mixed $item;
protected bool $selected = false;
protected bool $skip = false;
/**
* SelectItem constructor.
*
* @param int|string $id
* @param string $name
* @param mixed $item
* @param int|string $id
* @param string $name
* @param mixed $item
*/
public function __construct($id, string $name, $item = null)
public function __construct(int|string $id, string $name, mixed $item = null)
{
$this->id = $id;
$this->name = $name;
@@ -56,7 +56,7 @@ final class SelectItem implements JsonSerializable
/**
* @return int|string
*/
public function getId()
public function getId(): int|string
{
return $this->id;
}
@@ -77,13 +77,17 @@ final class SelectItem implements JsonSerializable
}
/**
* @param string $property
*
* @return mixed
*/
public function getItemProperty(string $property)
public function getItemProperty(string $property): mixed
{
return null !== $this->item && isset($this->item->{$property})
? $this->item->{$property}
: null;
if (null !== $this->item) {
return $this->item->{$property} ?? null;
}
return null;
}
public function isSkip(): bool
@@ -99,8 +103,8 @@ final class SelectItem implements JsonSerializable
/**
* @inheritDoc
*/
public function jsonSerialize()
public function jsonSerialize(): array
{
return ['id' => $this->id, 'name' => $this->name];
}
}
}

View File

@@ -28,6 +28,7 @@ use RuntimeException;
use SP\Core\Exceptions\SPException;
use SP\Domain\Common\Out\DataModelInterface;
use SP\Http\Json;
use function SP\__u;
/**
* Class SelectItemAdapter
@@ -103,27 +104,25 @@ final class SelectItemAdapter implements ItemAdapterInterface
/**
* Returns a collection of items for a select component and set selected ones from an array
*
* @param array $selected
* @param string|int|null $skip
* @param array $selected
* @param string|int|null $skip
*
* @return SelectItem[]
*/
public function getItemsFromModelSelected(
array $selected,
$skip = null
): array
{
mixed $skip = null
): array {
$items = $this->getItemsFromModel();
foreach ($items as $item) {
if ($skip !== null && $item->getId() === $skip) {
$item->setSkip(true);
array_walk(
$items,
static function (SelectItem $item) use ($selected, $skip) {
$item->setSkip($item->getId() === $skip);
/** @noinspection TypeUnsafeArraySearchInspection */
$item->setSelected(in_array($item->getId(), $selected));
}
if (in_array($item->getId(), $selected, false)) {
$item->setSelected(true);
}
}
);
return $items;
}
@@ -135,21 +134,16 @@ final class SelectItemAdapter implements ItemAdapterInterface
*/
public function getItemsFromModel(): array
{
$out = [];
return array_map(
static function ($item) {
if (!$item instanceof DataModelInterface) {
throw new RuntimeException(__u('Wrong object type'));
}
foreach ($this->items as $item) {
if (!$item instanceof DataModelInterface) {
throw new RuntimeException(__u('Wrong object type'));
}
$out[] = new SelectItem(
$item->getId(),
$item->getName(),
$item
);
}
return $out;
return new SelectItem($item->getId(), $item->getName(), $item);
},
$this->items
);
}
/**
@@ -157,20 +151,19 @@ final class SelectItemAdapter implements ItemAdapterInterface
*
* @return SelectItem[]
*/
public function getItemsFromArraySelected(
array $selected,
bool $useValueAsKey = false
): array
public function getItemsFromArraySelected(array $selected, bool $useValueAsKey = false): array
{
$items = $this->getItemsFromArray();
foreach ($items as $item) {
$value = $useValueAsKey ? $item->getName() : $item->getId();
array_walk(
$items,
static function (SelectItem $item) use ($selected, $useValueAsKey) {
$value = $useValueAsKey ? $item->getName() : $item->getId();
if (in_array($value, $selected, false)) {
$item->setSelected(true);
/** @noinspection TypeUnsafeArraySearchInspection */
$item->setSelected(in_array($value, $selected));
}
}
);
return $items;
}
@@ -182,12 +175,10 @@ final class SelectItemAdapter implements ItemAdapterInterface
*/
public function getItemsFromArray(): array
{
$out = [];
foreach ($this->items as $key => $value) {
$out[] = new SelectItem($key, $value);
}
return $out;
return array_map(
static fn($key, $value) => new SelectItem($key, $value),
array_keys($this->items),
array_values($this->items)
);
}
}
}

View File

@@ -0,0 +1,132 @@
<?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\Out;
use League\Fractal\Manager;
use League\Fractal\Resource\Item;
use SP\Domain\Account\Out\AccountAdapter;
use SP\Domain\CustomField\CustomFieldServiceInterface;
use SP\Mvc\View\Components\SelectItemAdapter;
use SP\Tests\Generators\AccountDataGenerator;
use SP\Tests\Generators\CustomFieldGenerator;
use SP\Tests\UnitaryTestCase;
/**
* Class AccountAdapterTest
*/
class AccountAdapterTest extends UnitaryTestCase
{
public function testAdapt(): void
{
$dataGenerator = AccountDataGenerator::factory();
$adapter = new AccountAdapter(
$this->config->getConfigData(),
$this->createStub(CustomFieldServiceInterface::class)
);
$accountData = $dataGenerator->getAccountData();
$out = $adapter->transform($accountData);
$this->assertEquals($accountData->getId(), $out['id']);
$this->assertEquals(
SelectItemAdapter::factory($accountData->getTags())->getItemsFromModel(),
$out['tags']
);
$this->assertEquals(
SelectItemAdapter::factory($accountData->getUsers())->getItemsFromModel(),
$out['users']
);
$this->assertEquals(
SelectItemAdapter::factory($accountData->getUserGroups())->getItemsFromModel(),
$out['userGroups']
);
$accountVData = $accountData->getAccountVData();
$this->assertEquals($accountVData->getName(), $out['name']);
$this->assertEquals($accountVData->getClientId(), $out['clientId']);
$this->assertEquals($accountVData->getClientName(), $out['clientName']);
$this->assertEquals($accountVData->getCategoryId(), $out['categoryId']);
$this->assertEquals($accountVData->getCategoryName(), $out['categoryName']);
$this->assertEquals($accountVData->getUserId(), $out['userId']);
$this->assertEquals($accountVData->getUserName(), $out['userName']);
$this->assertEquals($accountVData->getUserLogin(), $out['userLogin']);
$this->assertEquals($accountVData->getUserGroupId(), $out['userGroupId']);
$this->assertEquals($accountVData->getUserGroupName(), $out['userGroupName']);
$this->assertEquals($accountVData->getUserEditId(), $out['userEditId']);
$this->assertEquals($accountVData->getUserEditName(), $out['userEditName']);
$this->assertEquals($accountVData->getUserEditLogin(), $out['userEditLogin']);
$this->assertEquals($accountVData->getLogin(), $out['login']);
$this->assertEquals($accountVData->getUrl(), $out['url']);
$this->assertEquals($accountVData->getNotes(), $out['notes']);
$this->assertEquals($accountVData->getOtherUserEdit(), $out['otherUserEdit']);
$this->assertEquals($accountVData->getOtherUserGroupEdit(), $out['otherUserGroupEdit']);
$this->assertEquals($accountVData->getDateAdd(), $out['dateAdd']);
$this->assertEquals($accountVData->getDateEdit(), $out['dateEdit']);
$this->assertEquals($accountVData->getCountView(), $out['countView']);
$this->assertEquals($accountVData->getCountDecrypt(), $out['countDecrypt']);
$this->assertEquals($accountVData->getIsPrivate(), $out['isPrivate']);
$this->assertEquals($accountVData->getIsPrivateGroup(), $out['isPrivateGroup']);
$this->assertEquals($accountVData->getPassDate(), $out['passDate']);
$this->assertEquals($accountVData->getPassDateChange(), $out['passDateChange']);
$this->assertEquals($accountVData->getParentId(), $out['parentId']);
$this->assertEquals($accountVData->getPublicLinkHash(), $out['publicLinkHash']);
$this->assertNull($out['customFields']);
$this->assertEquals('self', $out['links'][0]['rel']);
$this->assertNotEmpty($out['links'][0]['uri']);
}
public function testIncludeCustomFields(): void
{
$customFieldData = CustomFieldGenerator::factory()->buildSimpleModel();
$customFieldsService = $this->createStub(CustomFieldServiceInterface::class);
$customFieldsService->expects(self::once())
->method('getForModuleAndItemId')
->willReturn([$customFieldData]);
$adapter = new AccountAdapter($this->config->getConfigData(), $customFieldsService);
$fractal = new Manager();
$fractal->parseIncludes('customFields');
$out = $fractal->createData(
new Item(AccountDataGenerator::factory()->getAccountData(), $adapter)
)->toArray();
$this->assertArrayHasKey('customFields', $out['data']);
$this->assertEquals($customFieldData->type, $out['data']['customFields']['data'][0]['typeName']);
$this->assertEquals($customFieldData->typeText, $out['data']['customFields']['data'][0]['typeText']);
$this->assertEquals($customFieldData->definitionId, $out['data']['customFields']['data'][0]['definitionId']);
$this->assertEquals(
$customFieldData->definitionName,
$out['data']['customFields']['data'][0]['definitionName']
);
$this->assertEquals($customFieldData->help, $out['data']['customFields']['data'][0]['help']);
$this->assertEquals($customFieldData->value, $out['data']['customFields']['data'][0]['value']);
$this->assertEquals($customFieldData->encrypted, $out['data']['customFields']['data'][0]['isEncrypted']);
$this->assertEquals($customFieldData->required, $out['data']['customFields']['data'][0]['required']);
}
}

View File

@@ -29,7 +29,6 @@ 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;
@@ -59,9 +58,8 @@ class AccountAclServiceTest extends UnitaryTestCase
ActionsInterface::ACCOUNT_COPY_PASS,
ActionsInterface::ACCOUNT_DELETE,
];
private static array $accounts;
protected AccountDetailsResponse $account;
private AccountAclService $accountAclService;
private static array $accounts;
private AccountAclService $accountAclService;
public static function setUpBeforeClass(): void
{

View File

@@ -0,0 +1,87 @@
<?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\Generators;
use SP\DataModel\AccountVData;
use SP\DataModel\Dto\AccountEnrichedDto;
use SP\DataModel\ItemData;
/**
* Class AccountDataGenerator
*/
final class AccountDataGenerator extends DataGenerator
{
public function getAccountData(): AccountEnrichedDto
{
$accountData = new AccountVData([
'id' => $this->faker->randomNumber(),
'name' => $this->faker->name,
'clientId' => $this->faker->randomNumber(),
'clientName' => $this->faker->name,
'categoryId' => $this->faker->randomNumber(),
'categoryName' => $this->faker->name,
'userId' => $this->faker->randomNumber(),
'userName' => $this->faker->userName,
'userLogin' => $this->faker->name,
'userGroupId' => $this->faker->randomNumber(),
'userGroupName' => $this->faker->name,
'userEditId' => $this->faker->randomNumber(),
'userEditName' => $this->faker->userName,
'userEditLogin' => $this->faker->name,
'login' => $this->faker->name,
'url' => $this->faker->url,
'notes' => $this->faker->text,
'otherUserEdit' => $this->faker->boolean,
'otherUserGroupEdit' => $this->faker->boolean,
'dateAdd' => $this->faker->unixTime,
'dateEdit' => $this->faker->unixTime,
'countView' => $this->faker->randomNumber(),
'countDecrypt' => $this->faker->randomNumber(),
'isPrivate' => $this->faker->boolean,
'isPrivateGroup' => $this->faker->boolean,
'passDate' => $this->faker->unixTime,
'passDateChange' => $this->faker->unixTime,
'parentId' => $this->faker->randomNumber(),
'publicLinkHash' => $this->faker->sha1,
]);
$out = new AccountEnrichedDto($accountData);
$out->setUsers($this->buildItemData());
$out->setTags($this->buildItemData());
$out->setUserGroups($this->buildItemData());
return $out;
}
/**
* @return ItemData[]
*/
public function buildItemData(): array
{
return array_map(
fn() => new ItemData(['id' => $this->faker->randomNumber(), 'name' => $this->faker->name]),
range(0, 9)
);
}
}

View File

@@ -0,0 +1,60 @@
<?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\Generators;
use SP\Domain\Common\Out\SimpleModel;
/**
* Class CustomFieldGenerator
*/
final class CustomFieldGenerator extends DataGenerator
{
public function buildSimpleModel(bool $useEncryption = false): SimpleModel
{
$data = null;
$key = null;
if ($useEncryption) {
$data = $this->faker->text;
$key = $this->faker->sha1;
}
return new SimpleModel([
'required' => $this->faker->boolean,
'showInList' => $this->faker->boolean,
'help' => $this->faker->text,
'definitionId' => $this->faker->randomNumber(),
'definitionName' => $this->faker->name,
'typeId' => $this->faker->randomNumber(),
'typeName' => $this->faker->name,
'typeText' => $this->faker->text,
'moduleId' => $this->faker->randomNumber(),
'formId' => $this->faker->randomNumber(),
'isEncrypted' => $this->faker->boolean,
'data' => $data,
'key' => $key,
]);
}
}

View File

@@ -0,0 +1,46 @@
<?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\Generators;
use Faker\Factory;
use Faker\Generator;
/**
* Class DataGenerator
*/
abstract class DataGenerator
{
protected Generator $faker;
private function __construct()
{
$this->faker = Factory::create();
}
public static function factory(): static
{
return new static();
}
}