diff --git a/application/Espo/Controllers/I18n.php b/application/Espo/Controllers/I18n.php index 856a2530c1..de337313f6 100644 --- a/application/Espo/Controllers/I18n.php +++ b/application/Espo/Controllers/I18n.php @@ -29,20 +29,23 @@ namespace Espo\Controllers; -use Espo\Core\ServiceFactory; +use Espo\Core\{ + ServiceFactory, + Api\Request, +}; class I18n { - protected $serviceFactory; + private $serviceFactory; public function __construct(ServiceFactory $serviceFactory) { $this->serviceFactory = $serviceFactory; } - public function actionRead($params, $data, $request) + public function getActionRead(Request $request): array { - $default = $request->get('default') === 'true'; + $default = $request->getQueryParam('default') === 'true'; return $this->serviceFactory->create('Language')->getDataForFrontend($default); } diff --git a/application/Espo/Controllers/Import.php b/application/Espo/Controllers/Import.php index 58ac6139bf..9c156e94fd 100644 --- a/application/Espo/Controllers/Import.php +++ b/application/Espo/Controllers/Import.php @@ -29,86 +29,46 @@ namespace Espo\Controllers; -use Espo\Core\Utils as Utils; -use Espo\Core\Exceptions\Error; use Espo\Core\Exceptions\Forbidden; use Espo\Core\Exceptions\BadRequest; -class Import extends \Espo\Core\Controllers\Record +use Espo\Core\{ + Controllers\Record, + Api\Request, +}; + +use StdClass; + +class Import extends Record { - protected function checkControllerAccess() + protected function checkAccess(): bool { - if (!$this->getAcl()->check('Import')) { - throw new Forbidden(); - } + return $this->acl->check('Import'); } - public function beforePatch() + public function postActionUploadFile(Request $request): StdClass { - throw new BadRequest(); - } - - public function beforeUpdate() - { - throw new BadRequest(); - } - - public function beforeMassUpdate() - { - throw new BadRequest(); - } - - public function beforeCreateLink() - { - throw new BadRequest(); - } - - public function beforeRemoveLink() - { - throw new BadRequest(); - } - - protected function getFileStorageManager() - { - return $this->getContainer()->get('fileStorageManager'); - } - - protected function getEntityManager() - { - return $this->getContainer()->get('entityManager'); - } - - public function postActionUploadFile($params, $data) - { - $contents = $data; + $contents = $request->getBodyContents(); $attachmentId = $this->getService('Import')->uploadFile($contents); - return ['attachmentId' => $attachmentId]; + return (object) ['attachmentId' => $attachmentId]; } - public function actionRevert($params, $data, $request) + public function postActionRevert(Request $request): bool { - if (empty($data->id)) { - throw new BadRequest(); - } - - if (!$request->isPost()) { - throw new BadRequest(); - } + $data = $request->getParsedBody(); $this->getService('Import')->revert($data->id); return true; } - public function actionRemoveDuplicates($params, $data, $request) + public function postActionRemoveDuplicates(Request $request): bool { - if (empty($data->id)) { - throw new BadRequest(); - } + $data = $request->getParsedBody(); - if (!$request->isPost()) { + if (empty($data->id)) { throw new BadRequest(); } @@ -117,11 +77,9 @@ class Import extends \Espo\Core\Controllers\Record return true; } - public function actionCreate($params, $data, $request) + public function postActionCreate(Request $request): StdClass { - if (!$request->isPost() && !$request->isPut()) { - throw new BadRequest(); - } + $data = $request->getParsedBody(); if (!isset($data->delimiter)) { throw new BadRequest(); @@ -197,15 +155,22 @@ class Import extends \Espo\Core\Controllers\Record $attachmentId = $data->attachmentId; - if (!$this->getAcl()->check($data->entityType, 'edit')) { + if (!$this->acl->check($data->entityType, 'edit')) { throw new Forbidden(); } - return $this->getService('Import')->import($data->entityType, $data->attributeList, $attachmentId, $importParams); + return $this->getService('Import')->import( + $data->entityType, + $data->attributeList, + $attachmentId, + $importParams + ); } - public function postActionUnmarkAsDuplicate($params, $data) + public function postActionUnmarkAsDuplicate(Request $request): bool { + $data = $request->getParsedBody(); + if (empty($data->id) || empty($data->entityType) || empty($data->entityId)) { throw new BadRequest(); } @@ -214,4 +179,24 @@ class Import extends \Espo\Core\Controllers\Record return true; } + + public function beforePatch(): void + { + throw new BadRequest(); + } + + public function beforeUpdate(): void + { + throw new BadRequest(); + } + + public function beforeCreateLink(): void + { + throw new BadRequest(); + } + + public function beforeRemoveLink(): void + { + throw new BadRequest(); + } } diff --git a/application/Espo/Controllers/InboundEmail.php b/application/Espo/Controllers/InboundEmail.php index 718c8d890e..d10a5f14a0 100644 --- a/application/Espo/Controllers/InboundEmail.php +++ b/application/Espo/Controllers/InboundEmail.php @@ -29,8 +29,6 @@ namespace Espo\Controllers; -use Espo\Core\Exceptions\Forbidden; - use Espo\Core\{ Controllers\Record, Api\Request, @@ -38,13 +36,6 @@ use Espo\Core\{ class InboundEmail extends Record { - protected function checkControllerAccess() - { - if (!$this->getUser()->isAdmin()) { - throw new Forbidden(); - } - } - protected function checkAccess(): bool { return $this->getUser()->isAdmin(); diff --git a/application/Espo/Controllers/Integration.php b/application/Espo/Controllers/Integration.php index d9f6b31995..2fc7ec8884 100644 --- a/application/Espo/Controllers/Integration.php +++ b/application/Espo/Controllers/Integration.php @@ -39,28 +39,25 @@ use Espo\{ Entities\User, }; +use StdClass; + class Integration { - protected $serviceFactory; + private $serviceFactory; - protected $user; + private $user; public function __construct(ServiceFactory $serviceFactory, User $user) { $this->serviceFactory = $serviceFactory; $this->user = $user; - $this->checkControllerAccess(); - } - - protected function checkControllerAccess() - { if (!$this->user->isAdmin()) { throw new Forbidden(); } } - public function getActionRead(Request $request) + public function getActionRead(Request $request): StdClass { $entity = $this->serviceFactory ->create('Integration') @@ -69,12 +66,7 @@ class Integration return $entity->getValueMap(); } - public function putActionUpdate(Request $request) - { - return $this->patchActionPatch($request); - } - - public function patchActionPatch(Request $request) + public function putActionUpdate(Request $request): StdClass { $entity = $this->serviceFactory ->create('Integration') diff --git a/application/Espo/Controllers/Job.php b/application/Espo/Controllers/Job.php index dd9b6c343f..496f0eb470 100644 --- a/application/Espo/Controllers/Job.php +++ b/application/Espo/Controllers/Job.php @@ -31,46 +31,21 @@ namespace Espo\Controllers; use Espo\Core\Exceptions\Forbidden; -class Job extends \Espo\Core\Controllers\Record +use Espo\Core\Controllers\RecordBase; + +class Job extends RecordBase { - protected function checkControllerAccess() + protected function checkAccess(): bool { - if (!$this->getUser()->isAdmin()) { - throw new Forbidden(); - } + return $this->getUser()->isAdmin(); } - public function beforeCreate() + public function beforeCreate(): void { throw new Forbidden(); } - public function beforeUpdate() - { - throw new Forbidden(); - } - - public function beforePatch() - { - throw new Forbidden(); - } - - public function beforeListLinked() - { - throw new Forbidden(); - } - - public function beforeMassUpdate() - { - throw new Forbidden(); - } - - public function beforeCreateLink() - { - throw new Forbidden(); - } - - public function beforeRemoveLink() + public function beforeUpdate(): void { throw new Forbidden(); } diff --git a/application/Espo/Controllers/KanbanOrder.php b/application/Espo/Controllers/KanbanOrder.php index 41b9936c0a..c6aaf7453e 100644 --- a/application/Espo/Controllers/KanbanOrder.php +++ b/application/Espo/Controllers/KanbanOrder.php @@ -37,14 +37,14 @@ use Espo\Core\{ class KanbanOrder { - protected $serviceFactory; + private $serviceFactory; public function __construct(ServiceFactory $serviceFactory) { $this->serviceFactory = $serviceFactory; } - public function postActionStore(Request $request) + public function postActionStore(Request $request): bool { $data = $request->getParsedBody(); diff --git a/application/Espo/Controllers/LabelManager.php b/application/Espo/Controllers/LabelManager.php index 89f1bdd6be..6864deff6e 100644 --- a/application/Espo/Controllers/LabelManager.php +++ b/application/Espo/Controllers/LabelManager.php @@ -43,11 +43,11 @@ use Espo\{ class LabelManager { - protected $user; + private $user; - protected $dataManager; + private $dataManager; - protected $labelManagerTool; + private $labelManagerTool; public function __construct(User $user, DataManager $dataManager, LabelManagerTool $labelManagerTool) { @@ -55,11 +55,6 @@ class LabelManager $this->dataManager = $dataManager; $this->labelManagerTool = $labelManagerTool; - $this->checkControllerAccess(); - } - - protected function checkControllerAccess() - { if (!$this->user->isAdmin()) { throw new Forbidden(); } diff --git a/application/Espo/Controllers/LastViewed.php b/application/Espo/Controllers/LastViewed.php index 7102c7ab05..9797379c6a 100644 --- a/application/Espo/Controllers/LastViewed.php +++ b/application/Espo/Controllers/LastViewed.php @@ -31,18 +31,25 @@ namespace Espo\Controllers; use Espo\Core\Exceptions\Forbidden; -use Espo\Core\Controllers\Record; +use Espo\Core\{ + Controllers\Base, + Api\Request, +}; -class LastViewed extends \Espo\Core\Controllers\Base +use StdClass; + +class LastViewed extends Base { - public function getActionIndex($params, $data, $request) + private const MAX_SIZE_LIMIT = 200; + + public function getActionIndex(Request $request): StdClass { $params = []; - $params['offset'] = $request->get('offset', 0); - $params['maxSize'] = $request->get('maxSize'); + $params['offset'] = $request->getQueryParam('offset', 0); + $params['maxSize'] = $request->getQueryParam('maxSize'); - $maxSizeLimit = $this->getConfig()->get('recordListMaxSizeLimit', Record::MAX_SIZE_LIMIT); + $maxSizeLimit = $this->config->get('recordListMaxSizeLimit', self::MAX_SIZE_LIMIT); if (empty($params['maxSize'])) { $params['maxSize'] = $maxSizeLimit; diff --git a/application/Espo/Controllers/Layout.php b/application/Espo/Controllers/Layout.php index 661b327f4d..b16c4f9890 100644 --- a/application/Espo/Controllers/Layout.php +++ b/application/Espo/Controllers/Layout.php @@ -29,31 +29,39 @@ namespace Espo\Controllers; -use Espo\Core\Utils as Utils; -use Espo\Core\Exceptions\NotFound; -use Espo\Core\Exceptions\Error; use Espo\Core\Exceptions\Forbidden; use Espo\Core\Exceptions\BadRequest; -class Layout extends \Espo\Core\Controllers\Base +use Espo\Core\{ + Controllers\Base, + Api\Request, +}; + +class Layout extends Base { - public function getActionRead($params, $data) + public function getActionRead(Request $request) { + $params = $request->getRouteParams(); + $scope = $params['scope'] ?? null; $name = $params['name'] ?? null; - return $this->getServiceFactory()->create('Layout')->getForFrontend($scope, $name); + return $this->getServiceFactory() + ->create('Layout') + ->getForFrontend($scope, $name); } - public function putActionUpdate($params, $data, $request) + public function putActionUpdate(Request $request) { + $params = $request->getRouteParams(); + $data = json_decode($request->getBodyContents()); if (is_object($data)) { $data = get_object_vars($data); } - if (!$this->getUser()->isAdmin()) { + if (!$this->user->isAdmin()) { throw new Forbidden(); } @@ -61,12 +69,16 @@ class Layout extends \Espo\Core\Controllers\Base $name = $params['name'] ?? null; $setId = $params['setId'] ?? null; - return $this->getServiceFactory()->create('Layout')->update($scope, $name, $setId, $data); + return $this->getServiceFactory() + ->create('Layout') + ->update($scope, $name, $setId, $data); } - public function postActionResetToDefault($params, $data, $request) + public function postActionResetToDefault(Request $request) { - if (!$this->getUser()->isAdmin()) { + $data = $request->getParsedBody(); + + if (!$this->user->isAdmin()) { throw new Forbidden(); } @@ -79,16 +91,18 @@ class Layout extends \Espo\Core\Controllers\Base ->resetToDefault($data->scope, $data->name, $data->setId ?? null); } - public function getActionGetOriginal($params, $data, $request) + public function getActionGetOriginal(Request $request) { - if (!$this->getUser()->isAdmin()) { + if (!$this->user->isAdmin()) { throw new Forbidden(); } return $this->getServiceFactory() ->create('Layout') ->getOriginal( - $request->get('scope'), $request->get('name'), $request->get('setId') + $request->getQueryParam('scope'), + $request->getQueryParam('name'), + $request->getQueryParam('setId') ); } } diff --git a/application/Espo/Controllers/LayoutSet.php b/application/Espo/Controllers/LayoutSet.php index a454edfe20..6abe01705b 100644 --- a/application/Espo/Controllers/LayoutSet.php +++ b/application/Espo/Controllers/LayoutSet.php @@ -29,14 +29,12 @@ namespace Espo\Controllers; -use Espo\Core\Exceptions\Forbidden; +use Espo\Core\Controllers\Record; -class LayoutSet extends \Espo\Core\Controllers\Record +class LayoutSet extends Record { - protected function checkControllerAccess() + protected function checkAccess(): bool { - if (!$this->getUser()->isAdmin()) { - throw new Forbidden(); - } + return $this->getUser()->isAdmin(); } } diff --git a/application/Espo/Controllers/LeadCapture.php b/application/Espo/Controllers/LeadCapture.php index 0ecd32d149..97709ac591 100644 --- a/application/Espo/Controllers/LeadCapture.php +++ b/application/Espo/Controllers/LeadCapture.php @@ -33,10 +33,21 @@ use Espo\Core\Exceptions\Forbidden; use Espo\Core\Exceptions\BadRequest; use Espo\Core\Exceptions\NotFound; -class LeadCapture extends \Espo\Core\Controllers\Record +use Espo\Core\{ + Controllers\Record, + Api\Request, + Api\Response, +}; + +use StdClass; + +class LeadCapture extends Record { - public function postActionLeadCapture($params, $data, $request, $response) + public function postActionLeadCapture(Request $request, Response $response): bool { + $params = $request->getRouteParams(); + $data = $request->getParsedBody(); + if (empty($params['apiKey'])) { throw new BadRequest('No API key provided.'); } @@ -45,7 +56,7 @@ class LeadCapture extends \Espo\Core\Controllers\Record throw new BadRequest('No payload provided.'); } - $allowOrigin = $this->getConfig()->get('leadCaptureAllowOrigin', '*'); + $allowOrigin = $this->config->get('leadCaptureAllowOrigin', '*'); $response->setHeader('Access-Control-Allow-Origin', $allowOrigin); @@ -54,8 +65,10 @@ class LeadCapture extends \Espo\Core\Controllers\Record return true; } - public function optionsActionLeadCapture($params, $data, $request, $response) + public function optionsActionLeadCapture(Request $request, Response $response): bool { + $params = $request->getRouteParams(); + if (empty($params['apiKey'])) { throw new BadRequest('No API key provided.'); } @@ -73,21 +86,27 @@ class LeadCapture extends \Espo\Core\Controllers\Record return true; } - public function postActionGenerateNewApiKey($params, $data, $request) + public function postActionGenerateNewApiKey(Request $request): StdClass { + $data = $request->getParsedBody(); + if (empty($data->id)) { throw new BadRequest(); } - return $this->getRecordService()->generateNewApiKeyForEntity($data->id)->getValueMap(); + return $this->getRecordService() + ->generateNewApiKeyForEntity($data->id) + ->getValueMap(); } - public function getActionSmtpAccountDataList() + public function getActionSmtpAccountDataList(): array { if (!$this->getUser()->isAdmin()) { throw new Forbidden(); } - return $this->getServiceFactory()->create('LeadCapture')->getSmtpAccountDataList(); + return $this->getServiceFactory() + ->create('LeadCapture') + ->getSmtpAccountDataList(); } } diff --git a/application/Espo/Controllers/Metadata.php b/application/Espo/Controllers/Metadata.php index c9e59851ad..db82e5c730 100644 --- a/application/Espo/Controllers/Metadata.php +++ b/application/Espo/Controllers/Metadata.php @@ -31,21 +31,30 @@ namespace Espo\Controllers; use Espo\Core\Exceptions\Forbidden; -class Metadata extends \Espo\Core\Controllers\Base +use Espo\Core\{ + Controllers\Base, + Api\Request, +}; + +use StdClass; + +class Metadata extends Base { - public function actionRead($params, $data) + public function getActionRead(): StdClass { - return $this->getServiceFactory()->create('Metadata')->getDataForFrontend(); + return $this->getServiceFactory() + ->create('Metadata') + ->getDataForFrontend(); } - public function getActionGet($params, $data, $request) + public function getActionGet(Request $request) { - if (!$this->getUser()->isAdmin()) { + if (!$this->user->isAdmin()) { throw new Forbidden(); } - $key = $request->get('key'); + $key = $request->getQueryParam('key'); - return $this->getMetadata()->get($key, false); + return $this->metadata->get($key, false); } } diff --git a/application/Espo/Controllers/Note.php b/application/Espo/Controllers/Note.php index b6675adc81..c4fff3c44a 100644 --- a/application/Espo/Controllers/Note.php +++ b/application/Espo/Controllers/Note.php @@ -29,7 +29,9 @@ namespace Espo\Controllers; -class Note extends \Espo\Core\Controllers\Record +use Espo\Core\Controllers\RecordBase; + +class Note extends RecordBase { } diff --git a/application/Espo/Controllers/Notification.php b/application/Espo/Controllers/Notification.php index fb2c99b6fa..c29cbf21b3 100644 --- a/application/Espo/Controllers/Notification.php +++ b/application/Espo/Controllers/Notification.php @@ -34,6 +34,7 @@ use Espo\Core\Exceptions\Error; use Espo\Core\{ Controllers\RecordBase, Api\Request, + Api\Response, }; use StdClass; @@ -42,7 +43,7 @@ class Notification extends RecordBase { public static $defaultAction = 'list'; - public function getActionList(Request $request): StdClass + public function getActionList(Request $request, Response $response): StdClass { $userId = $this->user->id; diff --git a/application/Espo/Controllers/Pdf.php b/application/Espo/Controllers/Pdf.php index 6e8f8a5847..205f7ea912 100644 --- a/application/Espo/Controllers/Pdf.php +++ b/application/Espo/Controllers/Pdf.php @@ -31,12 +31,20 @@ namespace Espo\Controllers; use Espo\Core\Exceptions\Forbidden; use Espo\Core\Exceptions\BadRequest; -use Espo\Core\Exceptions\Error; -class Pdf extends \Espo\Core\Controllers\Base +use Espo\Core\{ + Controllers\Base, + Api\Request, +}; + +use StdClass; + +class Pdf extends Base { - public function postActionMassPrint($params, $data) + public function postActionMassPrint(Request $request): StdClass { + $data = $request->getParsedBody(); + if (empty($data->idList) || !is_array($data->idList)) { throw new BadRequest(); } @@ -49,18 +57,23 @@ class Pdf extends \Espo\Core\Controllers\Base throw new BadRequest(); } - if (!$this->getAcl()->checkScope('Template')) { + if (!$this->acl->checkScope('Template')) { throw new Forbidden(); } - if (!$this->getAcl()->checkScope($data->entityType)) { + if (!$this->acl->checkScope($data->entityType)) { throw new Forbidden(); } - return [ + return (object) [ 'id' => $this->getServiceFactory() ->create('Pdf') - ->massGenerate($data->entityType, $data->idList, $data->templateId, true) + ->massGenerate( + $data->entityType, + $data->idList, + $data->templateId, + true + ) ]; } } diff --git a/application/Espo/Controllers/PhoneNumber.php b/application/Espo/Controllers/PhoneNumber.php index bd65c99f5e..acc3021d85 100644 --- a/application/Espo/Controllers/PhoneNumber.php +++ b/application/Espo/Controllers/PhoneNumber.php @@ -29,7 +29,7 @@ namespace Espo\Controllers; -class PhoneNumber extends \Espo\Core\Controllers\Record +class PhoneNumber extends \Espo\Core\Controllers\RecordBase { } diff --git a/application/Espo/Controllers/PopupNotification.php b/application/Espo/Controllers/PopupNotification.php index a626cc6ab5..f11b36dff5 100644 --- a/application/Espo/Controllers/PopupNotification.php +++ b/application/Espo/Controllers/PopupNotification.php @@ -33,16 +33,18 @@ use Espo\Core\{ ServiceFactory, }; +use StdClass; + class PopupNotification { - protected $serviceFactory; + private $serviceFactory; public function __construct(ServiceFactory $serviceFactory) { $this->serviceFactory = $serviceFactory; } - public function getActionGrouped() + public function getActionGrouped(): StdClass { return $this->serviceFactory ->create('PopupNotification') diff --git a/application/Espo/Controllers/Portal.php b/application/Espo/Controllers/Portal.php index 95992099ad..5f1a4e9551 100644 --- a/application/Espo/Controllers/Portal.php +++ b/application/Espo/Controllers/Portal.php @@ -29,16 +29,17 @@ namespace Espo\Controllers; -use Espo\Core\Exceptions\Forbidden; +use Espo\Core\{ + Controllers\Record, + Acl\Table, +}; -class Portal extends \Espo\Core\Controllers\Record +class Portal extends Record { - protected function checkControllerAccess() + protected function checkAccess(): bool { - $portalPermission = $this->getAcl()->get('portalPermission'); + $level = $this->acl->getPermissionLevel('portal'); - if (!$portalPermission || $portalPermission === 'no') { - throw new Forbidden(); - } + return $level === Table::LEVEL_YES; } } diff --git a/application/Espo/Controllers/Preferences.php b/application/Espo/Controllers/Preferences.php index c0003a773d..5e1a1d4829 100644 --- a/application/Espo/Controllers/Preferences.php +++ b/application/Espo/Controllers/Preferences.php @@ -34,84 +34,88 @@ use Espo\Core\Exceptions\Forbidden; use Espo\Core\Exceptions\BadRequest; use Espo\Core\Exceptions\NotFound; -class Preferences extends \Espo\Core\Controllers\Base +use Espo\Core\{ + Controllers\Base, + Api\Request, + Di, +}; + +use StdClass; + +class Preferences extends Base implements + + Di\EntityManagerAware, + Di\CryptAware { - protected function getPreferences() - { - return $this->getContainer()->get('preferences'); - } + use Di\EntityManagerSetter; + use Di\CryptSetter; - protected function getEntityManager() - { - return $this->getContainer()->get('entityManager'); - } + protected $entityManager; - protected function getCrypt() - { - return $this->getContainer()->get('crypt'); - } + protected $crypt; - protected function handleUserAccess($userId) + protected function handleUserAccess(string $userId): void { - if (!$this->getUser()->isAdmin()) { - if ($this->getUser()->id != $userId) { + if (!$this->user->isAdmin()) { + if ($this->user->getId() != $userId) { throw new Forbidden(); } } } - public function actionDelete($params, $data, $request) + public function deleteActionDelete(Request $request): StdClass { + $params = $request->getRouteParams(); + $userId = $params['id']; if (empty($userId)) { throw new BadRequest(); } - if (!$request->isDelete()) { - throw new BadRequest(); - } - $this->handleUserAccess($userId); - return $this->getEntityManager()->getRepository('Preferences')->resetToDefaults($userId); + $result = $this->entityManager + ->getRepository('Preferences') + ->resetToDefaults($userId); + + if (!$result) { + throw new NotFound(); + } + + return $result; } - public function actionPatch($params, $data, $request) + public function putActionUpdate(Request $request): StdClass { - return $this->actionUpdate($params, $data, $request); - } + $params = $request->getRouteParams(); + + $data = $request->getParsedBody(); - public function actionUpdate($params, $data, $request) - { $userId = $params['id']; $this->handleUserAccess($userId); - if (!$request->isPost() && !$request->isPatch() && !$request->isPut()) { - throw new BadRequest(); - } - - if ($this->getAcl()->getLevel('Preferences', 'edit') === 'no') { + if ($this->acl->getLevel('Preferences', 'edit') === 'no') { throw new Forbidden(); } - foreach ($this->getAcl()->getScopeForbiddenAttributeList('Preferences', 'edit') as $attribute) { + foreach ($this->acl->getScopeForbiddenAttributeList('Preferences', 'edit') as $attribute) { unset($data->$attribute); } if (property_exists($data, 'smtpPassword')) { - $data->smtpPassword = $this->getCrypt()->encrypt($data->smtpPassword); + $data->smtpPassword = $this->crypt->encrypt($data->smtpPassword); } - $user = $this->getEntityManager()->getEntity('User', $userId); + $user = $this->entityManager->getEntity('User', $userId); - $entity = $this->getEntityManager()->getEntity('Preferences', $userId); + $entity = $this->entityManager->getEntity('Preferences', $userId); if ($entity && $user) { $entity->set($data); - $this->getEntityManager()->saveEntity($entity); + $this->entityManager->saveEntity($entity); $entity->set('smtpEmailAddress', $user->get('emailAddress')); $entity->set('name', $user->get('name')); @@ -124,14 +128,16 @@ class Preferences extends \Espo\Core\Controllers\Base throw new Error(); } - public function actionRead($params) + public function getActionRead(Request $request): StdClass { + $params = $request->getRouteParams(); + $userId = $params['id']; $this->handleUserAccess($userId); - $entity = $this->getEntityManager()->getEntity('Preferences', $userId); - $user = $this->getEntityManager()->getEntity('User', $userId); + $entity = $this->entityManager->getEntity('Preferences', $userId); + $user = $this->entityManager->getEntity('User', $userId); if (!$entity || !$user) { throw new NotFound(); @@ -143,15 +149,17 @@ class Preferences extends \Espo\Core\Controllers\Base $entity->clear('smtpPassword'); - foreach ($this->getAcl()->getScopeForbiddenAttributeList('Preferences', 'read') as $attribute) { + foreach ($this->acl->getScopeForbiddenAttributeList('Preferences', 'read') as $attribute) { $entity->clear($attribute); } return $entity->getValueMap(); } - public function postActionResetDashboard($params, $data) + public function postActionResetDashboard(Request $request): StdClass { + $data = $request->getParsedBody(); + if (empty($data->id)) { throw new BadRequest(); } @@ -160,8 +168,8 @@ class Preferences extends \Espo\Core\Controllers\Base $this->handleUserAccess($userId); - $user = $this->getEntityManager()->getEntity('User', $userId); - $preferences = $this->getEntityManager()->getEntity('Preferences', $userId); + $user = $this->entityManager->getEntity('User', $userId); + $preferences = $this->entityManager->getEntity('Preferences', $userId); if (!$user) { throw new NotFound(); @@ -175,25 +183,25 @@ class Preferences extends \Espo\Core\Controllers\Base throw new Forbidden(); } - if ($this->getAcl()->getLevel('Preferences', 'edit') === 'no') { + if ($this->acl->getLevel('Preferences', 'edit') === 'no') { throw new Forbidden(); } - $forbiddenAttributeList = $this->getAcl()->getScopeForbiddenAttributeList('Preferences', 'edit'); + $forbiddenAttributeList = $this->acl->getScopeForbiddenAttributeList('Preferences', 'edit'); if (in_array('dashboardLayout', $forbiddenAttributeList)) { throw new Forbidden(); } - $dashboardLayout = $this->getConfig()->get('dashboardLayout'); - $dashletsOptions = $this->getConfig()->get('dashletsOptions'); + $dashboardLayout = $this->config->get('dashboardLayout'); + $dashletsOptions = $this->config->get('dashletsOptions'); $preferences->set([ 'dashboardLayout' => $dashboardLayout, 'dashletsOptions' => $dashletsOptions, ]); - $this->getEntityManager()->saveEntity($preferences); + $this->entityManager->saveEntity($preferences); return (object) [ 'dashboardLayout' => $preferences->get('dashboardLayout'), diff --git a/application/Espo/Controllers/ScheduledJob.php b/application/Espo/Controllers/ScheduledJob.php index a57d885edc..96e70f3155 100644 --- a/application/Espo/Controllers/ScheduledJob.php +++ b/application/Espo/Controllers/ScheduledJob.php @@ -29,14 +29,12 @@ namespace Espo\Controllers; -use Espo\Core\Exceptions\Forbidden; +use Espo\Core\Controllers\Record; -class ScheduledJob extends \Espo\Core\Controllers\Record +class ScheduledJob extends Record { - protected function checkControllerAccess() + protected function checkAccess(): bool { - if (!$this->getUser()->isAdmin()) { - throw new Forbidden(); - } + return $this->user->isAdmin(); } } diff --git a/application/Espo/Controllers/ScheduledJobLogRecord.php b/application/Espo/Controllers/ScheduledJobLogRecord.php index d1da3a7c9e..ac82a47578 100644 --- a/application/Espo/Controllers/ScheduledJobLogRecord.php +++ b/application/Espo/Controllers/ScheduledJobLogRecord.php @@ -29,14 +29,10 @@ namespace Espo\Controllers; -use Espo\Core\Exceptions\Forbidden; - class ScheduledJobLogRecord extends \Espo\Core\Controllers\Record { - protected function checkControllerAccess() + protected function checkAccess(): bool { - if (!$this->getUser()->isAdmin()) { - throw new Forbidden(); - } + return $this->user->isAdmin(); } } diff --git a/application/Espo/Controllers/Settings.php b/application/Espo/Controllers/Settings.php index ace62b9b2f..4c72eb4df5 100644 --- a/application/Espo/Controllers/Settings.php +++ b/application/Espo/Controllers/Settings.php @@ -30,24 +30,27 @@ namespace Espo\Controllers; use Espo\Core\Exceptions\Forbidden; -use Espo\Core\Exceptions\BadRequest; use Espo\Core\{ Authentication\LDAP\Utils as LDAPUtils, Authentication\LDAP\Client as LDAPClient, + Controllers\Base, + Api\Request, }; -class Settings extends \Espo\Core\Controllers\Base -{ - protected function getConfigData() - { - $data = $this->getServiceFactory()->create('Settings')->getConfigData(); +use StdClass; - $data->jsLibs = $this->getMetadata()->get(['app', 'jsLibs']); +class Settings extends Base +{ + protected function getConfigData(): StdClass + { + $data = $this->serviceFactory->create('Settings')->getConfigData(); + + $data->jsLibs = $this->metadata->get(['app', 'jsLibs']); unset($data->loginView); - $loginView = $this->getMetadata()->get(['clientDefs', 'App', 'loginView']); + $loginView = $this->metadata->get(['clientDefs', 'App', 'loginView']); if ($loginView) { $data->loginView = $loginView; @@ -56,50 +59,47 @@ class Settings extends \Espo\Core\Controllers\Base return $data; } - public function actionRead($params, $data) + public function getActionRead(): StdClass { return $this->getConfigData(); } - public function actionUpdate($params, $data, $request) + public function putActionUpdate(Request $request): StdClass { - return $this->actionPatch($params, $data, $request); - } - - public function actionPatch($params, $data, $request) - { - if (!$this->getUser()->isAdmin()) { + if (!$this->user->isAdmin()) { throw new Forbidden(); } - if (!$request->isPut() && !$request->isPatch()) { - throw new BadRequest(); - } + $data = $request->getParsedBody(); - $this->getServiceFactory()->create('Settings')->setConfigData($data); + $this->serviceFactory + ->create('Settings') + ->setConfigData($data); return $this->getConfigData(); } - public function postActionTestLdapConnection($params, $data) + public function postActionTestLdapConnection(Request $request): bool { - if (!$this->getUser()->isAdmin()) { + if (!$this->user->isAdmin()) { throw new Forbidden(); } + $data = $request->getParsedBody(); + if (!isset($data->password)) { - $data->password = $this->getConfig()->get('ldapPassword'); + $data->password = $this->config->get('ldapPassword'); } - $data = get_object_vars($data); - $ldapUtils = new LDAPUtils(); - $options = $ldapUtils->normalizeOptions($data); + $options = $ldapUtils->normalizeOptions( + get_object_vars($data) + ); $ldapClient = new LDAPClient($options); - //an exception if no connection + // An exception thrown if no connection. $ldapClient->bind(); return true; diff --git a/application/Espo/Controllers/Stream.php b/application/Espo/Controllers/Stream.php index e33a35af96..ac3832f756 100644 --- a/application/Espo/Controllers/Stream.php +++ b/application/Espo/Controllers/Stream.php @@ -29,14 +29,17 @@ namespace Espo\Controllers; -use Espo\Core\Exceptions\Error; +use Espo\Core\{ + ServiceFactory, + Utils\Config, + Api\Request, +}; -use Espo\Core\ServiceFactory; -use Espo\Core\Utils\Config; +use StdClass; class Stream { - const MAX_SIZE_LIMIT = 200; + protected const MAX_SIZE_LIMIT = 200; public static $defaultAction = 'list'; @@ -50,8 +53,10 @@ class Stream $this->config = $config; } - public function actionList($params, $data, $request) + public function getActionList(Request $request): StdClass { + $params = $request->getRouteParams(); + $scope = $params['scope']; $id = isset($params['id']) ? $params['id'] : null; @@ -69,7 +74,9 @@ class Stream } if (!empty($maxSize) && $maxSize > $maxSizeLimit) { - throw new Forbidden("Max size should should not exceed " . $maxSizeLimit . ". Use offset and limit."); + throw new Forbidden( + "Max size should should not exceed " . $maxSizeLimit . ". Use offset and limit." + ); } $result = $this->serviceFactory->create('Stream')->find($scope, $id, [ @@ -86,8 +93,10 @@ class Stream ]; } - public function getActionListPosts($params, $data, $request) + public function getActionListPosts(Request $request): StdClass { + $params = $request->getRouteParams(); + $scope = $params['scope']; $id = isset($params['id']) ? $params['id'] : null; @@ -103,7 +112,9 @@ class Stream $maxSize = $maxSizeLimit; } if (!empty($maxSize) && $maxSize > $maxSizeLimit) { - throw new Forbidden("Max size should should not exceed " . $maxSizeLimit . ". Use offset and limit."); + throw new Forbidden( + "Max size should should not exceed " . $maxSizeLimit . ". Use offset and limit." + ); } $result = $this->serviceFactory->create('Stream')->find($scope, $id, [ diff --git a/application/Espo/Controllers/TemplateManager.php b/application/Espo/Controllers/TemplateManager.php index 89941f0f0b..da115c3f36 100644 --- a/application/Espo/Controllers/TemplateManager.php +++ b/application/Espo/Controllers/TemplateManager.php @@ -36,13 +36,19 @@ use Espo\Core\Utils\Metadata; use Espo\Core\Utils\TemplateFileManager; use Espo\Core\ApplicationState; +use Espo\Core\{ + Api\Request, +}; + +use StdClass; + class TemplateManager { - protected $metadata; + private $metadata; - protected $templateFileManager; + private $templateFileManager; - protected $applicationState; + private $applicationState; public function __construct( Metadata $metadata, @@ -58,18 +64,18 @@ class TemplateManager } } - public function getActionGetTemplate($params, $data, $request) + public function getActionGetTemplate(Request $request): StdClass { - $name = $request->get('name'); + $name = $request->getQueryParam('name'); if (empty($name)) { throw new BadRequest(); } - $scope = $request->get('scope'); - $module = null; + $scope = $request->getQueryParam('scope'); $module = $this->metadata->get(['app', 'templates', $name, 'module']); + $hasSubject = !$this->metadata->get(['app', 'templates', $name, 'noSubject']); $templateFileManager = $this->templateFileManager; @@ -85,8 +91,10 @@ class TemplateManager return $returnData; } - public function postActionSaveTemplate($params, $data) + public function postActionSaveTemplate(Request $request): bool { + $data = $request->getParsedBody(); + $scope = null; if (empty($data->name)) { @@ -110,8 +118,10 @@ class TemplateManager return true; } - public function postActionResetTemplate($params, $data) + public function postActionResetTemplate(Request $request): StdClass { + $data = $request->getParsedBody(); + $scope = null; if (empty($data->name)) { @@ -122,8 +132,6 @@ class TemplateManager $scope = $data->scope; } - $module = null; - $module = $this->metadata->get(['app', 'templates', $data->name, 'module']); $hasSubject = !$this->metadata->get(['app', 'templates', $data->name, 'noSubject']); diff --git a/application/Espo/Controllers/User.php b/application/Espo/Controllers/User.php index 6a09e09bf4..16b0f8f185 100644 --- a/application/Espo/Controllers/User.php +++ b/application/Espo/Controllers/User.php @@ -34,17 +34,24 @@ use Espo\Core\Exceptions\NotFound; use Espo\Core\Exceptions\Forbidden; use Espo\Core\Exceptions\BadRequest; -class User extends \Espo\Core\Controllers\Record +use Espo\Core\{ + Controllers\Record, + Api\Request, +}; + +use StdClass; + +class User extends Record { - public function actionAcl($params, $data, $request) + public function getActionAcl(Request $request): StdClass { - $userId = $request->get('id'); + $userId = $request->getQueryParam('id'); if (empty($userId)) { throw new Error(); } - if (!$this->getUser()->isAdmin() && $this->getUser()->id != $userId) { + if (!$this->user->isAdmin() && $this->user->getId() != $userId) { throw new Forbidden(); } @@ -57,20 +64,32 @@ class User extends \Espo\Core\Controllers\Record return $this->getAclManager()->getMapData($user); } - public function postActionChangeOwnPassword($params, $data, $request) + public function postActionChangeOwnPassword(Request $request): bool { - if (!property_exists($data, 'password') || !property_exists($data, 'currentPassword')) { + $data = $request->getParsedBody(); + + if ( + !property_exists($data, 'password') || + !property_exists($data, 'currentPassword') + ) { throw new BadRequest(); } $this->getService('User') - ->changePassword($this->getUser()->id, $data->password, true, $data->currentPassword); + ->changePassword( + $this->user->getId(), + $data->password, + true, + $data->currentPassword + ); return true; } - public function postActionChangePasswordByRequest($params, $data, $request) + public function postActionChangePasswordByRequest(Request $request): StdClass { + $data = $request->getParsedBody(); + if (empty($data->requestId) || empty($data->password)) { throw new BadRequest(); } @@ -78,8 +97,10 @@ class User extends \Espo\Core\Controllers\Record return $this->getService('User')->changePasswordByRequest($data->requestId, $data->password); } - public function postActionPasswordChangeRequest($params, $data, $request) + public function postActionPasswordChangeRequest(Request $request): bool { + $data = $request->getParsedBody(); + if (empty($data->userName) || empty($data->emailAddress)) { throw new BadRequest(); } @@ -93,29 +114,37 @@ class User extends \Espo\Core\Controllers\Record $url = $data->url; } - return $this->getService('User')->passwordChangeRequest($userName, $emailAddress, $url); + $this->getService('User')->passwordChangeRequest($userName, $emailAddress, $url); + + return true; } - public function postActionGenerateNewApiKey($params, $data, $request) + public function postActionGenerateNewApiKey(Request $request): StdClass { + $data = $request->getParsedBody(); + if (empty($data->id)) { throw new BadRequest(); } - if (!$this->getUser()->isAdmin()) { + if (!$this->user->isAdmin()) { throw new Forbidden(); } - return $this->getRecordService()->generateNewApiKeyForEntity($data->id)->getValueMap(); + return $this->getRecordService() + ->generateNewApiKeyForEntity($data->id) + ->getValueMap(); } - public function postActionGenerateNewPassword($params, $data, $request) + public function postActionGenerateNewPassword(Request $request): bool { + $data = $request->getParsedBody(); + if (empty($data->id)) { throw new BadRequest(); } - if (!$this->getUser()->isAdmin()) { + if (!$this->user->isAdmin()) { throw new Forbidden(); } @@ -124,16 +153,16 @@ class User extends \Espo\Core\Controllers\Record return true; } - public function beforeCreateLink() + public function beforeCreateLink(): void { - if (!$this->getUser()->isAdmin()) { + if (!$this->user->isAdmin()) { throw new Forbidden(); } } - public function beforeRemoveLink($params, $data, $request) + public function beforeRemoveLink(): void { - if (!$this->getUser()->isAdmin()) { + if (!$this->user->isAdmin()) { throw new Forbidden(); } } diff --git a/application/Espo/Controllers/UserSecurity.php b/application/Espo/Controllers/UserSecurity.php index 9f3ed77b92..2068ca8884 100644 --- a/application/Espo/Controllers/UserSecurity.php +++ b/application/Espo/Controllers/UserSecurity.php @@ -32,57 +32,70 @@ namespace Espo\Controllers; use Espo\Core\Exceptions\Forbidden; use Espo\Core\Exceptions\BadRequest; -class UserSecurity extends \Espo\Core\Controllers\Base +use Espo\Core\{ + Controllers\Base, + Api\Request, +}; + +use StdClass; + +class UserSecurity extends Base { - protected function checkControllerAccess() + protected function checkAccess(): bool { - if (!$this->getUser()->isAdmin() && !$this->getUser()->isRegular()) { - throw new Forbidden(); + if ( + !$this->user->isAdmin() && + !$this->user->isRegular() + ) { + return false; } + + return true; } - public function getActionRead($params, $data, $request) + public function getActionRead(Request $request): StdClass { - $id = $params['id'] ?? null; + $id = $request->getRouteParam('id'); if (!$id) { throw new BadRequest(); } - if (!$this->getUser()->isAdmin() && $id !== $this->getUser()->id) { + if (!$this->user->isAdmin() && $id !== $this->user->getId()) { throw new Forbidden(); } return $this->getService('UserSecurity')->read($id); } - public function postActionGenerate2FAData($params, $data) + public function postActionGenerate2FAData(Request $request): StdClass { - $data = $data ?? (object) []; + $data = $request->getParsedBody(); - $id = $data->id; + $id = $data->id ?? null; if (!$id) { throw new BadRequest(); } - if (!$this->getUser()->isAdmin() && $id !== $this->getUser()->id) { + if (!$this->user->isAdmin() && $id !== $this->user->getId()) { throw new Forbidden(); } return $this->getService('UserSecurity')->generate2FAData($id, $data); } - public function putActionUpdate($params, $data) + public function putActionUpdate(Request $request): StdClass { - $id = $params['id'] ?? null; - $data = $data ?? (object) []; + $id = $request->getRouteParam('id'); + + $data = $request->getParsedBody(); if (!$id) { throw new BadRequest(); } - if (!$this->getUser()->isAdmin() && $id !== $this->getUser()->id) { + if (!$this->user->isAdmin() && $id !== $this->user->getId()) { throw new Forbidden(); } diff --git a/application/Espo/Controllers/Webhook.php b/application/Espo/Controllers/Webhook.php index 0d303e085b..07597834dd 100644 --- a/application/Espo/Controllers/Webhook.php +++ b/application/Espo/Controllers/Webhook.php @@ -29,22 +29,30 @@ namespace Espo\Controllers; -use Espo\Core\Exceptions\Forbidden; +use Espo\Core\{ + Controllers\RecordBase, + Api\Request, + Api\Response, +}; -class Webhook extends \Espo\Core\Controllers\Record +use StdClass; + +class Webhook extends RecordBase { - protected function checkControllerAccess() + protected function checkAccess(): bool { - if (!$this->getUser()->isAdmin() && !$this->getUser()->isApi()) { - throw new Forbidden(); + if (!$this->user->isAdmin() && !$this->user->isApi()) { + return false; } + + return true; } - public function actionCreate($params, $data, $request, $response = null) + public function postActionCreate(Request $request, Response $response): StdClass { - $result = parent::actionCreate($params, $data, $request, $response); + $result = parent::postActionCreate($request, $response); - if ($response) { + if ($result) { $response->setStatus(201); } diff --git a/application/Espo/Core/Controllers/RecordBase.php b/application/Espo/Core/Controllers/RecordBase.php index 17ec9e19e0..f6e8d75de5 100644 --- a/application/Espo/Core/Controllers/RecordBase.php +++ b/application/Espo/Core/Controllers/RecordBase.php @@ -41,6 +41,7 @@ use Espo\Core\{ Record\Collection as RecordCollection, RecordServiceContainer, Api\Request, + Api\Response, Record\Crud as CrudService, Di, }; @@ -82,7 +83,7 @@ class RecordBase extends Base implements /** * Read a record. */ - public function getActionRead(Request $request): StdClass + public function getActionRead(Request $request, Response $response): StdClass { if (method_exists($this, 'actionRead')) { // For backward compatibility. @@ -103,7 +104,7 @@ class RecordBase extends Base implements /** * Create a record. */ - public function postActionCreate(Request $request): StdClass + public function postActionCreate(Request $request, Response $response): StdClass { if (method_exists($this, 'actionCreate')) { // For backward compatibility. @@ -117,15 +118,15 @@ class RecordBase extends Base implements return $entity->getValueMap(); } - public function patchActionUpdate(Request $request): StdClass + public function patchActionUpdate(Request $request, Response $response): StdClass { - return $this->putActionUpdate($request); + return $this->putActionUpdate($request, $response); } /** * Update a record. */ - public function putActionUpdate(Request $request): StdClass + public function putActionUpdate(Request $request, Response $response): StdClass { if (method_exists($this, 'actionUpdate')) { // For backward compatibility. @@ -144,7 +145,7 @@ class RecordBase extends Base implements /** * List records. */ - public function getActionList(Request $request): StdClass + public function getActionList(Request $request, Response $response): StdClass { if (method_exists($this, 'actionList')) { // For backward compatibility. @@ -198,7 +199,7 @@ class RecordBase extends Base implements /** * Delete a record. */ - public function deleteActionDelete(Request $request): bool + public function deleteActionDelete(Request $request, Response $response): bool { if (method_exists($this, 'actionDelete')) { // For backward compatibility. diff --git a/application/Espo/Repositories/Preferences.php b/application/Espo/Repositories/Preferences.php index 5ccb1f7d92..d9d76317c9 100644 --- a/application/Espo/Repositories/Preferences.php +++ b/application/Espo/Repositories/Preferences.php @@ -34,6 +34,7 @@ use Espo\ORM\Repository\Repository; use Espo\Core\Utils\Json; use PDO; +use StdClass; use Espo\Core\Di; @@ -259,7 +260,7 @@ class Preferences extends Repository implements } } - public function resetToDefaults(string $userId) + public function resetToDefaults(string $userId): ?StdClass { $this->deleteFromDb($userId); @@ -267,8 +268,12 @@ class Preferences extends Repository implements unset($this->data[$userId]); } - if ($entity = $this->get($userId)) { - return $entity->toArray(); + $entity = $this->get($userId); + + if ($entity) { + return $entity->getValueMap(); } + + return null; } } diff --git a/application/Espo/Services/Layout.php b/application/Espo/Services/Layout.php index 90fc451195..d29f38c601 100644 --- a/application/Espo/Services/Layout.php +++ b/application/Espo/Services/Layout.php @@ -31,8 +31,9 @@ namespace Espo\Services; use Espo\Core\{ Exceptions\NotFound, - Exceptions\Error, + Exceptions\Forbidden, Acl, + Acl\Exceptions\NotImplemented, Utils\Layout as LayoutUtil, ORM\EntityManager, Utils\Metadata, @@ -112,6 +113,13 @@ class Layout public function getForFrontend(string $scope, string $name) { + try { + if (!$this->acl->checkScope($scope)) { + throw new Forbidden(); + } + } + catch (NotImplemented $e) {} + $layoutSetId = null; $data = null; diff --git a/application/Espo/Services/LeadCapture.php b/application/Espo/Services/LeadCapture.php index f097429031..7857ac8aea 100644 --- a/application/Espo/Services/LeadCapture.php +++ b/application/Espo/Services/LeadCapture.php @@ -181,7 +181,7 @@ class LeadCapture extends Record return $this->createTool()->confirmOptIn($id); } - public function getSmtpAccountDataList() + public function getSmtpAccountDataList(): array { if (!$this->getUser()->isAdmin()) { throw new Forbidden(); diff --git a/application/Espo/Services/User.php b/application/Espo/Services/User.php index 1e80188ba8..013d939838 100644 --- a/application/Espo/Services/User.php +++ b/application/Espo/Services/User.php @@ -203,13 +203,11 @@ class User extends Record implements return true; } - public function passwordChangeRequest(string $userName, string $emailAddress, ?string $url = null) + public function passwordChangeRequest(string $userName, string $emailAddress, ?string $url = null): void { $recovery = $this->injectableFactory->create(Recovery::class); $recovery->request($emailAddress, $userName, $url); - - return true; } public function changePasswordByRequest(string $requestId, string $password): StdClass