diff --git a/app/modules/api/Controllers/AccountController.php b/app/modules/api/Controllers/AccountController.php index 1a5d9323..3f067938 100644 --- a/app/modules/api/Controllers/AccountController.php +++ b/app/modules/api/Controllers/AccountController.php @@ -43,6 +43,7 @@ use SP\Services\Account\AccountRequest; use SP\Services\Account\AccountSearchFilter; use SP\Services\Account\AccountService; use SP\Services\Api\ApiResponse; +use SP\Util\Util; /** * Class AccountController @@ -72,7 +73,7 @@ final class AccountController extends ControllerBase $this->setupApi(ActionsInterface::ACCOUNT_VIEW); $id = $this->apiService->getParamInt('id', true); - $customFields = boolval($this->apiService->getParamString('customFields')); + $customFields = Util::boolval($this->apiService->getParamString('customFields')); if ($customFields) { $this->apiService->requireMasterPass(); @@ -99,13 +100,14 @@ final class AccountController extends ControllerBase $adapter = new AccountAdapter($this->configData); + $out = $this->fractal + ->createData(new Item($accountResponse, $adapter)); + if ($customFields) { - $adapter->withCustomFields($this->getCustomFieldsForItem(ActionsInterface::ACCOUNT, $id)); + $this->fractal->parseIncludes(['customFields']); } - $item = new Item($accountResponse, $adapter); - - $this->returnResponse(ApiResponse::makeSuccess($this->fractal->createData($item)->toArray(), $id)); + $this->returnResponse(ApiResponse::makeSuccess($out->toArray(), $id)); } catch (Exception $e) { $this->returnResponseException($e); diff --git a/app/modules/api/Controllers/CategoryController.php b/app/modules/api/Controllers/CategoryController.php index 5fdae281..f41bec19 100644 --- a/app/modules/api/Controllers/CategoryController.php +++ b/app/modules/api/Controllers/CategoryController.php @@ -27,6 +27,8 @@ namespace SP\Modules\Api\Controllers; use DI\DependencyException; use DI\NotFoundException; use Exception; +use League\Fractal\Resource\Item; +use SP\Adapters\CategoryAdapter; use SP\Core\Acl\ActionsInterface; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; @@ -34,8 +36,10 @@ use SP\Core\Exceptions\InvalidClassException; use SP\DataModel\CategoryData; use SP\DataModel\ItemSearchData; use SP\Modules\Api\Controllers\Help\CategoryHelp; +use SP\Mvc\Controller\ItemTrait; use SP\Services\Api\ApiResponse; use SP\Services\Category\CategoryService; +use SP\Util\Util; /** @@ -45,6 +49,8 @@ use SP\Services\Category\CategoryService; */ final class CategoryController extends ControllerBase { + use ItemTrait; + /** * @var CategoryService */ @@ -59,6 +65,10 @@ final class CategoryController extends ControllerBase $this->setupApi(ActionsInterface::CATEGORY_VIEW); $id = $this->apiService->getParamInt('id', true); + $customFields = Util::boolval($this->apiService->getParamString('customFields')); + + $adapter = new CategoryAdapter($this->configData); + $categoryData = $this->categoryService->getById($id); $this->eventDispatcher->notifyEvent('show.category', @@ -68,7 +78,16 @@ final class CategoryController extends ControllerBase ->addDetail('ID', $id)) ); - $this->returnResponse(ApiResponse::makeSuccess($categoryData, $id)); + $out = $this->fractal + ->createData( + new Item($categoryData, new CategoryAdapter($this->configData))); + + if ($customFields) { + $this->apiService->requireMasterPass(); + $this->fractal->parseIncludes(['customFields']); + } + + $this->returnResponse(ApiResponse::makeSuccess($out->toArray(), $id)); } catch (Exception $e) { processException($e); diff --git a/app/modules/api/Controllers/ClientController.php b/app/modules/api/Controllers/ClientController.php index 1029dd73..9d205c66 100644 --- a/app/modules/api/Controllers/ClientController.php +++ b/app/modules/api/Controllers/ClientController.php @@ -27,6 +27,8 @@ namespace SP\Modules\Api\Controllers; use DI\DependencyException; use DI\NotFoundException; use Exception; +use League\Fractal\Resource\Item; +use SP\Adapters\ClientAdapter; use SP\Core\Acl\ActionsInterface; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; @@ -34,8 +36,10 @@ use SP\Core\Exceptions\InvalidClassException; use SP\DataModel\ClientData; use SP\DataModel\ItemSearchData; use SP\Modules\Api\Controllers\Help\ClientHelp; +use SP\Mvc\Controller\ItemTrait; use SP\Services\Api\ApiResponse; use SP\Services\Client\ClientService; +use SP\Util\Util; /** * Class ClientController @@ -44,6 +48,8 @@ use SP\Services\Client\ClientService; */ final class ClientController extends ControllerBase { + use ItemTrait; + /** * @var ClientService */ @@ -58,6 +64,9 @@ final class ClientController extends ControllerBase $this->setupApi(ActionsInterface::CLIENT_VIEW); $id = $this->apiService->getParamInt('id', true); + + $customFields = Util::boolval($this->apiService->getParamString('customFields')); + $clientData = $this->clientService->getById($id); $this->eventDispatcher->notifyEvent('show.client', new Event($this)); @@ -69,7 +78,20 @@ final class ClientController extends ControllerBase ->addDetail('ID', $id)) ); - $this->returnResponse(ApiResponse::makeSuccess($clientData, $id)); + if ($customFields) { + $this->apiService->requireMasterPass(); + } + + $out = $this->fractal + ->createData( + new Item($clientData, new ClientAdapter($this->configData))); + + if ($customFields) { + $this->apiService->requireMasterPass(); + $this->fractal->parseIncludes(['customFields']); + } + + $this->returnResponse(ApiResponse::makeSuccess($out->toArray(), $id)); } catch (Exception $e) { processException($e); diff --git a/app/modules/api/Controllers/Help/CategoryHelp.php b/app/modules/api/Controllers/Help/CategoryHelp.php index 6780a966..083fb735 100644 --- a/app/modules/api/Controllers/Help/CategoryHelp.php +++ b/app/modules/api/Controllers/Help/CategoryHelp.php @@ -40,7 +40,9 @@ final class CategoryHelp implements HelpInterface { return [ - self::getItem('id', __('Category Id'), true) + self::getItem('id', __('Category Id'), true), + self::getItem('customFields', __('Get custom fields for the category within the response')), + self::getItem('tokenPass', __('Token\'s password when custom fields are retrieved'), true) ]; } diff --git a/app/modules/api/Controllers/Help/ClientHelp.php b/app/modules/api/Controllers/Help/ClientHelp.php index 41bd8c4f..5bbd276d 100644 --- a/app/modules/api/Controllers/Help/ClientHelp.php +++ b/app/modules/api/Controllers/Help/ClientHelp.php @@ -40,7 +40,9 @@ final class ClientHelp implements HelpInterface { return [ - self::getItem('id', __('Client Id'), true) + self::getItem('id', __('Client Id'), true), + self::getItem('customFields', __('Get custom fields for the client within the response')), + self::getItem('tokenPass', __('Token\'s password when custom fields are retrieved'), true) ]; } diff --git a/lib/SP/Adapters/AccountAdapter.php b/lib/SP/Adapters/AccountAdapter.php index f7aa8bf1..b07e84b7 100644 --- a/lib/SP/Adapters/AccountAdapter.php +++ b/lib/SP/Adapters/AccountAdapter.php @@ -24,13 +24,12 @@ namespace SP\Adapters; -use League\Fractal\TransformerAbstract; -use SP\Config\ConfigData; +use League\Fractal\Resource\Collection; use SP\Core\Acl\ActionsInterface; +use SP\Core\Exceptions\SPException; use SP\DataModel\Dto\AccountDetailsResponse; -use SP\DataModel\ItemData; +use SP\Mvc\Controller\ItemTrait; use SP\Mvc\View\Components\SelectItemAdapter; -use SP\Services\CustomField\CustomFieldItem; use SP\Util\Link; /** @@ -38,33 +37,26 @@ use SP\Util\Link; * * @package SP\Adapters */ -final class AccountAdapter extends TransformerAbstract +final class AccountAdapter extends AdapterBase { - /** - * @var CustomFieldItem[] - */ - private $customFields; - /** - * @var ConfigData - */ - private $configData; + use ItemTrait; + + protected $availableIncludes = [ + 'customFields' + ]; /** - * AccountAdapter constructor. + * @param AccountDetailsResponse $data * - * @param ConfigData $configData + * @return Collection + * @throws SPException */ - public function __construct(ConfigData $configData) + public function includeCustomFields(AccountDetailsResponse $data) { - $this->configData = $configData; - } - - /** - * @param ItemData[] $items - */ - public function withCustomFields(array $items) - { - $this->customFields = $items; + return $this->collection( + $this->getCustomFieldsForItem(ActionsInterface::ACCOUNT, $data->getId()), + new CustomFieldAdapter($this->configData) + ); } /** @@ -72,7 +64,7 @@ final class AccountAdapter extends TransformerAbstract * * @return array */ - public function transform(AccountDetailsResponse $data) + public function transform(AccountDetailsResponse $data): array { $account = $data->getAccountVData(); @@ -109,7 +101,7 @@ final class AccountAdapter extends TransformerAbstract 'tags' => SelectItemAdapter::factory($data->getTags())->getItemsFromModel(), 'users' => SelectItemAdapter::factory($data->getUsers())->getItemsFromModel(), 'userGroups' => SelectItemAdapter::factory($data->getUserGroups())->getItemsFromModel(), - 'customFields' => $this->customFields, + 'customFields' => null, 'links' => [ [ 'rel' => 'self', diff --git a/lib/SP/Adapters/AdapterBase.php b/lib/SP/Adapters/AdapterBase.php new file mode 100644 index 00000000..fa8ec71d --- /dev/null +++ b/lib/SP/Adapters/AdapterBase.php @@ -0,0 +1,52 @@ +. + */ + +namespace SP\Adapters; + + +use League\Fractal\TransformerAbstract; +use SP\Config\ConfigData; + +/** + * Class AdapterBase + * + * @package SP\Adapters + */ +abstract class AdapterBase extends TransformerAbstract +{ + /** + * @var ConfigData + */ + protected $configData; + + /** + * AccountAdapter constructor. + * + * @param ConfigData $configData + */ + public function __construct(ConfigData $configData) + { + $this->configData = $configData; + } +} \ No newline at end of file diff --git a/lib/SP/Adapters/CategoryAdapter.php b/lib/SP/Adapters/CategoryAdapter.php new file mode 100644 index 00000000..f7465618 --- /dev/null +++ b/lib/SP/Adapters/CategoryAdapter.php @@ -0,0 +1,84 @@ +. + */ + +namespace SP\Adapters; + +use League\Fractal\Resource\Collection; +use SP\Core\Acl\ActionsInterface; +use SP\Core\Exceptions\SPException; +use SP\DataModel\CategoryData; +use SP\Mvc\Controller\ItemTrait; +use SP\Util\Link; + +/** + * Class CategoryAdapter + * + * @package SP\Adapters + */ +final class CategoryAdapter extends AdapterBase +{ + use ItemTrait; + + protected $availableIncludes = [ + 'customFields' + ]; + + /** + * @param CategoryData $data + * + * @return Collection + * @throws SPException + */ + public function includeCustomFields(CategoryData $data) + { + return $this->collection( + $this->getCustomFieldsForItem(ActionsInterface::CATEGORY, $data->id), + new CustomFieldAdapter($this->configData) + ); + } + + /** + * @param CategoryData $data + * + * @return array + */ + public function transform(CategoryData $data): array + { + return [ + 'id' => (int)$data->getId(), + 'name' => $data->getName(), + 'description' => $data->getDescription(), + 'customFields' => null, + 'links' => [ + [ + 'rel' => 'self', + 'uri' => Link::getDeepLink($data->getId(), + ActionsInterface::CATEGORY_VIEW, + $this->configData, + true) + ] + ], + ]; + } +} \ No newline at end of file diff --git a/lib/SP/Adapters/ClientAdapter.php b/lib/SP/Adapters/ClientAdapter.php new file mode 100644 index 00000000..f79b4c8e --- /dev/null +++ b/lib/SP/Adapters/ClientAdapter.php @@ -0,0 +1,85 @@ +. + */ + +namespace SP\Adapters; + +use League\Fractal\Resource\Collection; +use SP\Core\Acl\ActionsInterface; +use SP\Core\Exceptions\SPException; +use SP\DataModel\ClientData; +use SP\Mvc\Controller\ItemTrait; +use SP\Util\Link; + +/** + * Class ClientAdapter + * + * @package SP\Adapters + */ +final class ClientAdapter extends AdapterBase +{ + use ItemTrait; + + protected $availableIncludes = [ + 'customFields' + ]; + + /** + * @param ClientData $data + * + * @return Collection + * @throws SPException + */ + public function includeCustomFields(ClientData $data) + { + return $this->collection( + $this->getCustomFieldsForItem(ActionsInterface::CLIENT, $data->id), + new CustomFieldAdapter($this->configData) + ); + } + + /** + * @param ClientData $data + * + * @return array + */ + public function transform(ClientData $data): array + { + return [ + 'id' => (int)$data->getId(), + 'name' => $data->getName(), + 'description' => $data->getDescription(), + 'global' => $data->isGlobal, + 'customFields' => null, + 'links' => [ + [ + 'rel' => 'self', + 'uri' => Link::getDeepLink($data->getId(), + ActionsInterface::CLIENT_VIEW, + $this->configData, + true) + ] + ], + ]; + } +} \ No newline at end of file diff --git a/lib/SP/Adapters/CustomFieldAdapter.php b/lib/SP/Adapters/CustomFieldAdapter.php new file mode 100644 index 00000000..35e75f3b --- /dev/null +++ b/lib/SP/Adapters/CustomFieldAdapter.php @@ -0,0 +1,55 @@ +. + */ + +namespace SP\Adapters; + + +use SP\Services\CustomField\CustomFieldItem; + +/** + * Class CustomFieldAdapter + * + * @package SP\Adapters + */ +final class CustomFieldAdapter extends AdapterBase +{ + /** + * @param CustomFieldItem $data + * + * @return array + */ + public function transform(CustomFieldItem $data): array + { + return [ + 'type' => $data->typeName, + 'typeText' => $data->typeText, + 'definitionId' => $data->definitionId, + 'definitionName' => $data->definitionName, + 'help' => $data->help, + 'value' => $data->value, + 'encrypted' => $data->isEncrypted, + 'required' => $data->required + ]; + } +} \ No newline at end of file diff --git a/lib/SP/Mvc/Controller/ItemTrait.php b/lib/SP/Mvc/Controller/ItemTrait.php index 1f15b927..5d56048c 100644 --- a/lib/SP/Mvc/Controller/ItemTrait.php +++ b/lib/SP/Mvc/Controller/ItemTrait.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2020, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -57,6 +57,7 @@ trait ItemTrait * @throws ConstraintException * @throws QueryException * @throws ServiceException + * @throws SPException */ protected function getCustomFieldsForItem($moduleId, $itemId) { @@ -90,7 +91,7 @@ trait ItemTrait $customFields[] = $customField; } catch (CryptoException $e) { - logger($e->getMessage()); + throw new SPException(__u('Internal error'), SPException::ERROR); } } diff --git a/lib/SP/Services/AuthToken/AuthTokenService.php b/lib/SP/Services/AuthToken/AuthTokenService.php index 76402693..0eff9482 100644 --- a/lib/SP/Services/AuthToken/AuthTokenService.php +++ b/lib/SP/Services/AuthToken/AuthTokenService.php @@ -63,6 +63,8 @@ final class AuthTokenService extends Service const CAN_USE_SECURE_TOKEN_ACTIONS = [ ActionsInterface::ACCOUNT_VIEW, + ActionsInterface::CATEGORY_VIEW, + ActionsInterface::CLIENT_VIEW, ]; /**