mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-24 22:40:55 +01:00
When a change removes recipients from an object, send them one last email
Summary: Depends on D19018. Fixes T4776. Ref T13053. When you remove someone from an object's recipient list (for example, by removing them a reviewer, auditor, subscriber, owner or author) we currently do not send them mail about it because they're no longer connected to the object. In many of these cases (Commandeer, Reassign) the actual action in the UI adds them back to the object somehow (as a reviewer or subscriber, respectively) so this doesn't actually matter. However, there's no recovery mechanism for reviewer or subscriber removal. This is slightly bad from a policy/threat viewpoint since it means an attacker can remove all the recipients of an object "somewhat" silently. This isn't really silent, but it's less un-silent than it should be. It's also just not very good from a human interaction perspective: if Alice removes Bob as a reviewer, possibly "against his will", he should be notified about that. In the good case, Alice wrote a nice goodbye note that he should get to read. In the bad case, he should get a chance to correct the mistake. Also add a `removed(@user)` mail stamp so you can route these locally if you want. Test Plan: - Created and edited some different objects without catching anything broken. - Removed subscribers from tasks, saw the final email include the removed recipients with a `removed()` stamp. I'm not totally sure this doesn't have any surprising behavior or break any weird objects, but I think anything that crops up should be easy to fix. Reviewers: amckinley Subscribers: sophiebits Maniphest Tasks: T13053, T4776 Differential Revision: https://secure.phabricator.com/D19019
This commit is contained in:
parent
dbe479f0d9
commit
f214abb63f
2 changed files with 77 additions and 0 deletions
|
@ -74,6 +74,9 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
private $mustEncrypt;
|
private $mustEncrypt;
|
||||||
private $stampTemplates = array();
|
private $stampTemplates = array();
|
||||||
private $mailStamps = array();
|
private $mailStamps = array();
|
||||||
|
private $oldTo = array();
|
||||||
|
private $oldCC = array();
|
||||||
|
private $mailRemovedPHIDs = array();
|
||||||
|
|
||||||
private $transactionQueue = array();
|
private $transactionQueue = array();
|
||||||
|
|
||||||
|
@ -916,6 +919,8 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
$this->willApplyTransactions($object, $xactions);
|
$this->willApplyTransactions($object, $xactions);
|
||||||
|
|
||||||
if ($object->getID()) {
|
if ($object->getID()) {
|
||||||
|
$this->buildOldRecipientLists($object, $xactions);
|
||||||
|
|
||||||
foreach ($xactions as $xaction) {
|
foreach ($xactions as $xaction) {
|
||||||
|
|
||||||
// If any of the transactions require a read lock, hold one and
|
// If any of the transactions require a read lock, hold one and
|
||||||
|
@ -1200,6 +1205,10 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
$this->mailToPHIDs = $this->getMailTo($object);
|
$this->mailToPHIDs = $this->getMailTo($object);
|
||||||
$this->mailCCPHIDs = $this->getMailCC($object);
|
$this->mailCCPHIDs = $this->getMailCC($object);
|
||||||
|
|
||||||
|
// Add any recipients who were previously on the notification list
|
||||||
|
// but were removed by this change.
|
||||||
|
$this->applyOldRecipientLists();
|
||||||
|
|
||||||
$mail_xactions = $this->getTransactionsForMail($object, $xactions);
|
$mail_xactions = $this->getTransactionsForMail($object, $xactions);
|
||||||
$stamps = $this->newMailStamps($object, $xactions);
|
$stamps = $this->newMailStamps($object, $xactions);
|
||||||
foreach ($stamps as $stamp) {
|
foreach ($stamps as $stamp) {
|
||||||
|
@ -4127,4 +4136,65 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
return $results;
|
return $results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getRemovedRecipientPHIDs() {
|
||||||
|
return $this->mailRemovedPHIDs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildOldRecipientLists($object, $xactions) {
|
||||||
|
// See T4776. Before we start making any changes, build a list of the old
|
||||||
|
// recipients. If a change removes a user from the recipient list for an
|
||||||
|
// object we still want to notify the user about that change. This allows
|
||||||
|
// them to respond if they didn't want to be removed.
|
||||||
|
|
||||||
|
if (!$this->shouldSendMail($object, $xactions)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->oldTo = $this->getMailTo($object);
|
||||||
|
$this->oldCC = $this->getMailCC($object);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function applyOldRecipientLists() {
|
||||||
|
$actor_phid = $this->getActingAsPHID();
|
||||||
|
|
||||||
|
// If you took yourself off the recipient list (for example, by
|
||||||
|
// unsubscribing or resigning) assume that you know what you did and
|
||||||
|
// don't need to be notified.
|
||||||
|
|
||||||
|
// If you just moved from "To" to "Cc" (or vice versa), you're still a
|
||||||
|
// recipient so we don't need to add you back in.
|
||||||
|
|
||||||
|
$map = array_fuse($this->mailToPHIDs) + array_fuse($this->mailCCPHIDs);
|
||||||
|
|
||||||
|
foreach ($this->oldTo as $phid) {
|
||||||
|
if ($phid === $actor_phid) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($map[$phid])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->mailToPHIDs[] = $phid;
|
||||||
|
$this->mailRemovedPHIDs[] = $phid;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->oldCC as $phid) {
|
||||||
|
if ($phid === $actor_phid) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($map[$phid])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->mailCCPHIDs[] = $phid;
|
||||||
|
$this->mailRemovedPHIDs[] = $phid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,10 @@ final class PhabricatorEditorMailEngineExtension
|
||||||
->setKey('herald')
|
->setKey('herald')
|
||||||
->setLabel(pht('Herald Rule'));
|
->setLabel(pht('Herald Rule'));
|
||||||
|
|
||||||
|
$templates[] = id(new PhabricatorPHIDMailStamp())
|
||||||
|
->setKey('removed')
|
||||||
|
->setLabel(pht('Recipient Removed'));
|
||||||
|
|
||||||
return $templates;
|
return $templates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +73,9 @@ final class PhabricatorEditorMailEngineExtension
|
||||||
|
|
||||||
$this->getMailStamp('herald')
|
$this->getMailStamp('herald')
|
||||||
->setValue($editor->getHeraldRuleMonograms());
|
->setValue($editor->getHeraldRuleMonograms());
|
||||||
|
|
||||||
|
$this->getMailStamp('removed')
|
||||||
|
->setValue($editor->getRemovedRecipientPHIDs());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue