From 3350ffc0b79e34c0954627ffb290ec7931c90da0 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Tue, 14 Feb 2023 12:48:42 +0200 Subject: [PATCH] system user id ref --- .../Classes/MassAction/User/MassDelete.php | 4 +- .../Classes/MassAction/User/MassUpdate.php | 4 +- application/Espo/Core/ApplicationUser.php | 6 +- .../ExtGroup/EmailGroup/ApplyTemplateType.php | 6 +- .../ExtGroup/EmailGroup/SendType.php | 14 +++-- application/Espo/Core/Loaders/Preferences.php | 13 ++-- .../Account/GroupAccount/Hooks/AfterFetch.php | 7 ++- .../Actions/MassRecalculateFormula.php | 6 +- .../Espo/Core/ORM/Repositories/RDB.php | 8 ++- .../Core/Rebuild/Actions/AddSystemUser.php | 28 ++++++--- .../Espo/Core/Repositories/Database.php | 20 +++++- application/Espo/Core/Utils/SystemUser.php | 61 +++++++++++++++++++ application/Espo/Entities/Email.php | 3 +- application/Espo/EntryPoints/Avatar.php | 4 +- application/Espo/Services/Email.php | 4 +- .../Espo/Tools/MassUpdate/MassUpdate.php | 4 +- application/Espo/Tools/Stream/Service.php | 8 ++- 17 files changed, 148 insertions(+), 52 deletions(-) create mode 100644 application/Espo/Core/Utils/SystemUser.php diff --git a/application/Espo/Classes/MassAction/User/MassDelete.php b/application/Espo/Classes/MassAction/User/MassDelete.php index c6ca174c39..166b5a261e 100644 --- a/application/Espo/Classes/MassAction/User/MassDelete.php +++ b/application/Espo/Classes/MassAction/User/MassDelete.php @@ -30,7 +30,6 @@ namespace Espo\Classes\MassAction\User; use Espo\Core\Acl; -use Espo\Core\ApplicationUser; use Espo\Core\Exceptions\BadRequest; use Espo\Core\Exceptions\Forbidden; use Espo\Core\MassAction\Actions\MassDelete as MassDeleteOriginal; @@ -41,6 +40,7 @@ use Espo\Core\MassAction\QueryBuilder; use Espo\Core\MassAction\Result; use Espo\Core\ORM\EntityManager; +use Espo\Core\Utils\SystemUser; use Espo\Entities\User; /** @@ -96,7 +96,7 @@ class MassDelete implements MassAction */ private function checkEntity(User $entity): void { - if ($entity->getUserName() === ApplicationUser::SYSTEM_USER_NAME) { + if ($entity->getUserName() === SystemUser::NAME) { throw new Forbidden("Can't delete 'system' user."); } diff --git a/application/Espo/Classes/MassAction/User/MassUpdate.php b/application/Espo/Classes/MassAction/User/MassUpdate.php index 2a3788b778..ec4d4945ed 100644 --- a/application/Espo/Classes/MassAction/User/MassUpdate.php +++ b/application/Espo/Classes/MassAction/User/MassUpdate.php @@ -29,7 +29,6 @@ namespace Espo\Classes\MassAction\User; -use Espo\Core\ApplicationUser; use Espo\Core\Exceptions\BadRequest; use Espo\Core\MassAction\Actions\MassUpdate as MassUpdateOriginal; use Espo\Core\MassAction\QueryBuilder; @@ -44,6 +43,7 @@ use Espo\Core\Acl\Table; use Espo\Core\Exceptions\Forbidden; +use Espo\Core\Utils\SystemUser; use Espo\Entities\User; use Espo\ORM\EntityManager; @@ -134,7 +134,7 @@ class MassUpdate implements MassAction */ private function checkEntity(User $entity, MassUpdateData $data): void { - if ($entity->getUserName() === ApplicationUser::SYSTEM_USER_NAME) { + if ($entity->getUserName() === SystemUser::NAME) { throw new Forbidden("Can't update 'system' user."); } diff --git a/application/Espo/Core/ApplicationUser.php b/application/Espo/Core/ApplicationUser.php index 417259772e..cffae12e3b 100644 --- a/application/Espo/Core/ApplicationUser.php +++ b/application/Espo/Core/ApplicationUser.php @@ -29,6 +29,7 @@ namespace Espo\Core; +use Espo\Core\Utils\SystemUser; use Espo\Entities\User; use Espo\Core\ORM\EntityManagerProxy; @@ -39,9 +40,8 @@ use RuntimeException; */ class ApplicationUser { - /** @deprecated As of v7.4. In the future different IDs may be used. */ + /** @deprecated As of v7.4. Different IDs may be used. Use Espo\Core\Utils\SystemUser. */ public const SYSTEM_USER_ID = 'system'; - public const SYSTEM_USER_NAME = 'system'; public function __construct( private Container $container, @@ -65,7 +65,7 @@ class ApplicationUser 'lastName', 'deleted', ]) - ->where(['userName' => self::SYSTEM_USER_NAME]) + ->where(['userName' => SystemUser::NAME]) ->findOne(); if (!$user) { diff --git a/application/Espo/Core/Formula/Functions/ExtGroup/EmailGroup/ApplyTemplateType.php b/application/Espo/Core/Formula/Functions/ExtGroup/EmailGroup/ApplyTemplateType.php index f398e7d7c9..f88cd09c59 100644 --- a/application/Espo/Core/Formula/Functions/ExtGroup/EmailGroup/ApplyTemplateType.php +++ b/application/Espo/Core/Formula/Functions/ExtGroup/EmailGroup/ApplyTemplateType.php @@ -29,7 +29,7 @@ namespace Espo\Core\Formula\Functions\ExtGroup\EmailGroup; -use Espo\Core\ApplicationUser; +use Espo\Core\Utils\SystemUser; use Espo\Entities\Email; use Espo\Core\Formula\ArgumentList; use Espo\Core\Formula\Functions\BaseFunction; @@ -142,8 +142,10 @@ class ApplyTemplateType extends BaseFunction implements ->setIsHtml($emailData->isHtml()) ->setAttachmentIdList($attachmentsIdList); + $systemUserId = $this->injectableFactory->create(SystemUser::class)->getId(); + $em->saveEntity($email, [ - 'modifiedById' => ApplicationUser::SYSTEM_USER_ID, + 'modifiedById' => $systemUserId, ]); return true; diff --git a/application/Espo/Core/Formula/Functions/ExtGroup/EmailGroup/SendType.php b/application/Espo/Core/Formula/Functions/ExtGroup/EmailGroup/SendType.php index 08775ec19b..6cfc0959c8 100644 --- a/application/Espo/Core/Formula/Functions/ExtGroup/EmailGroup/SendType.php +++ b/application/Espo/Core/Formula/Functions/ExtGroup/EmailGroup/SendType.php @@ -31,16 +31,16 @@ namespace Espo\Core\Formula\Functions\ExtGroup\EmailGroup; use Espo\Core\ApplicationUser; use Espo\Core\ORM\Repository\Option\SaveOption; +use Espo\Core\Formula\ArgumentList; +use Espo\Core\Formula\Functions\BaseFunction; +use Espo\Core\Utils\SystemUser; use Espo\Entities\Email; use Espo\Tools\Email\SendService; -use Exception; -use Espo\Core\Formula\{ - Functions\BaseFunction, - ArgumentList, -}; use Espo\Core\Di; +use Exception; + class SendType extends BaseFunction implements Di\EntityManagerAware, Di\ServiceFactoryAware, @@ -108,10 +108,12 @@ class SendType extends BaseFunction implements } } + $systemUserId = $this->injectableFactory->create(SystemUser::class)->getId(); + if ($toSave) { $em->saveEntity($email, [ SaveOption::SILENT => true, - SaveOption::MODIFIED_BY_ID => ApplicationUser::SYSTEM_USER_ID, + SaveOption::MODIFIED_BY_ID => $systemUserId, ]); } diff --git a/application/Espo/Core/Loaders/Preferences.php b/application/Espo/Core/Loaders/Preferences.php index a2313f3eb9..4f756d1740 100644 --- a/application/Espo/Core/Loaders/Preferences.php +++ b/application/Espo/Core/Loaders/Preferences.php @@ -30,26 +30,25 @@ namespace Espo\Core\Loaders; use Espo\Core\ApplicationState; -use Espo\Core\ApplicationUser as ApplicationUser; use Espo\Core\Container\Loader; use Espo\Core\ORM\EntityManager; +use Espo\Core\Utils\SystemUser; use Espo\Entities\Preferences as PreferencesEntity; class Preferences implements Loader { public function __construct( private EntityManager $entityManager, - private ApplicationState $applicationState + private ApplicationState $applicationState, + private SystemUser $systemUser ) {} public function load(): PreferencesEntity { - $id = ApplicationUser::SYSTEM_USER_ID; - - if ($this->applicationState->hasUser()) { - $id = $this->applicationState->getUser()->getId(); - } + $id = $this->applicationState->hasUser() ? + $this->applicationState->getUser()->getId() : + $this->systemUser->getId(); /** @var PreferencesEntity */ return $this->entityManager->getEntity(PreferencesEntity::ENTITY_TYPE, $id); diff --git a/application/Espo/Core/Mail/Account/GroupAccount/Hooks/AfterFetch.php b/application/Espo/Core/Mail/Account/GroupAccount/Hooks/AfterFetch.php index 5148ca1cc9..d326c4729a 100644 --- a/application/Espo/Core/Mail/Account/GroupAccount/Hooks/AfterFetch.php +++ b/application/Espo/Core/Mail/Account/GroupAccount/Hooks/AfterFetch.php @@ -29,10 +29,10 @@ namespace Espo\Core\Mail\Account\GroupAccount\Hooks; -use Espo\Core\ApplicationUser; use Espo\Core\Mail\Account\GroupAccount\AccountFactory as GroupAccountFactory; use Espo\Core\Mail\SenderParams; use Espo\Core\Templates\Entities\Person; +use Espo\Core\Utils\SystemUser; use Espo\Modules\Crm\Entities\Contact; use Espo\Modules\Crm\Entities\Lead; use Espo\Tools\Email\Util; @@ -96,7 +96,8 @@ class AfterFetch implements AfterFetchInterface RoundRobin $roundRobin, LeastBusy $leastBusy, GroupAccountFactory $groupAccountFactory, - EmailTemplateService $emailTemplateService + EmailTemplateService $emailTemplateService, + private SystemUser $systemUser ) { $this->entityManager = $entityManager; $this->streamService = $streamService; @@ -215,7 +216,7 @@ class AfterFetch implements AfterFetchInterface 'toEmailAddresses.id' => $emailAddress->getId(), 'dateSent>' => $threshold, 'status' => Email::STATUS_SENT, - 'createdById' => ApplicationUser::SYSTEM_USER_ID, + 'createdById' => $this->systemUser->getId(), ]) ->join('toEmailAddresses') ->count(); diff --git a/application/Espo/Core/MassAction/Actions/MassRecalculateFormula.php b/application/Espo/Core/MassAction/Actions/MassRecalculateFormula.php index d2db49d7d4..fa31805942 100644 --- a/application/Espo/Core/MassAction/Actions/MassRecalculateFormula.php +++ b/application/Espo/Core/MassAction/Actions/MassRecalculateFormula.php @@ -37,6 +37,7 @@ use Espo\Core\MassAction\Params; use Espo\Core\MassAction\QueryBuilder; use Espo\Core\MassAction\Result; use Espo\Core\ORM\EntityManager; +use Espo\Core\Utils\SystemUser; use Espo\Entities\User; class MassRecalculateFormula implements MassAction @@ -44,7 +45,8 @@ class MassRecalculateFormula implements MassAction public function __construct( private QueryBuilder $queryBuilder, private EntityManager $entityManager, - private User $user + private User $user, + private SystemUser $systemUser ) {} public function process(Params $params, Data $data): Result @@ -69,7 +71,7 @@ class MassRecalculateFormula implements MassAction foreach ($collection as $entity) { $this->entityManager->saveEntity($entity, [ - 'modifiedById' => ApplicationUser::SYSTEM_USER_ID, + 'modifiedById' => $this->systemUser->getId(), ]); /** @var string $id */ diff --git a/application/Espo/Core/ORM/Repositories/RDB.php b/application/Espo/Core/ORM/Repositories/RDB.php index 53309506cc..707c29ff4c 100644 --- a/application/Espo/Core/ORM/Repositories/RDB.php +++ b/application/Espo/Core/ORM/Repositories/RDB.php @@ -39,7 +39,7 @@ use Espo\Core\{ HookManager, ApplicationState, Utils\Id\RecordIdGenerator, -}; + Utils\SystemUser}; /** * @deprecated As of v6.0. Not to be extended. Extend Espo\Core\Repositories\Database, or better @@ -99,7 +99,8 @@ class RDB extends \Espo\Core\Repositories\Database implements Injectable /** @ph Metadata $metadata, HookManager $hookManager, ApplicationState $applicationState, - RecordIdGenerator $recordIdGenerator + RecordIdGenerator $recordIdGenerator, + SystemUser $systemUser ) { parent::__construct( $entityType, @@ -108,7 +109,8 @@ class RDB extends \Espo\Core\Repositories\Database implements Injectable /** @ph $metadata, $hookManager, $applicationState, - $recordIdGenerator + $recordIdGenerator, + $systemUser ); $this->init(); diff --git a/application/Espo/Core/Rebuild/Actions/AddSystemUser.php b/application/Espo/Core/Rebuild/Actions/AddSystemUser.php index 2a7972d911..c209bdd432 100644 --- a/application/Espo/Core/Rebuild/Actions/AddSystemUser.php +++ b/application/Espo/Core/Rebuild/Actions/AddSystemUser.php @@ -29,9 +29,9 @@ namespace Espo\Core\Rebuild\Actions; -use Espo\Core\ApplicationUser; use Espo\Core\Rebuild\RebuildAction; use Espo\Core\Utils\Config; +use Espo\Core\Utils\SystemUser; use Espo\Entities\User; use Espo\ORM\EntityManager; @@ -39,7 +39,8 @@ class AddSystemUser implements RebuildAction { public function __construct( private EntityManager $entityManager, - private Config $config + private Config $config, + private SystemUser $systemUser ) {} public function process(): void @@ -47,22 +48,33 @@ class AddSystemUser implements RebuildAction $repository = $this->entityManager->getRDBRepositoryByClass(User::class); $user = $repository - ->where(['userName' => ApplicationUser::SYSTEM_USER_NAME]) + ->where(['userName' => SystemUser::NAME]) ->findOne(); if ($user) { - return; - } + if ($user->getId() === $this->systemUser->getId()) { + return; + } - // @todo If a user with the 'system' ID already exists, delete it from DB. + $this->entityManager + ->getQueryExecutor() + ->execute( + $this->entityManager + ->getQueryBuilder() + ->delete() + ->from(User::ENTITY_TYPE) + ->where(['id' => $user->getId()]) + ->build() + ); + } /** @var array $attributes */ $attributes = $this->config->get('systemUserAttributes'); $user = $repository->getNew(); - $user->set('id', ApplicationUser::SYSTEM_USER_ID); - $user->set('userName', ApplicationUser::SYSTEM_USER_NAME); + $user->set('id', $this->systemUser->getId()); + $user->set('userName', SystemUser::NAME); $user->set('type', User::TYPE_SYSTEM); $user->set($attributes); diff --git a/application/Espo/Core/Repositories/Database.php b/application/Espo/Core/Repositories/Database.php index 5c1c8a0335..289dfeaa29 100644 --- a/application/Espo/Core/Repositories/Database.php +++ b/application/Espo/Core/Repositories/Database.php @@ -30,6 +30,7 @@ namespace Espo\Core\Repositories; use Espo\Core\ORM\Repository\Option\SaveOption; +use Espo\Core\Utils\SystemUser; use Espo\ORM\BaseEntity; use Espo\ORM\Entity; use Espo\ORM\Repository\RDBRepository; @@ -101,7 +102,8 @@ class Database extends RDBRepository Metadata $metadata, HookManager $hookManager, ApplicationState $applicationState, - RecordIdGenerator $recordIdGenerator + RecordIdGenerator $recordIdGenerator, + private SystemUser $systemUser ) { $this->metadata = $metadata; $this->hookManager = $hookManager; @@ -177,6 +179,11 @@ class Database extends RDBRepository if ($entity->hasAttribute('modifiedById')) { $modifiedById = $options[SaveOption::MODIFIED_BY_ID] ?? null; + if ($modifiedById === SystemUser::NAME) { + // For bc. + $modifiedById = $this->systemUser->getId(); + } + if (!$modifiedById && $this->applicationState->hasUser()) { $modifiedById = $this->applicationState->getUser()->getId(); } @@ -389,8 +396,15 @@ class Database extends RDBRepository } if ($entity->hasAttribute('createdById')) { - if (!empty($options[SaveOption::CREATED_BY_ID])) { - $entity->set('createdById', $options[SaveOption::CREATED_BY_ID]); + $createdById = $options[SaveOption::CREATED_BY_ID] ?? null; + + if ($createdById) { + if ($createdById === SystemUser::NAME) { + // For bc. + $createdById = $this->systemUser->getId(); + } + + $entity->set('createdById', $createdById); } else if ( empty($options[SaveOption::SKIP_CREATED_BY]) && diff --git a/application/Espo/Core/Utils/SystemUser.php b/application/Espo/Core/Utils/SystemUser.php new file mode 100644 index 0000000000..2bc083b590 --- /dev/null +++ b/application/Espo/Core/Utils/SystemUser.php @@ -0,0 +1,61 @@ +isUuid = $metadata->get(['app', 'recordId', 'dbType']) === 'uuid'; + } + + /** + * Get a system user ID. + */ + public function getId(): string + { + return $this->isUuid ? + self::UUID : + self::ID; + } +} diff --git a/application/Espo/Entities/Email.php b/application/Espo/Entities/Email.php index d39aec198e..16c7b52af9 100644 --- a/application/Espo/Entities/Email.php +++ b/application/Espo/Entities/Email.php @@ -178,8 +178,7 @@ class Email extends Entity return false; } - return $this->getStatus() === self::STATUS_ARCHIVED && - $this->get('createdById') !== ApplicationUser::SYSTEM_USER_ID; + return true; } /** diff --git a/application/Espo/EntryPoints/Avatar.php b/application/Espo/EntryPoints/Avatar.php index 28fe9944b8..75927dab9b 100644 --- a/application/Espo/EntryPoints/Avatar.php +++ b/application/Espo/EntryPoints/Avatar.php @@ -29,7 +29,6 @@ namespace Espo\EntryPoints; -use Espo\Core\ApplicationUser; use Espo\Core\Exceptions\BadRequest; use Espo\Core\Exceptions\Error; use Espo\Core\Api\Request; @@ -38,6 +37,7 @@ use Espo\Core\Exceptions\ForbiddenSilent; use Espo\Core\Exceptions\NotFound; use Espo\Core\Exceptions\NotFoundSilent; +use Espo\Core\Utils\SystemUser; use Espo\Entities\User; use Identicon\Identicon; @@ -139,7 +139,7 @@ class Avatar extends Image $color = $this->getColor($userId); - if ($user->getUserName() === ApplicationUser::SYSTEM_USER_NAME) { + if ($user->getUserName() === SystemUser::NAME) { $color = $this->metadata->get(['app', 'avatars', 'systemColor']) ?? $this->systemColor; } diff --git a/application/Espo/Services/Email.php b/application/Espo/Services/Email.php index a143dc9bc8..84b4c0a754 100644 --- a/application/Espo/Services/Email.php +++ b/application/Espo/Services/Email.php @@ -29,7 +29,7 @@ namespace Espo\Services; -use Espo\Core\ApplicationUser; +use Espo\Core\Utils\SystemUser; use Espo\Tools\Email\SendService; use Espo\ORM\Entity; use Espo\Entities\User; @@ -269,7 +269,7 @@ class Email extends Record return true; } - return $user->getUserName() !== ApplicationUser::SYSTEM_USER_NAME; + return $user->getUserName() !== SystemUser::NAME; } private function clearEntityForUpdate(EmailEntity $email): void diff --git a/application/Espo/Tools/MassUpdate/MassUpdate.php b/application/Espo/Tools/MassUpdate/MassUpdate.php index cf6a3ded6a..a04aebfce8 100644 --- a/application/Espo/Tools/MassUpdate/MassUpdate.php +++ b/application/Espo/Tools/MassUpdate/MassUpdate.php @@ -29,7 +29,6 @@ namespace Espo\Tools\MassUpdate; -use Espo\Core\ApplicationUser; use Espo\Core\Exceptions\BadRequest; use Espo\Core\Exceptions\Forbidden; use Espo\Core\Exceptions\NotFound; @@ -37,6 +36,7 @@ use Espo\Core\MassAction\Params; use Espo\Core\MassAction\Result; use Espo\Core\MassAction\MassActionFactory; +use Espo\Core\Utils\SystemUser; use Espo\ORM\EntityManager; use Espo\Entities\User; @@ -70,7 +70,7 @@ class MassUpdate if (!$user) { $user = $this->entityManager ->getRDBRepositoryByClass(User::class) - ->where(['userName' => ApplicationUser::SYSTEM_USER_NAME]) + ->where(['userName' => SystemUser::NAME]) ->findOne(); } diff --git a/application/Espo/Tools/Stream/Service.php b/application/Espo/Tools/Stream/Service.php index 8c392b4db4..5f22dc08ab 100644 --- a/application/Espo/Tools/Stream/Service.php +++ b/application/Espo/Tools/Stream/Service.php @@ -33,6 +33,7 @@ use Espo\Core\ApplicationUser; use Espo\Core\Exceptions\Error; use Espo\Core\Record\ServiceContainer as RecordServiceContainer; +use Espo\Core\Utils\SystemUser; use Espo\Entities\Subscription; use Espo\Modules\Crm\Entities\Account; use Espo\Repositories\EmailAddress as EmailAddressRepository; @@ -130,7 +131,8 @@ class Service FieldUtil $fieldUtil, SelectBuilderFactory $selectBuilderFactory, UserAclManagerProvider $userAclManagerProvider, - RecordServiceContainer $recordServiceContainer + RecordServiceContainer $recordServiceContainer, + private SystemUser $systemUser ) { $this->entityManager = $entityManager; $this->config = $config; @@ -212,7 +214,7 @@ class Service $userIdList = []; foreach ($sourceUserIdList as $id) { - if ($id === ApplicationUser::SYSTEM_USER_ID) { + if ($id === $this->systemUser->getId()) { continue; } @@ -292,7 +294,7 @@ class Service public function followEntity(Entity $entity, string $userId, bool $skipAclCheck = false): bool { - if ($userId === ApplicationUser::SYSTEM_USER_ID) { + if ($userId === $this->systemUser->getId()) { return false; }