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

Introduce CAN_EDIT for ExternalAccount, and make CAN_VIEW more liberal

Summary:
Fixes T3732. Ref T1205. Ref T3116.

External accounts (like emails used as identities, Facebook accounts, LDAP accounts, etc.) are stored in "ExternalAccount" objects.

Currently, we have a very restrictive `CAN_VIEW` policy for ExternalAccounts, to add an extra layer of protection to make sure users can't use them in unintended ways. For example, it would be bad if a user could link their Phabricator account to a Facebook account without proper authentication. All of the controllers which do sensitive things have checks anyway, but a restrictive CAN_VIEW provided an extra layer of protection. Se T3116 for some discussion.

However, this means that when grey/external users take actions (via email, or via applications like Legalpad) other users can't load the account handles and can't see anything about the actor (they just see "Restricted External Account" or similar).

Balancing these concerns is mostly about not making a huge mess while doing it. This seems like a reasonable approach:

- Add `CAN_EDIT` on these objects.
- Make that very restricted, but open up `CAN_VIEW`.
- Require `CAN_EDIT` any time we're going to do something authentication/identity related.

This is slightly easier to get wrong (forget CAN_EDIT) than other approaches, but pretty simple, and we always have extra checks in place anyway -- this is just a safety net.

I'm not quite sure how we should identify external accounts, so for now we're just rendering "Email User" or similar -- clearly not a bug, but not identifying. We can figure out what to render in the long term elsewhere.

Test Plan:
- Viewed external accounts.
- Linked an external account.
- Refreshed an external account.
- Edited profile picture.
- Viewed sessions panel.
- Published a bunch of stuff to Asana/JIRA.
- Legalpad signature page now shows external accounts.

{F171595}

Reviewers: chad, btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T3732, T1205, T3116

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

