@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Remove actor as a follower from unowned Asana subtasks after touching them

Summary: Ref T2852. Asana adds the actor as a follower when they create a task, so subtasks currently have up to two followers (the actor and the reviewer) when they should have only one (the reviewer). Simply removing the actor is an effective remedy for this because unfollowing tasks occurs with sneaky ninja stealth in Asana and doesn't generate notifications or even transaction activity.

Test Plan: Synchronized a revision without this patch, saw two followers on the subtask. Synchronized a revision after this patch, saw the "removeFollowers" fire and only one follower on the subtask, with no record of the removal in notifications or the transaction log.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2852

Differential Revision: https://secure.phabricator.com/D6700

+27 -6
+27 -6
src/applications/doorkeeper/worker/DoorkeeperFeedWorkerAsana.php
··· 194 194 array_keys($phid_aid_map)); 195 195 $try_users = array_filter($try_users); 196 196 197 - list($possessed_user, $oauth_token) = $this->findAnyValidAsanaAccessToken( 198 - $try_users); 197 + $access_info = $this->findAnyValidAsanaAccessToken($try_users); 198 + list($possessed_user, $possessed_asana_id, $oauth_token) = $access_info; 199 + 199 200 if (!$oauth_token) { 200 201 throw new PhabricatorWorkerPermanentFailureException( 201 202 'Unable to find any Asana user with valid credentials to '. ··· 425 426 } 426 427 427 428 // For each user that we don't have a subtask for, create a new subtask. 428 - 429 429 foreach ($need_subtasks as $user_phid => $is_completed) { 430 430 $subtask = $this->makeAsanaAPICall( 431 431 $oauth_token, ··· 472 472 )); 473 473 } 474 474 475 + foreach ($user_to_ref_map as $user_phid => $ref) { 476 + // For each subtask, if the acting user isn't the same user as the subtask 477 + // owner, remove the acting user as a follower. Currently, the acting user 478 + // will be added as a follower only when they create the task, but this 479 + // may change in the future (e.g., closing the task may also mark them 480 + // as a follower). Wipe every subtask to be sure. The intent here is to 481 + // leave only the owner as a follower so that the acting user doesn't 482 + // receive notifications about changes to subtask state. Note that 483 + // removing followers is silent in all cases in Asana and never produces 484 + // any kind of notification, so this isn't self-defeating. 485 + if ($user_phid != $possessed_user->getPHID()) { 486 + $this->makeAsanaAPICall( 487 + $oauth_token, 488 + 'tasks/'.$ref->getObjectID().'/removeFollowers', 489 + 'POST', 490 + array( 491 + 'followers' => array($possessed_asana_id), 492 + )); 493 + } 494 + } 495 + 475 496 // Update edges on our side. 476 497 477 498 $sub_editor->save(); ··· 527 548 528 549 private function findAnyValidAsanaAccessToken(array $user_phids) { 529 550 if (!$user_phids) { 530 - return array(null, null); 551 + return array(null, null, null); 531 552 } 532 553 533 554 $provider = $this->getProvider(); ··· 572 593 ->withPHIDs(array($account->getUserPHID())) 573 594 ->executeOne(); 574 595 if ($user) { 575 - return array($user, $token); 596 + return array($user, $account->getAccountID(), $token); 576 597 } 577 598 } 578 599 579 - return array(null, null); 600 + return array(null, null, null); 580 601 } 581 602 582 603 private function makeAsanaAPICall($token, $action, $method, array $params) {