email filter move to folder

This commit is contained in:
Yuri Kuznetsov
2022-10-12 18:35:43 +03:00
parent a7d3073861
commit 4e31fc89d4
18 changed files with 446 additions and 299 deletions
@@ -29,7 +29,9 @@
namespace Espo\Classes\Acl\EmailFilter;
use Espo\Entities\EmailAccount;
use Espo\Entities\User;
use Espo\Entities\EmailFilter;
use Espo\ORM\Entity;
@@ -39,41 +41,48 @@ use Espo\Core\{
};
/**
* @implements OwnershipOwnChecker<\Espo\Entities\EmailFilter>
* @implements OwnershipOwnChecker<EmailFilter>
*/
class OwnershipChecker implements OwnershipOwnChecker
{
private $entityManager;
private EntityManager $entityManager;
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
/**
* @param EmailFilter $entity
*/
public function checkOwn(User $user, Entity $entity): bool
{
if (!$entity->has('parentId') || !$entity->has('parentType')) {
if ($entity->isGlobal()) {
return false;
}
$parentType = $entity->get('parentType');
$parentId = $entity->get('parentId');
$parentType = $entity->getParentType();
$parentId = $entity->getParentId();
if (!$parentType || !$parentId) {
return false;
}
$parent = $this->entityManager->getEntity($parentType, $parentId);
$parent = $this->entityManager->getEntityById($parentType, $parentId);
if (!$parent) {
return false;
}
if ($parent->getEntityType() === 'User') {
if ($parent->getEntityType() === User::ENTITY_TYPE) {
return $parent->getId() === $user->getId();
}
if ($parent->has('assignedUserId') && $parent->get('assignedUserId') === $user->getId()) {
if (
$parent instanceof EmailAccount &&
$parent->has('assignedUserId') &&
$parent->get('assignedUserId') === $user->getId()
) {
return true;
}
+26 -5
View File
@@ -48,9 +48,12 @@ use Espo\Core\Field\DateTime as DateTimeField;
use Espo\Entities\EmailFilter;
use Espo\Entities\Email;
use Espo\Entities\InboundEmail;
use Espo\ORM\Collection;
use Espo\ORM\EntityManager;
use Espo\ORM\Query\Part\Expression;
use Espo\ORM\Query\Part\Order;
use Throwable;
use DateTime;
@@ -392,22 +395,40 @@ class Fetcher
*/
private function getFilterList(Account $account): Collection
{
/** @var Collection<EmailFilter> */
return $this->entityManager
$actionList = [EmailFilter::ACTION_SKIP];
if ($account->getEntityType() === InboundEmail::ENTITY_TYPE) {
$actionList[] = EmailFilter::ACTION_MOVE_TO_GROUP_FOLDER;
}
$builder = $this->entityManager
->getRDBRepository(EmailFilter::ENTITY_TYPE)
->where([
'action' => 'Skip',
'action' => $actionList,
'OR' => [
[
'parentType' => $account->getEntityType(),
'parentId' => $account->getId(),
'action' => $actionList,
],
[
'parentId' => null,
'action' => EmailFilter::ACTION_SKIP,
],
]
])
->find();
]);
if (count($actionList) > 1) {
$builder->order(
Order::createByPositionInList(
Expression::column('action'),
$actionList
)
);
}
/** @var Collection<EmailFilter> */
return $builder->find();
}
private function checkFetchOnlyHeader(Storage $storage, int $id): bool
+19 -2
View File
@@ -31,6 +31,7 @@ namespace Espo\Core\Mail;
use Espo\Core\Mail\Importer\DuplicateFinder;
use Espo\Entities\Email;
use Espo\Entities\EmailFilter;
use Espo\Entities\Job;
use Espo\Modules\Crm\Entities\Account;
use Espo\Modules\Crm\Entities\Contact;
@@ -181,10 +182,18 @@ class Importer
$email->setLinkMultipleColumn('users', 'folderId', $uId, $folderId);
}
if ($this->filtersMatcher->findMatch($email, $filterList, true)) {
$matchedFilter = $this->filtersMatcher->findMatch($email, $filterList, true);
if ($matchedFilter && $matchedFilter->getAction() === EmailFilter::ACTION_SKIP) {
return null;
}
if ($matchedFilter && $matchedFilter->getAction() === EmailFilter::ACTION_MOVE_TO_GROUP_FOLDER) {
$groupEmailFolderId = $matchedFilter->getGroupEmailFolderId();
$email->set('groupFolderId', $groupEmailFolderId);
}
if (
$parser->hasHeader($message, 'message-Id') &&
$parser->getHeader($message, 'message-Id')
@@ -265,9 +274,17 @@ class Importer
if (!$data->fetchOnlyHeader()) {
$inlineAttachmentList = $parser->getInlineAttachmentList($message, $email);
if ($this->filtersMatcher->findMatch($email, $filterList)) {
$matchedFilter = $this->filtersMatcher->findMatch($email, $filterList);
if ($matchedFilter && $matchedFilter->getAction() === EmailFilter::ACTION_SKIP) {
return null;
}
if ($matchedFilter && $matchedFilter->getAction() === EmailFilter::ACTION_MOVE_TO_GROUP_FOLDER) {
$groupEmailFolderId = $matchedFilter->getGroupEmailFolderId();
$email->set('groupFolderId', $groupEmailFolderId);
}
}
else {
$email->set('body', 'Not fetched. The email size exceeds the limit.');
+21
View File
@@ -35,6 +35,7 @@ class EmailFilter extends \Espo\Core\ORM\Entity
public const ACTION_SKIP = 'Skip';
public const ACTION_MOVE_TO_FOLDER = 'Move to Folder';
public const ACTION_MOVE_TO_GROUP_FOLDER = 'Move to Group Folder';
/**
* @return self::ACTION_*|null
@@ -49,6 +50,26 @@ class EmailFilter extends \Espo\Core\ORM\Entity
return $this->get('emailFolderId');
}
public function getGroupEmailFolderId(): ?string
{
return $this->get('groupEmailFolderId');
}
public function isGlobal(): bool
{
return (bool) $this->get('isGlobal');
}
public function getParentType(): ?string
{
return $this->get('parentType');
}
public function getParentId(): ?string
{
return $this->get('parentId');
}
public function getFrom(): ?string
{
return $this->get('from');
@@ -6,7 +6,12 @@
"bodyContains": "Body Contains",
"action": "Action",
"isGlobal": "Is Global",
"emailFolder": "Folder"
"emailFolder": "Folder",
"groupEmailFolder": "Group Email Folder"
},
"links": {
"emailFolder": "Folder",
"groupEmailFolder": "Group Email Folder"
},
"labels": {
"Create EmailFilter": "Create Email Filter",
@@ -15,7 +20,8 @@
"options": {
"action": {
"Skip": "Ignore",
"Move to Folder": "Put in Folder"
"Move to Folder": "Put in Folder",
"Move to Group Folder": "Put in Group Folder"
}
},
"tooltips": {
@@ -13,6 +13,9 @@
[
false, {"name": "emailFolder"}
],
[
false, {"name": "groupEmailFolder"}
],
[
{"name": "subject", "fullWidth": true}
],
@@ -21,5 +24,4 @@
]
]
}
]
]
@@ -13,6 +13,9 @@
[
{"name": "emailFolder"}
],
[
{"name": "groupEmailFolder"}
],
[
{"name": "from"}
],
@@ -27,5 +30,4 @@
]
]
}
]
]
@@ -3,4 +3,4 @@
"action",
"createdBy",
"createdAt"
]
]
@@ -1,14 +1,11 @@
{
"controller": "controllers/record",
"dynamicHandler": "handlers/email-filter",
"modalViews": {
"edit": "views/email-filter/modals/edit"
},
"recordViews": {
"list": "views/email-filter/record/list",
"detail": "views/email-filter/record/detail",
"edit": "views/email-filter/record/edit",
"editQuick": "views/email-filter/record/edit-small",
"detailQuick": "views/email-filter/record/detail-small"
"list": "views/email-filter/record/list"
},
"searchPanelDisabled": false,
"menu": {
@@ -23,5 +20,116 @@
]
}
},
"boolFilterList": ["onlyMy"]
"boolFilterList": [
"onlyMy"
],
"dynamicLogic": {
"fields": {
"parent": {
"visible": {
"conditionGroup": [
{
"attribute": "isGlobal",
"type": "isFalse"
}
]
},
"required": {
"conditionGroup": [
{
"attribute": "isGlobal",
"type": "isFalse"
}
]
}
},
"emailFolder": {
"visible": {
"conditionGroup": [
{
"attribute": "action",
"type": "equals",
"value": "Move to Folder"
}
]
},
"required": {
"conditionGroup": [
{
"attribute": "action",
"type": "equals",
"value": "Move to Folder"
}
]
}
},
"groupEmailFolder": {
"visible": {
"conditionGroup": [
{
"attribute": "action",
"type": "equals",
"value": "Move to Group Folder"
}
]
},
"required": {
"conditionGroup": [
{
"attribute": "action",
"type": "equals",
"value": "Move to Group Folder"
}
]
}
}
},
"options": {
"action": [
{
"conditionGroup": [
{
"attribute": "isGlobal",
"type": "isTrue"
}
],
"optionList": [
"Skip"
]
},
{
"conditionGroup": [
{
"attribute": "parentType",
"type": "equals",
"value": "User"
}
],
"optionList": [
"Skip",
"Move to Folder"
]
},
{
"conditionGroup": [
{
"attribute": "parentType",
"type": "equals",
"value": "InboundEmail"
}
],
"optionList": [
"Skip",
"Move to Group Folder"
]
},
{
"conditionGroup": [],
"optionList": [
"Skip"
]
}
]
}
}
}
@@ -31,7 +31,8 @@
},
"isGlobal": {
"type": "bool",
"tooltip": true
"tooltip": true,
"default": false
},
"parent": {
"type": "linkParent",
@@ -40,13 +41,20 @@
"action": {
"type": "enum",
"default": "Skip",
"options": ["Skip", "Move to Folder"],
"options": [
"Skip",
"Move to Folder",
"Move to Group Folder"
],
"view": "views/email-filter/fields/action"
},
"emailFolder": {
"type": "link",
"view": "views/email-filter/fields/email-folder"
},
"groupEmailFolder": {
"type": "link"
},
"createdAt": {
"type": "datetime",
"readOnly": true
@@ -75,11 +83,19 @@
},
"parent": {
"type": "belongsToParent",
"entityList": ["User", "EmailAccount", "InboundEmail"]
"entityList": [
"User",
"EmailAccount",
"InboundEmail"
]
},
"emailFolder": {
"type": "belongsTo",
"entity": "EmailFolder"
},
"groupEmailFolder": {
"type": "belongsTo",
"entity": "GroupEmailFolder"
}
},
"collection": {
+90 -3
View File
@@ -29,26 +29,113 @@
namespace Espo\Services;
use Espo\Entities\EmailAccount as EmailAccountEntity;
use Espo\Entities\EmailFilter as EmailFilterEntity;
use Espo\Entities\InboundEmail as InboundEmailEntity;
use Espo\Entities\User as UserEntity;
use Espo\ORM\Entity;
use Espo\Core\Exceptions\Forbidden;
use stdClass;
/**
* @extends Record<\Espo\Entities\EmailFilter>
* @extends Record<EmailFilterEntity>
*/
class EmailFilter extends Record
{
/**
* @param EmailFilterEntity $entity
* @throws Forbidden
*/
protected function beforeCreateEntity(Entity $entity, $data)
{
parent::beforeCreateEntity($entity, $data);
if (!$this->getAcl()->check($entity, 'edit')) {
// Check if own.
if (!$this->acl->checkEntityEdit($entity)) {
throw new Forbidden();
}
if ($entity->get('isGlobal')) {
$this->controlEntityValues($entity);
}
/**
* @param EmailFilterEntity $entity
* @throws Forbidden
*/
protected function beforeUpdateEntity(Entity $entity, $data)
{
parent::beforeUpdateEntity($entity, $data);
$this->controlEntityValues($entity);
}
/**
* @throws Forbidden
*/
private function controlEntityValues(EmailFilterEntity $entity): void
{
if ($entity->isGlobal()) {
$entity->set('parentId', null);
$entity->set('parentType', null);
if ($entity->getAction() !== EmailFilterEntity::ACTION_SKIP) {
throw new Forbidden("Not allowed `action`.");
}
}
if ($entity->getParentType() && !$entity->getParentId()) {
throw new Forbidden("Not allowed `parentId` value.");
}
if (
$entity->getParentType() === UserEntity::ENTITY_TYPE &&
!in_array(
$entity->getAction(),
[
EmailFilterEntity::ACTION_SKIP,
EmailFilterEntity::ACTION_MOVE_TO_FOLDER,
]
)
) {
throw new Forbidden("Not allowed `action`.");
}
if (
$entity->getParentType() === InboundEmailEntity::ENTITY_TYPE &&
!in_array(
$entity->getAction(),
[
EmailFilterEntity::ACTION_SKIP,
EmailFilterEntity::ACTION_MOVE_TO_GROUP_FOLDER,
]
)
) {
throw new Forbidden("Not allowed `action`.");
}
if (
$entity->getParentType() === EmailAccountEntity::ENTITY_TYPE &&
$entity->getAction() !== EmailFilterEntity::ACTION_SKIP
) {
throw new Forbidden("Not allowed `action`.");
}
if ($entity->getAction() !== EmailFilterEntity::ACTION_MOVE_TO_FOLDER) {
$entity->set('emailFolderId', null);
}
if ($entity->getAction() !== EmailFilterEntity::ACTION_MOVE_TO_GROUP_FOLDER) {
$entity->set('groupEmailFolderId', null);
}
}
public function filterUpdateInput(stdClass $data): void
{
parent::filterUpdateInput($data);
unset($data->isGlobal);
unset($data->parentId);
unset($data->parentType);
}
}