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

Make Differential views capability-sensitive

Summary:
Ref T603. Make Differential behaviors for logged-out and underprivleged users more similar to other apps.

I'm going to drop this "anonymous access" thing at some point, but `reviews.fb.net` actually looks like it's running semi-modern code, so leave it alive until we have a more compelling replacement in the upstream.

Test Plan: As a logged out user, browsed Differential and clicked things and such.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T603

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

+130 -40
+20 -1
src/applications/differential/controller/DifferentialChangesetViewController.php
··· 3 3 final class DifferentialChangesetViewController extends DifferentialController { 4 4 5 5 public function shouldRequireLogin() { 6 - return !$this->allowsAnonymousAccess(); 6 + if ($this->allowsAnonymousAccess()) { 7 + return false; 8 + } 9 + 10 + return parent::shouldRequireLogin(); 11 + } 12 + 13 + public function shouldAllowPublic() { 14 + return true; 7 15 } 8 16 9 17 public function processRequest() { ··· 27 35 if (!$changeset) { 28 36 return new Aphront404Response(); 29 37 } 38 + 39 + // TODO: (T603) Make Changeset policy-aware. For now, just fake it 40 + // by making sure we can see the diff. 41 + $diff = id(new DifferentialDiffQuery()) 42 + ->setViewer($request->getUser()) 43 + ->withIDs(array($changeset->getDiffID())) 44 + ->executeOne(); 45 + if (!$diff) { 46 + return new Aphront404Response(); 47 + } 48 + 30 49 31 50 $view = $request->getStr('view'); 32 51 if ($view) {
+4 -1
src/applications/differential/controller/DifferentialRevisionListController.php
··· 6 6 private $queryKey; 7 7 8 8 public function shouldRequireLogin() { 9 - return !$this->allowsAnonymousAccess(); 9 + if ($this->allowsAnonymousAccess()) { 10 + return false; 11 + } 12 + return parent::shouldRequireLogin(); 10 13 } 11 14 12 15 public function shouldAllowPublic() {
+58 -38
src/applications/differential/controller/DifferentialRevisionViewController.php
··· 5 5 private $revisionID; 6 6 7 7 public function shouldRequireLogin() { 8 - return !$this->allowsAnonymousAccess(); 8 + if ($this->allowsAnonymousAccess()) { 9 + return false; 10 + } 11 + return parent::shouldRequireLogin(); 12 + } 13 + 14 + public function shouldAllowPublic() { 15 + return true; 9 16 } 10 17 11 18 public function willProcessRequest(array $data) { ··· 405 412 )); 406 413 if ($comment_form) { 407 414 $page_pane->appendChild($comment_form->render()); 415 + } else { 416 + // TODO: For now, just use this to get "Login to Comment". 417 + $page_pane->appendChild( 418 + id(new PhabricatorApplicationTransactionCommentView()) 419 + ->setUser($user) 420 + ->setRequestURI($request->getRequestURI())); 408 421 } 422 + 409 423 410 424 $object_id = 'D'.$revision->getID(); 411 425 ··· 493 507 $viewer_is_owner = ($revision->getAuthorPHID() == $viewer_phid); 494 508 $viewer_is_reviewer = in_array($viewer_phid, $revision->getReviewers()); 495 509 $viewer_is_cc = in_array($viewer_phid, $revision->getCCPHIDs()); 496 - $viewer_is_anonymous = !$this->getRequest()->getUser()->isLoggedIn(); 510 + $logged_in = $this->getRequest()->getUser()->isLoggedIn(); 497 511 $status = $revision->getStatus(); 498 512 $revision_id = $revision->getID(); 499 513 $revision_phid = $revision->getPHID(); 500 514 501 515 $links = array(); 502 516 503 - if ($viewer_is_owner) { 517 + $can_edit = PhabricatorPolicyFilter::hasCapability( 518 + $user, 519 + $revision, 520 + PhabricatorPolicyCapability::CAN_EDIT); 521 + 522 + $links[] = array( 523 + 'icon' => 'edit', 524 + 'href' => "/differential/revision/edit/{$revision_id}/", 525 + 'name' => pht('Edit Revision'), 526 + 'disabled' => !$can_edit, 527 + 'sigil' => $can_edit ? null : 'workflow', 528 + ); 529 + 530 + if (!$viewer_is_owner && !$viewer_is_reviewer) { 531 + $action = $viewer_is_cc ? 'rem' : 'add'; 504 532 $links[] = array( 505 - 'icon' => 'edit', 506 - 'href' => "/differential/revision/edit/{$revision_id}/", 507 - 'name' => pht('Edit Revision'), 533 + 'icon' => $viewer_is_cc ? 'disable' : 'check', 534 + 'href' => "/differential/subscribe/{$action}/{$revision_id}/", 535 + 'name' => $viewer_is_cc ? pht('Unsubscribe') : pht('Subscribe'), 536 + 'instant' => $logged_in, 537 + 'disabled' => !$logged_in, 538 + 'sigil' => $can_edit ? null : 'workflow', 539 + ); 540 + } else { 541 + $links[] = array( 542 + 'icon' => 'enable', 543 + 'name' => pht('Automatically Subscribed'), 544 + 'disabled' => true, 508 545 ); 509 546 } 510 547 511 - if (!$viewer_is_anonymous) { 512 - 513 - if (!$viewer_is_owner && !$viewer_is_reviewer) { 514 - $action = $viewer_is_cc ? 'rem' : 'add'; 515 - $links[] = array( 516 - 'icon' => $viewer_is_cc ? 'disable' : 'check', 517 - 'href' => "/differential/subscribe/{$action}/{$revision_id}/", 518 - 'name' => $viewer_is_cc ? pht('Unsubscribe') : pht('Subscribe'), 519 - 'instant' => true, 520 - ); 521 - } else { 522 - $links[] = array( 523 - 'icon' => 'enable', 524 - 'name' => pht('Automatically Subscribed'), 525 - 'disabled' => true, 526 - ); 527 - } 548 + require_celerity_resource('phabricator-object-selector-css'); 549 + require_celerity_resource('javelin-behavior-phabricator-object-selector'); 528 550 529 - require_celerity_resource('phabricator-object-selector-css'); 530 - require_celerity_resource('javelin-behavior-phabricator-object-selector'); 551 + $links[] = array( 552 + 'icon' => 'link', 553 + 'name' => pht('Edit Dependencies'), 554 + 'href' => "/search/attach/{$revision_phid}/DREV/dependencies/", 555 + 'sigil' => 'workflow', 556 + 'disabled' => !$can_edit, 557 + ); 531 558 559 + $maniphest = 'PhabricatorApplicationManiphest'; 560 + if (PhabricatorApplication::isClassInstalled($maniphest)) { 532 561 $links[] = array( 533 - 'icon' => 'link', 534 - 'name' => pht('Edit Dependencies'), 535 - 'href' => "/search/attach/{$revision_phid}/DREV/dependencies/", 562 + 'icon' => 'attach', 563 + 'name' => pht('Edit Maniphest Tasks'), 564 + 'href' => "/search/attach/{$revision_phid}/TASK/", 536 565 'sigil' => 'workflow', 566 + 'disabled' => !$can_edit, 537 567 ); 538 - 539 - $maniphest = 'PhabricatorApplicationManiphest'; 540 - if (PhabricatorApplication::isClassInstalled($maniphest)) { 541 - $links[] = array( 542 - 'icon' => 'attach', 543 - 'name' => pht('Edit Maniphest Tasks'), 544 - 'href' => "/search/attach/{$revision_phid}/TASK/", 545 - 'sigil' => 'workflow', 546 - ); 547 - } 548 568 } 549 569 550 570 $request_uri = $this->getRequest()->getRequestURI();
+26
src/applications/differential/query/DifferentialDiffQuery.php
··· 44 44 } 45 45 46 46 public function willFilterPage(array $diffs) { 47 + $revision_ids = array_filter(mpull($diffs, 'getRevisionID')); 48 + 49 + $revisions = array(); 50 + if ($revision_ids) { 51 + $revisions = id(new DifferentialRevisionQuery()) 52 + ->setViewer($this->getViewer()) 53 + ->withIDs($revision_ids) 54 + ->execute(); 55 + } 56 + 57 + foreach ($diffs as $key => $diff) { 58 + if (!$diff->getRevisionID()) { 59 + $diff->attachRevision(null); 60 + continue; 61 + } 62 + 63 + $revision = idx($revisions, $diff->getRevisionID()); 64 + if ($revision) { 65 + $diff->attachRevision($revision); 66 + continue; 67 + } 68 + 69 + unset($diffs[$key]); 70 + } 71 + 72 + 47 73 if ($this->needChangesets) { 48 74 $this->loadChangesets($diffs); 49 75 }
+18
src/applications/differential/storage/DifferentialDiff.php
··· 32 32 private $unsavedChangesets = array(); 33 33 private $changesets = self::ATTACHABLE; 34 34 private $arcanistProject = self::ATTACHABLE; 35 + private $revision = self::ATTACHABLE; 35 36 36 37 public function addUnsavedChangeset(DifferentialChangeset $changeset) { 37 38 if ($this->changesets === null) { ··· 284 285 return $changes; 285 286 } 286 287 288 + public function getRevision() { 289 + return $this->assertAttached($this->revision); 290 + } 291 + 292 + public function attachRevision(DifferentialRevision $revision = null) { 293 + $this->revision = $revision; 294 + return $this; 295 + } 296 + 287 297 288 298 /* -( PhabricatorPolicyInterface )----------------------------------------- */ 289 299 ··· 295 305 } 296 306 297 307 public function getPolicy($capability) { 308 + if ($this->getRevision()) { 309 + return $this->getRevision()->getPolicy($capability); 310 + } 311 + 298 312 return PhabricatorPolicies::POLICY_USER; 299 313 } 300 314 301 315 public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { 316 + if ($this->getRevision()) { 317 + return $this->getRevision()->hasAutomaticCapability($capability, $viewer); 318 + } 319 + 302 320 return false; 303 321 } 304 322
+4
src/applications/help/controller/PhabricatorHelpKeyboardShortcutController.php
··· 3 3 final class PhabricatorHelpKeyboardShortcutController 4 4 extends PhabricatorHelpController { 5 5 6 + public function shouldAllowPublic() { 7 + return true; 8 + } 9 + 6 10 public function processRequest() { 7 11 $request = $this->getRequest(); 8 12 $user = $request->getUser();