@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<?php
2
3final class PhabricatorPolicyRequestExceptionHandler
4 extends PhabricatorRequestExceptionHandler {
5
6 public function getRequestExceptionHandlerPriority() {
7 return 320000;
8 }
9
10 public function getRequestExceptionHandlerDescription() {
11 return pht(
12 'Handles policy exceptions which occur when a user tries to '.
13 'do something they do not have permission to do.');
14 }
15
16 public function canHandleRequestThrowable(
17 AphrontRequest $request,
18 $throwable) {
19
20 if (!$this->isPhabricatorSite($request)) {
21 return false;
22 }
23
24 return ($throwable instanceof PhabricatorPolicyException);
25 }
26
27 public function handleRequestThrowable(
28 AphrontRequest $request,
29 $throwable) {
30
31 $viewer = $this->getViewer($request);
32
33 if (!$viewer->isLoggedIn()) {
34 // If the user isn't logged in, just give them a login form. This is
35 // probably a generally more useful response than a policy dialog that
36 // they have to click through to get a login form.
37 //
38 // Possibly we should add a header here like "you need to login to see
39 // the thing you are trying to look at".
40 $auth_app_class = PhabricatorAuthApplication::class;
41 $auth_app = PhabricatorApplication::getByClass($auth_app_class);
42
43 return id(new PhabricatorAuthStartController())
44 ->setRequest($request)
45 ->setCurrentApplication($auth_app)
46 ->handleRequest($request);
47 }
48
49 $content = array(
50 phutil_tag(
51 'div',
52 array(
53 'class' => 'aphront-policy-rejection',
54 ),
55 $throwable->getRejection()),
56 );
57
58 $list = null;
59 if ($throwable->getCapabilityName()) {
60 $list = $throwable->getMoreInfo();
61 foreach ($list as $key => $item) {
62 $list[$key] = $item;
63 }
64
65 $content[] = phutil_tag(
66 'div',
67 array(
68 'class' => 'aphront-capability-details',
69 ),
70 pht(
71 'Users with the "%s" capability:',
72 $throwable->getCapabilityName()));
73
74 }
75
76 $dialog = id(new AphrontDialogView())
77 ->setTitle($throwable->getTitle())
78 ->setClass('aphront-access-dialog')
79 ->setViewer($viewer)
80 ->appendChild($content);
81
82 if ($list) {
83 $dialog->appendList($list);
84 }
85
86 // If the install is in developer mode, include a stack trace for the
87 // exception. When debugging things, it isn't always obvious where a
88 // policy exception came from and this can make it easier to hunt down
89 // bugs or improve ambiguous/confusing messaging.
90
91 $is_developer = PhabricatorEnv::getEnvConfig('phabricator.developer-mode');
92 if ($is_developer) {
93 $dialog->appendChild(
94 id(new AphrontStackTraceView())
95 ->setTrace($throwable->getTrace()));
96 }
97
98 if ($request->isAjax()) {
99 $dialog->addCancelButton('/', pht('Close'));
100 } else {
101 $dialog->addCancelButton('/', pht('OK'));
102 }
103
104 return $dialog;
105 }
106
107}