@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.

Raise an "Account Setup Issue" if your primary address is unverified

Summary:
Ref T12237. This adds a UI cue for users who have unverified primary addresses, since we no longer send them mail.

Also adds a new `bin/mail unverify` to unverify an address (for example, because mail is bouncing).

Test Plan:
- Unverified my address, saw setup issue.
- Verified my address, no more setup issue.

{F2861820}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T12237

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

+283
+4
src/__phutil_library_map__.php
··· 2947 2947 'PhabricatorMailManagementSendTestWorkflow' => 'applications/metamta/management/PhabricatorMailManagementSendTestWorkflow.php', 2948 2948 'PhabricatorMailManagementShowInboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementShowInboundWorkflow.php', 2949 2949 'PhabricatorMailManagementShowOutboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementShowOutboundWorkflow.php', 2950 + 'PhabricatorMailManagementUnverifyWorkflow' => 'applications/metamta/management/PhabricatorMailManagementUnverifyWorkflow.php', 2950 2951 'PhabricatorMailManagementVolumeWorkflow' => 'applications/metamta/management/PhabricatorMailManagementVolumeWorkflow.php', 2951 2952 'PhabricatorMailManagementWorkflow' => 'applications/metamta/management/PhabricatorMailManagementWorkflow.php', 2952 2953 'PhabricatorMailOutboundMailHeraldAdapter' => 'applications/metamta/herald/PhabricatorMailOutboundMailHeraldAdapter.php', ··· 3772 3773 'PhabricatorSettingsDeveloperPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsDeveloperPanelGroup.php', 3773 3774 'PhabricatorSettingsEditEngine' => 'applications/settings/editor/PhabricatorSettingsEditEngine.php', 3774 3775 'PhabricatorSettingsEmailPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsEmailPanelGroup.php', 3776 + 'PhabricatorSettingsIssueController' => 'applications/settings/controller/PhabricatorSettingsIssueController.php', 3775 3777 'PhabricatorSettingsListController' => 'applications/settings/controller/PhabricatorSettingsListController.php', 3776 3778 'PhabricatorSettingsLogsPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsLogsPanelGroup.php', 3777 3779 'PhabricatorSettingsMainController' => 'applications/settings/controller/PhabricatorSettingsMainController.php', ··· 8009 8011 'PhabricatorMailManagementSendTestWorkflow' => 'PhabricatorMailManagementWorkflow', 8010 8012 'PhabricatorMailManagementShowInboundWorkflow' => 'PhabricatorMailManagementWorkflow', 8011 8013 'PhabricatorMailManagementShowOutboundWorkflow' => 'PhabricatorMailManagementWorkflow', 8014 + 'PhabricatorMailManagementUnverifyWorkflow' => 'PhabricatorMailManagementWorkflow', 8012 8015 'PhabricatorMailManagementVolumeWorkflow' => 'PhabricatorMailManagementWorkflow', 8013 8016 'PhabricatorMailManagementWorkflow' => 'PhabricatorManagementWorkflow', 8014 8017 'PhabricatorMailOutboundMailHeraldAdapter' => 'HeraldAdapter', ··· 9021 9024 'PhabricatorSettingsDeveloperPanelGroup' => 'PhabricatorSettingsPanelGroup', 9022 9025 'PhabricatorSettingsEditEngine' => 'PhabricatorEditEngine', 9023 9026 'PhabricatorSettingsEmailPanelGroup' => 'PhabricatorSettingsPanelGroup', 9027 + 'PhabricatorSettingsIssueController' => 'PhabricatorController', 9024 9028 'PhabricatorSettingsListController' => 'PhabricatorController', 9025 9029 'PhabricatorSettingsLogsPanelGroup' => 'PhabricatorSettingsPanelGroup', 9026 9030 'PhabricatorSettingsMainController' => 'PhabricatorController',
+110
src/applications/metamta/management/PhabricatorMailManagementUnverifyWorkflow.php
··· 1 + <?php 2 + 3 + final class PhabricatorMailManagementUnverifyWorkflow 4 + extends PhabricatorMailManagementWorkflow { 5 + 6 + protected function didConstruct() { 7 + $this 8 + ->setName('unverify') 9 + ->setSynopsis( 10 + pht('Unverify an email address so it no longer receives mail.')) 11 + ->setExamples('**unverify** __address__ ...') 12 + ->setArguments( 13 + array( 14 + array( 15 + 'name' => 'addresses', 16 + 'wildcard' => true, 17 + 'help' => pht('Address (or addresses) to unverify.'), 18 + ), 19 + )); 20 + } 21 + 22 + public function execute(PhutilArgumentParser $args) { 23 + $console = PhutilConsole::getConsole(); 24 + $viewer = $this->getViewer(); 25 + 26 + $addresses = $args->getArg('addresses'); 27 + if (!$addresses) { 28 + throw new PhutilArgumentUsageException( 29 + pht('Specify one or more email addresses to unverify.')); 30 + } 31 + 32 + foreach ($addresses as $address) { 33 + $email = id(new PhabricatorUserEmail())->loadOneWhere( 34 + 'address = %s', 35 + $address); 36 + if (!$email) { 37 + echo tsprintf( 38 + "%s\n", 39 + pht( 40 + 'Address "%s" is unknown.', 41 + $address)); 42 + continue; 43 + } 44 + 45 + $user_phid = $email->getUserPHID(); 46 + 47 + $user = id(new PhabricatorPeopleQuery()) 48 + ->setViewer($viewer) 49 + ->withPHIDs(array($user_phid)) 50 + ->executeOne(); 51 + 52 + if (!$user) { 53 + echo tsprintf( 54 + "%s\n", 55 + pht( 56 + 'Address "%s" belongs to invalid user "%s".', 57 + $address, 58 + $user_phid)); 59 + continue; 60 + } 61 + 62 + if (!$email->getIsVerified()) { 63 + echo tsprintf( 64 + "%s\n", 65 + pht( 66 + 'Address "%s" (owned by "%s") is already unveriifed.', 67 + $address, 68 + $user->getUsername())); 69 + continue; 70 + } 71 + 72 + $email->openTransaction(); 73 + 74 + $email 75 + ->setIsVerified(0) 76 + ->save(); 77 + 78 + if ($email->getIsPrimary()) { 79 + $user 80 + ->setIsEmailVerified(0) 81 + ->save(); 82 + } 83 + 84 + $email->saveTransaction(); 85 + 86 + if ($email->getIsPrimary()) { 87 + echo tsprintf( 88 + "%s\n", 89 + pht( 90 + 'Unverified "%s", the primary address for "%s".', 91 + $address, 92 + $user->getUsername())); 93 + } else { 94 + echo tsprintf( 95 + "%s\n", 96 + pht( 97 + 'Unverified "%s", an address for "%s".', 98 + $address, 99 + $user->getUsername())); 100 + } 101 + } 102 + 103 + echo tsprintf( 104 + "%s\n", 105 + pht('Done.')); 106 + 107 + return 0; 108 + } 109 + 110 + }
+1
src/applications/settings/application/PhabricatorSettingsApplication.php
··· 41 41 'adjust/' => 'PhabricatorSettingsAdjustController', 42 42 'timezone/(?P<offset>[^/]+)/' 43 43 => 'PhabricatorSettingsTimezoneController', 44 + 'issue/' => 'PhabricatorSettingsIssueController', 44 45 ), 45 46 ); 46 47 }
+103
src/applications/settings/controller/PhabricatorSettingsIssueController.php
··· 1 + <?php 2 + 3 + final class PhabricatorSettingsIssueController 4 + extends PhabricatorController { 5 + 6 + public function handleRequest(AphrontRequest $request) { 7 + $viewer = $request->getViewer(); 8 + 9 + $setup_uri = id(new PhabricatorEmailAddressesSettingsPanel()) 10 + ->setViewer($viewer) 11 + ->setUser($viewer) 12 + ->getPanelURI(); 13 + 14 + $issues = array(); 15 + if (!$viewer->getIsEmailVerified()) { 16 + // We could specifically detect that the user has missed email because 17 + // their address is unverified here and point them at Mail so they can 18 + // look at messages they missed. 19 + 20 + // We could also detect that an administrator unverified their address 21 + // and let that come with a message. 22 + 23 + // For now, just make sure the unverified address does not escape notice. 24 + $issues[] = array( 25 + 'title' => pht('Primary Email Unverified'), 26 + 'summary' => pht( 27 + 'Your primary email address is unverified. You will not be able '. 28 + 'to receive email until you verify it.'), 29 + 'uri' => $setup_uri, 30 + ); 31 + } 32 + 33 + if ($issues) { 34 + require_celerity_resource('phabricator-notification-menu-css'); 35 + 36 + $items = array(); 37 + foreach ($issues as $issue) { 38 + $classes = array(); 39 + $classes[] = 'phabricator-notification'; 40 + $classes[] = 'phabricator-notification-unread'; 41 + 42 + $uri = $issue['uri']; 43 + $title = $issue['title']; 44 + $summary = $issue['summary']; 45 + 46 + $items[] = javelin_tag( 47 + 'div', 48 + array( 49 + 'class' => 50 + 'phabricator-notification phabricator-notification-unread', 51 + 'sigil' => 'notification', 52 + 'meta' => array( 53 + 'href' => $uri, 54 + ), 55 + ), 56 + array( 57 + phutil_tag('strong', array(), pht('%s:', $title)), 58 + ' ', 59 + $summary, 60 + )); 61 + } 62 + 63 + $content = phutil_tag( 64 + 'div', 65 + array( 66 + 'class' => 'setup-issue-menu', 67 + ), 68 + $items); 69 + } else { 70 + $content = phutil_tag( 71 + 'div', 72 + array( 73 + 'class' => 'phabricator-notification no-notifications', 74 + ), 75 + pht('You have no account setup issues.')); 76 + } 77 + 78 + $header = phutil_tag( 79 + 'div', 80 + array( 81 + 'class' => 'phabricator-notification-header', 82 + ), 83 + phutil_tag( 84 + 'a', 85 + array( 86 + 'href' => $setup_uri, 87 + ), 88 + pht('Account Setup Issues'))); 89 + 90 + $content = array( 91 + $header, 92 + $content, 93 + ); 94 + 95 + $json = array( 96 + 'content' => hsprintf('%s', $content), 97 + 'number' => count($issues), 98 + ); 99 + 100 + return id(new AphrontAjaxResponse())->setContent($json); 101 + } 102 + 103 + }
+65
src/view/page/menu/PhabricatorMainMenuView.php
··· 595 595 } 596 596 } 597 597 598 + $user_dropdown = null; 599 + $user_tag = null; 600 + if ($viewer->isLoggedIn()) { 601 + if (!$viewer->getIsEmailVerified()) { 602 + $bubble_id = celerity_generate_unique_node_id(); 603 + $count_id = celerity_generate_unique_node_id(); 604 + $dropdown_id = celerity_generate_unique_node_id(); 605 + 606 + $settings_uri = id(new PhabricatorEmailAddressesSettingsPanel()) 607 + ->setViewer($viewer) 608 + ->setUser($viewer) 609 + ->getPanelURI(); 610 + 611 + $user_icon = javelin_tag( 612 + 'span', 613 + array( 614 + 'class' => 'phabricator-main-menu-setup-icon phui-icon-view '. 615 + 'phui-font-fa fa-user', 616 + 'sigil' => 'menu-icon', 617 + )); 618 + 619 + $user_count = javelin_tag( 620 + 'span', 621 + array( 622 + 'class' => 'phabricator-main-menu-setup-count', 623 + 'id' => $count_id, 624 + ), 625 + 1); 626 + 627 + $user_tag = phutil_tag( 628 + 'a', 629 + array( 630 + 'href' => $settings_uri, 631 + 'class' => 'setup-unread', 632 + 'id' => $bubble_id, 633 + ), 634 + array( 635 + $user_icon, 636 + $user_count, 637 + )); 638 + 639 + Javelin::initBehavior( 640 + 'aphlict-dropdown', 641 + array( 642 + 'bubbleID' => $bubble_id, 643 + 'countID' => $count_id, 644 + 'dropdownID' => $dropdown_id, 645 + 'loadingText' => pht('Loading...'), 646 + 'uri' => '/settings/issue/', 647 + 'unreadClass' => 'setup-unread', 648 + )); 649 + 650 + $user_dropdown = javelin_tag( 651 + 'div', 652 + array( 653 + 'id' => $dropdown_id, 654 + 'class' => 'phabricator-notification-menu', 655 + 'sigil' => 'phabricator-notification-menu', 656 + 'style' => 'display: none;', 657 + )); 658 + } 659 + } 660 + 598 661 $dropdowns = array( 599 662 $notification_dropdown, 600 663 $message_notification_dropdown, 601 664 $setup_notification_dropdown, 665 + $user_dropdown, 602 666 ); 603 667 604 668 return array( ··· 606 670 $bubble_tag, 607 671 $message_tag, 608 672 $setup_tag, 673 + $user_tag, 609 674 ), 610 675 $dropdowns, 611 676 $aural,