Skip to content

Commit c830461

Browse files
author
epriestley
committed
Allow application policies to be edited
Summary: Ref T603. Enables: - Application policies can be edited. - Applications can define custom policies (this will be used for setting defaults, like "what is the default visibiltiy of new tasks", and meta-policies, like "who can create a task?"). Test Plan: Edited application policies. A future diff does more with custom policies. Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T603 Differential Revision: https://secure.phabricator.com/D7205
1 parent bf14d8e commit c830461

File tree

5 files changed

+305
-27
lines changed

5 files changed

+305
-27
lines changed

src/__phutil_library_map__.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,7 @@
828828
'PhabricatorApplicationDiviner' => 'applications/diviner/application/PhabricatorApplicationDiviner.php',
829829
'PhabricatorApplicationDoorkeeper' => 'applications/doorkeeper/application/PhabricatorApplicationDoorkeeper.php',
830830
'PhabricatorApplicationDrydock' => 'applications/drydock/application/PhabricatorApplicationDrydock.php',
831+
'PhabricatorApplicationEditController' => 'applications/meta/controller/PhabricatorApplicationEditController.php',
831832
'PhabricatorApplicationFact' => 'applications/fact/application/PhabricatorApplicationFact.php',
832833
'PhabricatorApplicationFeed' => 'applications/feed/application/PhabricatorApplicationFeed.php',
833834
'PhabricatorApplicationFiles' => 'applications/files/application/PhabricatorApplicationFiles.php',
@@ -2937,6 +2938,7 @@
29372938
'PhabricatorApplicationDiviner' => 'PhabricatorApplication',
29382939
'PhabricatorApplicationDoorkeeper' => 'PhabricatorApplication',
29392940
'PhabricatorApplicationDrydock' => 'PhabricatorApplication',
2941+
'PhabricatorApplicationEditController' => 'PhabricatorApplicationsController',
29402942
'PhabricatorApplicationFact' => 'PhabricatorApplication',
29412943
'PhabricatorApplicationFeed' => 'PhabricatorApplication',
29422944
'PhabricatorApplicationFiles' => 'PhabricatorApplication',

src/applications/base/PhabricatorApplication.php

Lines changed: 95 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -321,18 +321,32 @@ public static function getAllInstalledApplications() {
321321

322322

323323
public function getCapabilities() {
324-
return array(
325-
PhabricatorPolicyCapability::CAN_VIEW,
326-
PhabricatorPolicyCapability::CAN_EDIT,
327-
);
324+
return array_merge(
325+
array(
326+
PhabricatorPolicyCapability::CAN_VIEW,
327+
PhabricatorPolicyCapability::CAN_EDIT,
328+
),
329+
array_keys($this->getCustomCapabilities()));
328330
}
329331

330332
public function getPolicy($capability) {
333+
$default = $this->getCustomPolicySetting($capability);
334+
if ($default) {
335+
return $default;
336+
}
337+
331338
switch ($capability) {
332339
case PhabricatorPolicyCapability::CAN_VIEW:
333-
return PhabricatorPolicies::POLICY_USER;
340+
if (PhabricatorEnv::getEnvConfig('policy.allow-public')) {
341+
return PhabricatorPolicies::POLICY_PUBLIC;
342+
} else {
343+
return PhabricatorPolicies::POLICY_USER;
344+
}
334345
case PhabricatorPolicyCapability::CAN_EDIT:
335346
return PhabricatorPolicies::POLICY_ADMIN;
347+
default:
348+
$spec = $this->getCustomCapabilitySpecification($capability);
349+
return idx($spec, 'default', PhabricatorPolicies::POLICY_USER);
336350
}
337351
}
338352

@@ -345,4 +359,80 @@ public function describeAutomaticCapability($capability) {
345359
}
346360

347361

362+
/* -( Policies )----------------------------------------------------------- */
363+
364+
protected function getCustomCapabilities() {
365+
return array();
366+
}
367+
368+
private function getCustomPolicySetting($capability) {
369+
if (!$this->isCapabilityEditable($capability)) {
370+
return null;
371+
}
372+
373+
$config = PhabricatorEnv::getEnvConfig('phabricator.application-settings');
374+
375+
$app = idx($config, $this->getPHID());
376+
if (!$app) {
377+
return null;
378+
}
379+
380+
$policy = idx($app, 'policy');
381+
if (!$policy) {
382+
return null;
383+
}
384+
385+
return idx($policy, $capability);
386+
}
387+
388+
389+
private function getCustomCapabilitySpecification($capability) {
390+
$custom = $this->getCustomCapabilities();
391+
if (empty($custom[$capability])) {
392+
throw new Exception("Unknown capability '{$capability}'!");
393+
}
394+
return $custom[$capability];
395+
}
396+
397+
public function getCapabilityLabel($capability) {
398+
$map = array(
399+
PhabricatorPolicyCapability::CAN_VIEW => pht('Can Use Application'),
400+
PhabricatorPolicyCapability::CAN_EDIT => pht('Can Configure Application'),
401+
);
402+
403+
$map += ipull($this->getCustomCapabilities(), 'label');
404+
405+
return idx($map, $capability);
406+
}
407+
408+
public function isCapabilityEditable($capability) {
409+
switch ($capability) {
410+
case PhabricatorPolicyCapability::CAN_VIEW:
411+
return $this->canUninstall();
412+
case PhabricatorPolicyCapability::CAN_EDIT:
413+
return false;
414+
default:
415+
$spec = $this->getCustomCapabilitySpecification($capability);
416+
return idx($spec, 'edit', true);
417+
}
418+
}
419+
420+
public function getCapabilityCaption($capability) {
421+
switch ($capability) {
422+
case PhabricatorPolicyCapability::CAN_VIEW:
423+
if (!$this->canUninstall()) {
424+
return pht(
425+
'This application is required for Phabricator to operate, so all '.
426+
'users must have access to it.');
427+
} else {
428+
return null;
429+
}
430+
case PhabricatorPolicyCapability::CAN_EDIT:
431+
return null;
432+
default:
433+
$spec = $this->getCustomCapabilitySpecification($capability);
434+
return idx($spec, 'caption');
435+
}
436+
}
437+
348438
}

