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

In Phortune, use actual merchant authority (not authority grants) to control account visibility

Summary:
Depends on D20715. Ref T13366. See that task for discussion.

Replace the unreliable "grantAuthority()"-based check with an actual "can the viewer edit any merchant this account has a relationship with?" check.

This makes these objects easier to use from a policy perspective and makes it so that the `Query` alone can fully enforce permissions properly with no setup, so general infrastructure (like handles and transactions) works properly with Phortune objects.

Test Plan: Viewed merchants and accounts as users with no authority, direct authority on the account, and indirect authority via a merchant relationship.

Maniphest Tasks: T13366

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

+84 -14
+4 -3
src/applications/phortune/controller/merchant/PhortuneMerchantInvoiceCreateController.php
··· 58 58 } 59 59 60 60 if (!$target_account) { 61 - $accounts = PhortuneAccountQuery::loadAccountsForUser( 62 - $target_user, 63 - PhabricatorContentSource::newFromRequest($request)); 61 + $accounts = id(new PhortuneAccountQuery()) 62 + ->setViewer($viewer) 63 + ->withMemberPHIDs(array($target_user->getPHID())) 64 + ->execute(); 64 65 65 66 $form = id(new AphrontFormView()) 66 67 ->setUser($viewer)
+65 -4
src/applications/phortune/query/PhortuneMerchantQuery.php
··· 86 86 if ($this->ids !== null) { 87 87 $where[] = qsprintf( 88 88 $conn, 89 - 'id IN (%Ld)', 89 + 'merchant.id IN (%Ld)', 90 90 $this->ids); 91 91 } 92 92 93 93 if ($this->phids !== null) { 94 94 $where[] = qsprintf( 95 95 $conn, 96 - 'phid IN (%Ls)', 96 + 'merchant.phid IN (%Ls)', 97 97 $this->phids); 98 98 } 99 99 ··· 113 113 if ($this->memberPHIDs !== null) { 114 114 $joins[] = qsprintf( 115 115 $conn, 116 - 'LEFT JOIN %T e ON m.phid = e.src AND e.type = %d', 116 + 'LEFT JOIN %T e ON merchant.phid = e.src AND e.type = %d', 117 117 PhabricatorEdgeConfig::TABLE_NAME_EDGE, 118 118 PhortuneMerchantHasMemberEdgeType::EDGECONST); 119 119 } ··· 126 126 } 127 127 128 128 protected function getPrimaryTableAlias() { 129 - return 'm'; 129 + return 'merchant'; 130 + } 131 + 132 + public static function canViewersEditMerchants( 133 + array $viewer_phids, 134 + array $merchant_phids) { 135 + 136 + // See T13366 for some discussion. This is an unusual caching construct to 137 + // make policy filtering of Accounts easier. 138 + 139 + foreach ($viewer_phids as $key => $viewer_phid) { 140 + if (!$viewer_phid) { 141 + unset($viewer_phids[$key]); 142 + } 143 + } 144 + 145 + if (!$viewer_phids) { 146 + return array(); 147 + } 148 + 149 + $cache_key = 'phortune.merchant.can-edit'; 150 + $cache = PhabricatorCaches::getRequestCache(); 151 + 152 + $cache_data = $cache->getKey($cache_key); 153 + if (!$cache_data) { 154 + $cache_data = array(); 155 + } 156 + 157 + $load_phids = array(); 158 + foreach ($viewer_phids as $viewer_phid) { 159 + if (!isset($cache_data[$viewer_phid])) { 160 + $load_phids[] = $viewer_phid; 161 + } 162 + } 163 + 164 + $did_write = false; 165 + foreach ($load_phids as $load_phid) { 166 + $merchants = id(new self()) 167 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 168 + ->withMemberPHIDs(array($load_phid)) 169 + ->execute(); 170 + foreach ($merchants as $merchant) { 171 + $cache_data[$load_phid][$merchant->getPHID()] = true; 172 + $did_write = true; 173 + } 174 + } 175 + 176 + if ($did_write) { 177 + $cache->setKey($cache_key, $cache_data); 178 + } 179 + 180 + $results = array(); 181 + foreach ($viewer_phids as $viewer_phid) { 182 + foreach ($merchant_phids as $merchant_phid) { 183 + if (!isset($cache_data[$viewer_phid][$merchant_phid])) { 184 + continue; 185 + } 186 + $results[$viewer_phid][$merchant_phid] = true; 187 + } 188 + } 189 + 190 + return $results; 130 191 } 131 192 132 193 }
+15 -7
src/applications/phortune/storage/PhortuneAccount.php
··· 179 179 return true; 180 180 } 181 181 182 - // If the viewer is acting on behalf of a merchant, they can see 183 - // payment accounts. 182 + // See T13366. If the viewer can edit any merchant that this payment 183 + // account has a relationship with, they can see the payment account. 184 184 if ($capability == PhabricatorPolicyCapability::CAN_VIEW) { 185 - foreach ($viewer->getAuthorities() as $authority) { 186 - if ($authority instanceof PhortuneMerchant) { 187 - return true; 188 - } 185 + $viewer_phids = array($viewer->getPHID()); 186 + $merchant_phids = $this->getMerchantPHIDs(); 187 + 188 + $any_edit = PhortuneMerchantQuery::canViewersEditMerchants( 189 + $viewer_phids, 190 + $merchant_phids); 191 + 192 + if ($any_edit) { 193 + return true; 189 194 } 190 195 } 191 196 ··· 193 198 } 194 199 195 200 public function describeAutomaticCapability($capability) { 196 - return pht('Members of an account can always view and edit it.'); 201 + return array( 202 + pht('Members of an account can always view and edit it.'), 203 + pht('Merchants an account has established a relationship can view it.'), 204 + ); 197 205 } 198 206 199 207