+279 -172
+167 -167
resources/celerity/map.php
··· 8 8 'names' => 9 9 array( 10 10 'core.pkg.css' => 'c2c68e64', 11 - 'core.pkg.js' => 'f8ec7ddc', 11 + 'core.pkg.js' => '2b9e8efd', 12 12 'darkconsole.pkg.js' => 'df001cab', 13 13 'differential.pkg.css' => '4a93db37', 14 14 'differential.pkg.js' => '7528cfc9', ··· 163 163 'rsrc/externals/font/fontawesome/fontawesome-webfont.woff' => 'a119ee5e', 164 164 'rsrc/externals/font/sourcesans/SourceSansPro.woff' => '3614608c', 165 165 'rsrc/externals/font/sourcesans/SourceSansProBold.woff' => 'cbf46566', 166 - 'rsrc/externals/javelin/core/Event.js' => '69815cac', 167 - 'rsrc/externals/javelin/core/Stratcom.js' => 'c293f7b9', 166 + 'rsrc/externals/javelin/core/Event.js' => '85ea0626', 167 + 'rsrc/externals/javelin/core/Stratcom.js' => '8b0ad945', 168 168 'rsrc/externals/javelin/core/__tests__/event-stop-and-kill.js' => '717554e4', 169 169 'rsrc/externals/javelin/core/__tests__/install.js' => 'c432ee85', 170 170 'rsrc/externals/javelin/core/__tests__/stratcom.js' => 'da194d4b', 171 171 'rsrc/externals/javelin/core/__tests__/util.js' => 'd3b157a9', 172 172 'rsrc/externals/javelin/core/init.js' => 'b88ab49e', 173 173 'rsrc/externals/javelin/core/init_node.js' => 'd7dde471', 174 - 'rsrc/externals/javelin/core/install.js' => '52a92793', 175 - 'rsrc/externals/javelin/core/util.js' => '65b0b249', 176 - 'rsrc/externals/javelin/docs/Base.js' => '897bb199', 177 - 'rsrc/externals/javelin/docs/onload.js' => '81fb4862', 174 + 'rsrc/externals/javelin/core/install.js' => '1ffb3a9c', 175 + 'rsrc/externals/javelin/core/util.js' => 'a23de73d', 176 + 'rsrc/externals/javelin/docs/Base.js' => '74676256', 177 + 'rsrc/externals/javelin/docs/onload.js' => 'e819c479', 178 178 'rsrc/externals/javelin/ext/fx/Color.js' => '7e41274a', 179 179 'rsrc/externals/javelin/ext/fx/FX.js' => '54b612ba', 180 180 'rsrc/externals/javelin/ext/reactor/core/DynVal.js' => 'f6555212', ··· 193 193 'rsrc/externals/javelin/ext/view/__tests__/ViewInterpreter.js' => '7a94d6a5', 194 194 'rsrc/externals/javelin/ext/view/__tests__/ViewRenderer.js' => '5426001c', 195 195 'rsrc/externals/javelin/lib/Cookie.js' => '6b3dcf44', 196 - 'rsrc/externals/javelin/lib/DOM.js' => '07d99a3d', 196 + 'rsrc/externals/javelin/lib/DOM.js' => 'c4569c05', 197 197 'rsrc/externals/javelin/lib/History.js' => 'c60f4327', 198 - 'rsrc/externals/javelin/lib/JSON.js' => '08e56a4e', 199 - 'rsrc/externals/javelin/lib/Mask.js' => 'b9f26029', 200 - 'rsrc/externals/javelin/lib/Request.js' => '7bad574b', 198 + 'rsrc/externals/javelin/lib/JSON.js' => '69adf288', 199 + 'rsrc/externals/javelin/lib/Mask.js' => '8a41885b', 200 + 'rsrc/externals/javelin/lib/Request.js' => '97258e55', 201 201 'rsrc/externals/javelin/lib/Resource.js' => '0f81f8df', 202 202 'rsrc/externals/javelin/lib/Routable.js' => 'b3e7d692', 203 203 'rsrc/externals/javelin/lib/Router.js' => '29274e2b', 204 - 'rsrc/externals/javelin/lib/URI.js' => 'd9a9b862', 205 - 'rsrc/externals/javelin/lib/Vector.js' => 'bd0aedcd', 206 - 'rsrc/externals/javelin/lib/Workflow.js' => '09b15cf1', 204 + 'rsrc/externals/javelin/lib/URI.js' => '6eff08aa', 205 + 'rsrc/externals/javelin/lib/Vector.js' => '23cbb8ac', 206 + 'rsrc/externals/javelin/lib/Workflow.js' => 'd149e002', 207 207 'rsrc/externals/javelin/lib/__tests__/Cookie.js' => '5ed109e8', 208 208 'rsrc/externals/javelin/lib/__tests__/DOM.js' => 'c984504b', 209 209 'rsrc/externals/javelin/lib/__tests__/JSON.js' => '2295d074', 210 210 'rsrc/externals/javelin/lib/__tests__/URI.js' => '003ed329', 211 211 'rsrc/externals/javelin/lib/__tests__/behavior.js' => '1ea62783', 212 - 'rsrc/externals/javelin/lib/behavior.js' => '8a3ed18b', 213 - 'rsrc/externals/javelin/lib/control/tokenizer/Tokenizer.js' => 'e7c21fb3', 214 - 'rsrc/externals/javelin/lib/control/typeahead/Typeahead.js' => 'c54eeefb', 215 - 'rsrc/externals/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js' => '5f850b5c', 216 - 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadCompositeSource.js' => '84f34ab1', 217 - 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js' => 'a79b75a4', 218 - 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js' => '66815d9c', 219 - 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js' => '62e18640', 220 - 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadStaticSource.js' => 'cdde23f1', 212 + 'rsrc/externals/javelin/lib/behavior.js' => '61cbc29a', 213 + 'rsrc/externals/javelin/lib/control/tokenizer/Tokenizer.js' => 'a5b67173', 214 + 'rsrc/externals/javelin/lib/control/typeahead/Typeahead.js' => '61f72a3d', 215 + 'rsrc/externals/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js' => 'aa93c7b0', 216 + 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadCompositeSource.js' => '503e17fd', 217 + 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js' => '8b3fd187', 218 + 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js' => '54f314a0', 219 + 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js' => '210aa43b', 220 + 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadStaticSource.js' => '316b8fa1', 221 221 'rsrc/externals/raphael/g.raphael.js' => '40dde778', 222 222 'rsrc/externals/raphael/g.raphael.line.js' => '40da039e', 223 223 'rsrc/externals/raphael/raphael.js' => '51ee6b43', ··· 415 415 'rsrc/js/application/projects/behavior-project-create.js' => '065227cc', 416 416 'rsrc/js/application/releeph/releeph-preview-branch.js' => 'b2b4fbaf', 417 417 'rsrc/js/application/releeph/releeph-request-state-change.js' => 'ab836011', 418 - 'rsrc/js/application/releeph/releeph-request-typeahead.js' => 'cd9e7094', 418 + 'rsrc/js/application/releeph/releeph-request-typeahead.js' => 'de2e896f', 419 419 'rsrc/js/application/repository/repository-crossreference.js' => 'f9539603', 420 420 'rsrc/js/application/search/behavior-reorder-queries.js' => 'e9581f08', 421 421 'rsrc/js/application/slowvote/behavior-slowvote-embed.js' => 'd6f54db0', ··· 480 480 'rsrc/js/core/behavior-reveal-content.js' => '60821bc7', 481 481 'rsrc/js/core/behavior-search-typeahead.js' => '5a376f34', 482 482 'rsrc/js/core/behavior-select-on-click.js' => '4e3e79a6', 483 - 'rsrc/js/core/behavior-toggle-class.js' => 'a82a7769', 483 + 'rsrc/js/core/behavior-toggle-class.js' => 'e566f52c', 484 484 'rsrc/js/core/behavior-tokenizer.js' => 'b3a4b884', 485 485 'rsrc/js/core/behavior-tooltip.js' => '3ee3408b', 486 486 'rsrc/js/core/behavior-watch-anchor.js' => '06e05112', ··· 541 541 'herald-test-css' => '778b008e', 542 542 'inline-comment-summary-css' => '8cfd34e8', 543 543 'javelin-aphlict' => '4a07e8e3', 544 - 'javelin-behavior' => '8a3ed18b', 544 + 'javelin-behavior' => '61cbc29a', 545 545 'javelin-behavior-aphlict-dropdown' => 'f51afce0', 546 546 'javelin-behavior-aphlict-listen' => 'a826c925', 547 547 'javelin-behavior-aphlict-status' => '58f7803f', ··· 642 642 'javelin-behavior-refresh-csrf' => '7814b593', 643 643 'javelin-behavior-releeph-preview-branch' => 'b2b4fbaf', 644 644 'javelin-behavior-releeph-request-state-change' => 'ab836011', 645 - 'javelin-behavior-releeph-request-typeahead' => 'cd9e7094', 645 + 'javelin-behavior-releeph-request-typeahead' => 'de2e896f', 646 646 'javelin-behavior-remarkup-preview' => 'f7379f45', 647 647 'javelin-behavior-reorder-applications' => '76b9fc3e', 648 648 'javelin-behavior-repository-crossreference' => 'f9539603', ··· 651 651 'javelin-behavior-slowvote-embed' => 'd6f54db0', 652 652 'javelin-behavior-stripe-payment-form' => '1693a296', 653 653 'javelin-behavior-test-payment-form' => 'ab8d2723', 654 - 'javelin-behavior-toggle-class' => 'a82a7769', 654 + 'javelin-behavior-toggle-class' => 'e566f52c', 655 655 'javelin-behavior-view-placeholder' => '2fa810fc', 656 656 'javelin-behavior-workflow' => '0a3f3021', 657 657 'javelin-color' => '7e41274a', 658 658 'javelin-cookie' => '6b3dcf44', 659 659 'javelin-diffusion-locate-file-source' => 'b42eddc7', 660 - 'javelin-dom' => '07d99a3d', 660 + 'javelin-dom' => 'c4569c05', 661 661 'javelin-dynval' => 'f6555212', 662 - 'javelin-event' => '69815cac', 662 + 'javelin-event' => '85ea0626', 663 663 'javelin-fx' => '54b612ba', 664 664 'javelin-history' => 'c60f4327', 665 - 'javelin-install' => '52a92793', 666 - 'javelin-json' => '08e56a4e', 665 + 'javelin-install' => '1ffb3a9c', 666 + 'javelin-json' => '69adf288', 667 667 'javelin-magical-init' => 'b88ab49e', 668 - 'javelin-mask' => 'b9f26029', 668 + 'javelin-mask' => '8a41885b', 669 669 'javelin-reactor' => '77b1cf6f', 670 670 'javelin-reactor-dom' => 'b6d401d6', 671 671 'javelin-reactor-node-calmer' => '76f4ebed', 672 672 'javelin-reactornode' => 'b4c30592', 673 - 'javelin-request' => '7bad574b', 673 + 'javelin-request' => '97258e55', 674 674 'javelin-resource' => '0f81f8df', 675 675 'javelin-routable' => 'b3e7d692', 676 676 'javelin-router' => '29274e2b', 677 - 'javelin-stratcom' => 'c293f7b9', 678 - 'javelin-tokenizer' => 'e7c21fb3', 679 - 'javelin-typeahead' => 'c54eeefb', 680 - 'javelin-typeahead-composite-source' => '84f34ab1', 681 - 'javelin-typeahead-normalizer' => '5f850b5c', 682 - 'javelin-typeahead-ondemand-source' => 'a79b75a4', 683 - 'javelin-typeahead-preloaded-source' => '66815d9c', 684 - 'javelin-typeahead-source' => '62e18640', 685 - 'javelin-typeahead-static-source' => 'cdde23f1', 686 - 'javelin-uri' => 'd9a9b862', 687 - 'javelin-util' => '65b0b249', 688 - 'javelin-vector' => 'bd0aedcd', 677 + 'javelin-stratcom' => '8b0ad945', 678 + 'javelin-tokenizer' => 'a5b67173', 679 + 'javelin-typeahead' => '61f72a3d', 680 + 'javelin-typeahead-composite-source' => '503e17fd', 681 + 'javelin-typeahead-normalizer' => 'aa93c7b0', 682 + 'javelin-typeahead-ondemand-source' => '8b3fd187', 683 + 'javelin-typeahead-preloaded-source' => '54f314a0', 684 + 'javelin-typeahead-source' => '210aa43b', 685 + 'javelin-typeahead-static-source' => '316b8fa1', 686 + 'javelin-uri' => '6eff08aa', 687 + 'javelin-util' => 'a23de73d', 688 + 'javelin-vector' => '23cbb8ac', 689 689 'javelin-view' => '0f764c35', 690 690 'javelin-view-html' => 'e5b406f9', 691 691 'javelin-view-interpreter' => '0c33c1a0', 692 692 'javelin-view-renderer' => '6c2b09a2', 693 693 'javelin-view-visitor' => 'efe49472', 694 - 'javelin-workflow' => '09b15cf1', 694 + 'javelin-workflow' => 'd149e002', 695 695 'lightbox-attachment-css' => '7acac05d', 696 696 'maniphest-batch-editor' => '8f380ebc', 697 697 'maniphest-report-css' => '6fc16517', ··· 872 872 4 => 'javelin-util', 873 873 5 => 'phabricator-busy', 874 874 ), 875 - '07d99a3d' => 876 - array( 877 - 0 => 'javelin-magical-init', 878 - 1 => 'javelin-install', 879 - 2 => 'javelin-util', 880 - 3 => 'javelin-vector', 881 - 4 => 'javelin-stratcom', 882 - ), 883 - '08e56a4e' => 884 - array( 885 - 0 => 'javelin-install', 886 - ), 887 - '09b15cf1' => 888 - array( 889 - 0 => 'javelin-stratcom', 890 - 1 => 'javelin-request', 891 - 2 => 'javelin-dom', 892 - 3 => 'javelin-vector', 893 - 4 => 'javelin-install', 894 - 5 => 'javelin-util', 895 - 6 => 'javelin-mask', 896 - 7 => 'javelin-uri', 897 - 8 => 'javelin-routable', 898 - ), 899 875 '0a3f3021' => 900 876 array( 901 877 0 => 'javelin-behavior', ··· 1015 991 1 => 'javelin-dom', 1016 992 2 => 'javelin-reactor-dom', 1017 993 ), 994 + '1ffb3a9c' => 995 + array( 996 + 0 => 'javelin-util', 997 + 1 => 'javelin-magical-init', 998 + ), 999 + '210aa43b' => 1000 + array( 1001 + 0 => 'javelin-install', 1002 + 1 => 'javelin-util', 1003 + 2 => 'javelin-dom', 1004 + 3 => 'javelin-typeahead-normalizer', 1005 + ), 1018 1006 '2290aeef' => 1019 1007 array( 1020 1008 0 => 'javelin-install', ··· 1028 1016 0 => 'javelin-behavior', 1029 1017 1 => 'javelin-dom', 1030 1018 2 => 'javelin-vector', 1019 + ), 1020 + '23cbb8ac' => 1021 + array( 1022 + 0 => 'javelin-install', 1023 + 1 => 'javelin-event', 1031 1024 ), 1032 1025 '2926fff2' => 1033 1026 array( ··· 1062 1055 1 => 'javelin-dom', 1063 1056 2 => 'javelin-view-renderer', 1064 1057 3 => 'javelin-install', 1058 + ), 1059 + '316b8fa1' => 1060 + array( 1061 + 0 => 'javelin-install', 1062 + 1 => 'javelin-typeahead-source', 1065 1063 ), 1066 1064 '357b6e9b' => 1067 1065 array( ··· 1225 1223 1 => 'javelin-stratcom', 1226 1224 2 => 'javelin-dom', 1227 1225 ), 1226 + '503e17fd' => 1227 + array( 1228 + 0 => 'javelin-install', 1229 + 1 => 'javelin-typeahead-source', 1230 + 2 => 'javelin-util', 1231 + ), 1228 1232 '519705ea' => 1229 1233 array( 1230 1234 0 => 'javelin-install', 1231 1235 1 => 'javelin-dom', 1232 1236 2 => 'javelin-reactor-dom', 1233 1237 ), 1234 - '52a92793' => 1235 - array( 1236 - 0 => 'javelin-util', 1237 - 1 => 'javelin-magical-init', 1238 - ), 1239 1238 '54b612ba' => 1240 1239 array( 1241 1240 0 => 'javelin-color', 1242 1241 1 => 'javelin-install', 1243 1242 2 => 'javelin-util', 1244 1243 ), 1244 + '54f314a0' => 1245 + array( 1246 + 0 => 'javelin-install', 1247 + 1 => 'javelin-util', 1248 + 2 => 'javelin-request', 1249 + 3 => 'javelin-typeahead-source', 1250 + ), 1245 1251 '558829c2' => 1246 1252 array( 1247 1253 0 => 'javelin-stratcom', ··· 1288 1294 0 => 'javelin-behavior', 1289 1295 1 => 'javelin-stratcom', 1290 1296 ), 1291 - '5f850b5c' => 1292 - array( 1293 - 0 => 'javelin-install', 1294 - ), 1295 1297 '5fefb143' => 1296 1298 array( 1297 1299 0 => 'javelin-behavior', ··· 1312 1314 2 => 'javelin-dom', 1313 1315 3 => 'javelin-workflow', 1314 1316 ), 1315 - '62e18640' => 1317 + '61cbc29a' => 1316 1318 array( 1317 - 0 => 'javelin-install', 1319 + 0 => 'javelin-magical-init', 1318 1320 1 => 'javelin-util', 1319 - 2 => 'javelin-dom', 1320 - 3 => 'javelin-typeahead-normalizer', 1321 1321 ), 1322 - '6453c869' => 1322 + '61f72a3d' => 1323 1323 array( 1324 1324 0 => 'javelin-install', 1325 1325 1 => 'javelin-dom', 1326 - 2 => 'javelin-fx', 1326 + 2 => 'javelin-vector', 1327 + 3 => 'javelin-util', 1327 1328 ), 1328 - '66815d9c' => 1329 + '6453c869' => 1329 1330 array( 1330 1331 0 => 'javelin-install', 1331 - 1 => 'javelin-util', 1332 - 2 => 'javelin-request', 1333 - 3 => 'javelin-typeahead-source', 1332 + 1 => 'javelin-dom', 1333 + 2 => 'javelin-fx', 1334 1334 ), 1335 - '69815cac' => 1335 + '69adf288' => 1336 1336 array( 1337 1337 0 => 'javelin-install', 1338 1338 ), ··· 1359 1359 0 => 'javelin-install', 1360 1360 1 => 'javelin-dom', 1361 1361 2 => 'javelin-util', 1362 + ), 1363 + '6eff08aa' => 1364 + array( 1365 + 0 => 'javelin-install', 1366 + 1 => 'javelin-util', 1367 + 2 => 'javelin-stratcom', 1362 1368 ), 1363 1369 '710f209e' => 1364 1370 array( ··· 1433 1439 2 => 'javelin-stratcom', 1434 1440 3 => 'javelin-util', 1435 1441 ), 1436 - '7bad574b' => 1437 - array( 1438 - 0 => 'javelin-install', 1439 - 1 => 'javelin-stratcom', 1440 - 2 => 'javelin-util', 1441 - 3 => 'javelin-behavior', 1442 - 4 => 'javelin-json', 1443 - 5 => 'javelin-dom', 1444 - 6 => 'javelin-resource', 1445 - 7 => 'javelin-routable', 1446 - ), 1447 1442 '7c273581' => 1448 1443 array( 1449 1444 0 => 'javelin-behavior', ··· 1491 1486 3 => 'javelin-workflow', 1492 1487 4 => 'phabricator-draggable-list', 1493 1488 ), 1494 - '84f34ab1' => 1495 - array( 1496 - 0 => 'javelin-install', 1497 - 1 => 'javelin-typeahead-source', 1498 - 2 => 'javelin-util', 1499 - ), 1500 1489 '85ab3c8e' => 1501 1490 array( 1502 1491 0 => 'javelin-behavior', ··· 1504 1493 2 => 'javelin-util', 1505 1494 3 => 'javelin-workflow', 1506 1495 4 => 'javelin-stratcom', 1496 + ), 1497 + '85ea0626' => 1498 + array( 1499 + 0 => 'javelin-install', 1507 1500 ), 1508 1501 '880fa5ac' => 1509 1502 array( ··· 1524 1517 3 => 'javelin-view-interpreter', 1525 1518 4 => 'javelin-view-renderer', 1526 1519 ), 1527 - '8a3ed18b' => 1520 + '8a41885b' => 1521 + array( 1522 + 0 => 'javelin-install', 1523 + 1 => 'javelin-dom', 1524 + ), 1525 + '8b0ad945' => 1528 1526 array( 1529 - 0 => 'javelin-magical-init', 1527 + 0 => 'javelin-install', 1528 + 1 => 'javelin-event', 1529 + 2 => 'javelin-util', 1530 + 3 => 'javelin-magical-init', 1531 + ), 1532 + '8b3fd187' => 1533 + array( 1534 + 0 => 'javelin-install', 1530 1535 1 => 'javelin-util', 1536 + 2 => 'javelin-request', 1537 + 3 => 'javelin-typeahead-source', 1531 1538 ), 1532 1539 '8d199d97' => 1533 1540 array( ··· 1575 1582 3 => 'javelin-workflow', 1576 1583 4 => 'javelin-util', 1577 1584 ), 1585 + '97258e55' => 1586 + array( 1587 + 0 => 'javelin-install', 1588 + 1 => 'javelin-stratcom', 1589 + 2 => 'javelin-util', 1590 + 3 => 'javelin-behavior', 1591 + 4 => 'javelin-json', 1592 + 5 => 'javelin-dom', 1593 + 6 => 'javelin-resource', 1594 + 7 => 'javelin-routable', 1595 + ), 1578 1596 '988040b4' => 1579 1597 array( 1580 1598 0 => 'javelin-install', ··· 1631 1649 3 => 'javelin-stratcom', 1632 1650 4 => 'javelin-vector', 1633 1651 ), 1634 - 'a5d7cf86' => 1652 + 'a5b67173' => 1635 1653 array( 1636 1654 0 => 'javelin-dom', 1655 + 1 => 'javelin-util', 1656 + 2 => 'javelin-stratcom', 1657 + 3 => 'javelin-install', 1637 1658 ), 1638 - 'a79b75a4' => 1659 + 'a5d7cf86' => 1639 1660 array( 1640 - 0 => 'javelin-install', 1641 - 1 => 'javelin-util', 1642 - 2 => 'javelin-request', 1643 - 3 => 'javelin-typeahead-source', 1661 + 0 => 'javelin-dom', 1644 1662 ), 1645 1663 'a80d0378' => 1646 1664 array( ··· 1661 1679 8 => 'javelin-util', 1662 1680 9 => 'phabricator-notification', 1663 1681 ), 1664 - 'a82a7769' => 1665 - array( 1666 - 0 => 'javelin-behavior', 1667 - 1 => 'javelin-stratcom', 1668 - 2 => 'javelin-dom', 1669 - ), 1670 1682 'a8d8459d' => 1671 1683 array( 1672 1684 0 => 'javelin-behavior', ··· 1696 1708 3 => 'javelin-dom', 1697 1709 4 => 'javelin-util', 1698 1710 5 => 'phabricator-prefab', 1711 + ), 1712 + 'aa93c7b0' => 1713 + array( 1714 + 0 => 'javelin-install', 1699 1715 ), 1700 1716 'ab836011' => 1701 1717 array( ··· 1782 1798 3 => 'javelin-dom', 1783 1799 4 => 'phabricator-draggable-list', 1784 1800 ), 1785 - 'b9f26029' => 1786 - array( 1787 - 0 => 'javelin-install', 1788 - 1 => 'javelin-dom', 1789 - ), 1790 1801 'bba9eedf' => 1791 1802 array( 1792 1803 0 => 'javelin-behavior', 1793 1804 1 => 'javelin-stratcom', 1794 1805 2 => 'javelin-dom', 1795 - ), 1796 - 'bd0aedcd' => 1797 - array( 1798 - 0 => 'javelin-install', 1799 - 1 => 'javelin-event', 1800 1806 ), 1801 1807 'bd4c8dca' => 1802 1808 array( ··· 1828 1834 2 => 'javelin-util', 1829 1835 3 => 'phabricator-shaped-request', 1830 1836 ), 1831 - 'c293f7b9' => 1837 + 'c4569c05' => 1832 1838 array( 1833 - 0 => 'javelin-install', 1834 - 1 => 'javelin-event', 1839 + 0 => 'javelin-magical-init', 1840 + 1 => 'javelin-install', 1835 1841 2 => 'javelin-util', 1836 - 3 => 'javelin-magical-init', 1837 - ), 1838 - 'c54eeefb' => 1839 - array( 1840 - 0 => 'javelin-install', 1841 - 1 => 'javelin-dom', 1842 - 2 => 'javelin-vector', 1843 - 3 => 'javelin-util', 1842 + 3 => 'javelin-vector', 1843 + 4 => 'javelin-stratcom', 1844 1844 ), 1845 1845 'c60f4327' => 1846 1846 array( ··· 1856 1856 2 => 'javelin-stratcom', 1857 1857 3 => 'phabricator-phtize', 1858 1858 ), 1859 - 'cd9e7094' => 1859 + 'd149e002' => 1860 1860 array( 1861 - 0 => 'javelin-behavior', 1862 - 1 => 'javelin-dom', 1863 - 2 => 'javelin-typeahead', 1864 - 3 => 'javelin-typeahead-ondemand-source', 1865 - 4 => 'javelin-dom', 1866 - ), 1867 - 'cdde23f1' => 1868 - array( 1869 - 0 => 'javelin-install', 1870 - 1 => 'javelin-typeahead-source', 1861 + 0 => 'javelin-stratcom', 1862 + 1 => 'javelin-request', 1863 + 2 => 'javelin-dom', 1864 + 3 => 'javelin-vector', 1865 + 4 => 'javelin-install', 1866 + 5 => 'javelin-util', 1867 + 6 => 'javelin-mask', 1868 + 7 => 'javelin-uri', 1869 + 8 => 'javelin-routable', 1871 1870 ), 1872 1871 'd19198c8' => 1873 1872 array( ··· 1926 1925 2 => 'javelin-util', 1927 1926 3 => 'phabricator-shaped-request', 1928 1927 ), 1929 - 'd9a9b862' => 1930 - array( 1931 - 0 => 'javelin-install', 1932 - 1 => 'javelin-util', 1933 - 2 => 'javelin-stratcom', 1934 - ), 1935 1928 'dd7e8ef5' => 1936 1929 array( 1937 1930 0 => 'javelin-behavior', ··· 1940 1933 3 => 'javelin-util', 1941 1934 4 => 'javelin-stratcom', 1942 1935 ), 1936 + 'de2e896f' => 1937 + array( 1938 + 0 => 'javelin-behavior', 1939 + 1 => 'javelin-dom', 1940 + 2 => 'javelin-typeahead', 1941 + 3 => 'javelin-typeahead-ondemand-source', 1942 + 4 => 'javelin-dom', 1943 + ), 1943 1944 'e10f8e18' => 1944 1945 array( 1945 1946 0 => 'javelin-behavior', ··· 1970 1971 3 => 'javelin-dom', 1971 1972 4 => 'javelin-uri', 1972 1973 ), 1974 + 'e566f52c' => 1975 + array( 1976 + 0 => 'javelin-behavior', 1977 + 1 => 'javelin-stratcom', 1978 + 2 => 'javelin-dom', 1979 + ), 1973 1980 'e5822781' => 1974 1981 array( 1975 1982 0 => 'javelin-behavior', ··· 1984 1991 1 => 'javelin-dom', 1985 1992 2 => 'javelin-view-visitor', 1986 1993 3 => 'javelin-util', 1987 - ), 1988 - 'e7c21fb3' => 1989 - array( 1990 - 0 => 'javelin-dom', 1991 - 1 => 'javelin-util', 1992 - 2 => 'javelin-stratcom', 1993 - 3 => 'javelin-install', 1994 1994 ), 1995 1995 'e9581f08' => 1996 1996 array(
+8 -1
src/applications/auth/controller/PhabricatorAuthController.php
··· 143 143 // be logged in yet, and because we want to tailor an error message to 144 144 // distinguish between "not usable" and "does not exist". We do explicit 145 145 // checks later on to make sure this account is valid for the intended 146 - // operation. 146 + // operation. This requires edit permission for completeness and consistency 147 + // but it won't actually be meaningfully checked because we're using the 148 + // ominpotent user. 147 149 148 150 $account = id(new PhabricatorExternalAccountQuery()) 149 151 ->setViewer(PhabricatorUser::getOmnipotentUser()) 150 152 ->withAccountSecrets(array($account_key)) 151 153 ->needImages(true) 154 + ->requireCapabilities( 155 + array( 156 + PhabricatorPolicyCapability::CAN_VIEW, 157 + PhabricatorPolicyCapability::CAN_EDIT, 158 + )) 152 159 ->executeOne(); 153 160 154 161 if (!$account) {
+6 -1
src/applications/auth/management/PhabricatorAuthManagementRefreshWorkflow.php
··· 36 36 $viewer = $this->getViewer(); 37 37 38 38 $query = id(new PhabricatorExternalAccountQuery()) 39 - ->setViewer($viewer); 39 + ->setViewer($viewer) 40 + ->requireCapabilities( 41 + array( 42 + PhabricatorPolicyCapability::CAN_VIEW, 43 + PhabricatorPolicyCapability::CAN_EDIT, 44 + )); 40 45 41 46 $username = $args->getArg('user'); 42 47 if (strlen($username)) {
+10
src/applications/auth/query/PhabricatorExternalAccountQuery.php
··· 1 1 <?php 2 2 3 + /** 4 + * NOTE: When loading ExternalAccounts for use in an authetication context (that 5 + * is, you're going to act as the account or link identities or anything like 6 + * that) you should require CAN_EDIT capability even if you aren't actually 7 + * editing the ExternalAccount. 8 + * 9 + * ExternalAccounts have a permissive CAN_VIEW policy (like users) because they 10 + * interact directly with objects and can leave comments, sign documents, etc. 11 + * However, CAN_EDIT is restricted to users who own the accounts. 12 + */ 3 13 final class PhabricatorExternalAccountQuery 4 14 extends PhabricatorCursorPagedPolicyAwareQuery { 5 15
+5
src/applications/differential/landing/DifferentialLandingToGitHub.php
··· 101 101 ->withUserPHIDs(array($viewer->getPHID())) 102 102 ->withAccountTypes(array('github')) 103 103 ->withAccountDomains(array($repo_domain)) 104 + ->requireCapabilities( 105 + array( 106 + PhabricatorPolicyCapability::CAN_VIEW, 107 + PhabricatorPolicyCapability::CAN_EDIT, 108 + )) 104 109 ->executeOne(); 105 110 106 111 if (!$this->account) {
+5
src/applications/doorkeeper/bridge/DoorkeeperBridgeAsana.php
··· 37 37 ->withUserPHIDs(array($viewer->getPHID())) 38 38 ->withAccountTypes(array($provider->getProviderType())) 39 39 ->withAccountDomains(array($provider->getProviderDomain())) 40 + ->requireCapabilities( 41 + array( 42 + PhabricatorPolicyCapability::CAN_VIEW, 43 + PhabricatorPolicyCapability::CAN_EDIT, 44 + )) 40 45 ->execute(); 41 46 42 47 if (!$accounts) {
+5
src/applications/doorkeeper/bridge/DoorkeeperBridgeJIRA.php
··· 31 31 ->setViewer($viewer) 32 32 ->withUserPHIDs(array($viewer->getPHID())) 33 33 ->withAccountTypes(array($provider->getProviderType())) 34 + ->requireCapabilities( 35 + array( 36 + PhabricatorPolicyCapability::CAN_VIEW, 37 + PhabricatorPolicyCapability::CAN_EDIT, 38 + )) 34 39 ->execute(); 35 40 36 41 if (!$accounts) {
+5
src/applications/doorkeeper/option/PhabricatorAsanaConfigOptions.php
··· 59 59 ->withUserPHIDs(array($viewer->getPHID())) 60 60 ->withAccountTypes(array($provider->getProviderType())) 61 61 ->withAccountDomains(array($provider->getProviderDomain())) 62 + ->requireCapabilities( 63 + array( 64 + PhabricatorPolicyCapability::CAN_VIEW, 65 + PhabricatorPolicyCapability::CAN_EDIT, 66 + )) 62 67 ->executeOne(); 63 68 if (!$account) { 64 69 return null;
+10
src/applications/doorkeeper/worker/DoorkeeperFeedWorkerAsana.php
··· 524 524 ->withUserPHIDs($all_phids) 525 525 ->withAccountTypes(array($provider->getProviderType())) 526 526 ->withAccountDomains(array($provider->getProviderDomain())) 527 + ->requireCapabilities( 528 + array( 529 + PhabricatorPolicyCapability::CAN_VIEW, 530 + PhabricatorPolicyCapability::CAN_EDIT, 531 + )) 527 532 ->execute(); 528 533 529 534 foreach ($accounts as $account) { ··· 549 554 ->withUserPHIDs($user_phids) 550 555 ->withAccountTypes(array($provider->getProviderType())) 551 556 ->withAccountDomains(array($provider->getProviderDomain())) 557 + ->requireCapabilities( 558 + array( 559 + PhabricatorPolicyCapability::CAN_VIEW, 560 + PhabricatorPolicyCapability::CAN_EDIT, 561 + )) 552 562 ->execute(); 553 563 554 564 // Reorder accounts in the original order.
+5
src/applications/doorkeeper/worker/DoorkeeperFeedWorkerJIRA.php
··· 63 63 ->withUserPHIDs($try_users) 64 64 ->withAccountTypes(array($provider->getProviderType())) 65 65 ->withAccountDomains(array($domain)) 66 + ->requireCapabilities( 67 + array( 68 + PhabricatorPolicyCapability::CAN_VIEW, 69 + PhabricatorPolicyCapability::CAN_EDIT, 70 + )) 66 71 ->execute(); 67 72 // Reorder accounts in the original order. 68 73 // TODO: This needs to be adjusted if/when we allow you to link multiple
+5
src/applications/metamta/receiver/PhabricatorMailReceiver.php
··· 107 107 ->withAccountTypes(array('email')) 108 108 ->withAccountDomains(array($from_obj->getDomainName(), 'self')) 109 109 ->withAccountIDs(array($from_obj->getAddress())) 110 + ->requireCapabilities( 111 + array( 112 + PhabricatorPolicyCapability::CAN_VIEW, 113 + PhabricatorPolicyCapability::CAN_EDIT, 114 + )) 110 115 ->loadOneOrCreate(); 111 116 return $xuser->getPhabricatorUser(); 112 117 } else {
+5
src/applications/people/controller/PhabricatorPeopleProfilePictureController.php
··· 125 125 ->setViewer($viewer) 126 126 ->withUserPHIDs(array($user->getPHID())) 127 127 ->needImages(true) 128 + ->requireCapabilities( 129 + array( 130 + PhabricatorPolicyCapability::CAN_VIEW, 131 + PhabricatorPolicyCapability::CAN_EDIT, 132 + )) 128 133 ->execute(); 129 134 130 135 foreach ($accounts as $account) {
+33 -3
src/applications/people/storage/PhabricatorExternalAccount.php
··· 84 84 return true; 85 85 } 86 86 87 + public function getDisplayName() { 88 + if (strlen($this->displayName)) { 89 + return $this->displayName; 90 + } 91 + 92 + // TODO: Figure out how much identifying information we're going to show 93 + // to users about external accounts. For now, just show a string which is 94 + // clearly not an error, but don't disclose any identifying information. 95 + 96 + $map = array( 97 + 'email' => pht('Email User'), 98 + ); 99 + 100 + $type = $this->getAccountType(); 101 + 102 + return idx($map, $type, pht('"%s" User', $type)); 103 + } 104 + 105 + 87 106 88 107 /* -( PhabricatorPolicyInterface )----------------------------------------- */ 89 108 ··· 91 110 public function getCapabilities() { 92 111 return array( 93 112 PhabricatorPolicyCapability::CAN_VIEW, 113 + PhabricatorPolicyCapability::CAN_EDIT, 94 114 ); 95 115 } 96 116 97 117 public function getPolicy($capability) { 98 - return PhabricatorPolicies::POLICY_NOONE; 118 + switch ($capability) { 119 + case PhabricatorPolicyCapability::CAN_VIEW: 120 + return PhabricatorPolicies::getMostOpenPolicy(); 121 + case PhabricatorPolicyCapability::CAN_EDIT: 122 + return PhabricatorPolicies::POLICY_NOONE; 123 + } 99 124 } 100 125 101 126 public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { ··· 103 128 } 104 129 105 130 public function describeAutomaticCapability($capability) { 106 - // TODO: (T603) This is complicated. 107 - return null; 131 + switch ($capability) { 132 + case PhabricatorPolicyCapability::CAN_VIEW: 133 + return null; 134 + case PhabricatorPolicyCapability::CAN_EDIT: 135 + return pht( 136 + 'External accounts can only be edited by the account owner.'); 137 + } 108 138 } 109 139 110 140 }
+5
src/applications/settings/panel/PhabricatorSettingsPanelExternalAccounts.php
··· 28 28 ->setViewer($viewer) 29 29 ->withUserPHIDs(array($viewer->getPHID())) 30 30 ->needImages(true) 31 + ->requireCapabilities( 32 + array( 33 + PhabricatorPolicyCapability::CAN_VIEW, 34 + PhabricatorPolicyCapability::CAN_EDIT, 35 + )) 31 36 ->execute(); 32 37 33 38 $linked_head = id(new PHUIHeaderView())
+5
src/applications/settings/panel/PhabricatorSettingsPanelSessions.php
··· 25 25 $accounts = id(new PhabricatorExternalAccountQuery()) 26 26 ->setViewer($viewer) 27 27 ->withUserPHIDs(array($viewer->getPHID())) 28 + ->requireCapabilities( 29 + array( 30 + PhabricatorPolicyCapability::CAN_VIEW, 31 + PhabricatorPolicyCapability::CAN_EDIT, 32 + )) 28 33 ->execute(); 29 34 30 35 $identity_phids = mpull($accounts, 'getPHID');