src/applications/meta/application/PhabricatorApplicationApplications.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ public function getRoutes() {
3333
'PhabricatorApplicationsListController',
3434
'view/(?P<application>\w+)/' =>
3535
'PhabricatorApplicationDetailViewController',
36+
'edit/(?P<application>\w+)/' =>
37+
'PhabricatorApplicationEditController',
3638
'(?P<application>\w+)/(?P<action>install|uninstall)/' =>
3739
'PhabricatorApplicationUninstallController',
3840
),

src/applications/meta/controller/PhabricatorApplicationDetailViewController.php

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ public function processRequest() {
1313
$request = $this->getRequest();
1414
$user = $request->getUser();
1515

16-
$selected = PhabricatorApplication::getByClass($this->application);
17-
16+
$selected = id(new PhabricatorApplicationQuery())
17+
->setViewer($user)
18+
->withClasses(array($this->application))
19+
->executeOne();
1820
if (!$selected) {
1921
return new Aphront404Response();
2022
}
@@ -24,8 +26,7 @@ public function processRequest() {
2426
$crumbs = $this->buildApplicationCrumbs();
2527
$crumbs->addCrumb(
2628
id(new PhabricatorCrumbView())
27-
->setName(pht('Applications'))
28-
->setHref($this->getApplicationURI()));
29+
->setName($selected->getName()));
2930

3031
$header = id(new PHUIHeaderView())
3132
->setHeader($title);
@@ -70,37 +71,68 @@ public function processRequest() {
7071
));
7172
}
7273

73-
private function buildPropertyView(PhabricatorApplication $selected) {
74+
private function buildPropertyView(PhabricatorApplication $application) {
75+
$viewer = $this->getRequest()->getUser();
76+
7477
$properties = id(new PhabricatorPropertyListView())
75-
->addProperty(
76-
pht('Description'), $selected->getShortDescription());
78+
->addProperty(pht('Description'), $application->getShortDescription());
79+
80+
$descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions(
81+
$viewer,
82+
$application);
83+
84+
$properties->addSectionHeader(pht('Policies'));
85+
86+
foreach ($application->getCapabilities() as $capability) {
87+
$properties->addProperty(
88+
$application->getCapabilityLabel($capability),
89+
idx($descriptions, $capability));
90+
}
7791

7892
return $properties;
7993
}
8094

8195
private function buildActionView(
82-
PhabricatorUser $user, PhabricatorApplication $selected) {
96+
PhabricatorUser $user,
97+
PhabricatorApplication $selected) {
8398

8499
$view = id(new PhabricatorActionListView())
85100
->setUser($user)
86101
->setObjectURI($this->getRequest()->getRequestURI());
87102

103+
$can_edit = PhabricatorPolicyFilter::hasCapability(
104+
$user,
105+
$selected,
106+
PhabricatorPolicyCapability::CAN_EDIT);
107+
108+
$edit_uri = $this->getApplicationURI('edit/'.get_class($selected).'/');
109+
110+
$view->addAction(
111+
id(new PhabricatorActionView())
112+
->setName(pht('Edit Policies'))
113+
->setIcon('edit')
114+
->setDisabled(!$can_edit)
115+
->setWorkflow(!$can_edit)
116+
->setHref($edit_uri));
117+
88118
if ($selected->canUninstall()) {
89119
if ($selected->isInstalled()) {
90120
$view->addAction(
91-
id(new PhabricatorActionView())
92-
->setName(pht('Uninstall'))
93-
->setIcon('delete')
94-
->setWorkflow(true)
95-
->setHref(
96-
$this->getApplicationURI(get_class($selected).'/uninstall/')));
121+
id(new PhabricatorActionView())
122+
->setName(pht('Uninstall'))
123+
->setIcon('delete')
124+
->setDisabled(!$can_edit)
125+
->setWorkflow(true)
126+
->setHref(
127+
$this->getApplicationURI(get_class($selected).'/uninstall/')));
97128
} else {
98129
$action = id(new PhabricatorActionView())
99130
->setName(pht('Install'))
100131
->setIcon('new')
132+
->setDisabled(!$can_edit)
101133
->setWorkflow(true)
102134
->setHref(
103-
$this->getApplicationURI(get_class($selected).'/install/'));
135+
$this->getApplicationURI(get_class($selected).'/install/'));
104136

105137
$beta_enabled = PhabricatorEnv::getEnvConfig(
106138
'phabricator.show-beta-applications');
@@ -112,14 +144,15 @@ private function buildActionView(
112144
}
113145
} else {
114146
$view->addAction(
115-
id(new PhabricatorActionView())
116-
->setName(pht('Uninstall'))
117-
->setIcon('delete')
118-
->setWorkflow(true)
119-
->setDisabled(true)
120-
->setHref(
121-
$this->getApplicationURI(get_class($selected).'/uninstall/')));
147+
id(new PhabricatorActionView())
148+
->setName(pht('Uninstall'))
149+
->setIcon('delete')
150+
->setWorkflow(true)
151+
->setDisabled(true)
152+
->setHref(
153+
$this->getApplicationURI(get_class($selected).'/uninstall/')));
122154
}
155+
123156
return $view;
124157
}
125158

0 commit comments

Comments
 (0)