1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-23 07:12:41 +01:00

Config - add an option to lock policy settings

Summary: Fixes T6947

Test Plan:
locked people.create.user and noted the UI only showed a link to the existing policy with no way to edit it.

tried to set the config to all the various bad things and saw helpful error messages telling me what I did wrong.

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: Korvin, epriestley

Maniphest Tasks: T6947

Differential Revision: https://secure.phabricator.com/D11358
This commit is contained in:
Bob Trahan 2015-01-13 11:46:29 -08:00
parent 7e78a3f906
commit 8cfc37f8fc
4 changed files with 90 additions and 11 deletions

View file

@ -2864,6 +2864,7 @@ phutil_register_library_map(array(
'PhrictionTransactionComment' => 'applications/phriction/storage/PhrictionTransactionComment.php', 'PhrictionTransactionComment' => 'applications/phriction/storage/PhrictionTransactionComment.php',
'PhrictionTransactionEditor' => 'applications/phriction/editor/PhrictionTransactionEditor.php', 'PhrictionTransactionEditor' => 'applications/phriction/editor/PhrictionTransactionEditor.php',
'PhrictionTransactionQuery' => 'applications/phriction/query/PhrictionTransactionQuery.php', 'PhrictionTransactionQuery' => 'applications/phriction/query/PhrictionTransactionQuery.php',
'PolicyLockOptionType' => 'applications/policy/config/PolicyLockOptionType.php',
'PonderAddAnswerView' => 'applications/ponder/view/PonderAddAnswerView.php', 'PonderAddAnswerView' => 'applications/ponder/view/PonderAddAnswerView.php',
'PonderAnswer' => 'applications/ponder/storage/PonderAnswer.php', 'PonderAnswer' => 'applications/ponder/storage/PonderAnswer.php',
'PonderAnswerCommentController' => 'applications/ponder/controller/PonderAnswerCommentController.php', 'PonderAnswerCommentController' => 'applications/ponder/controller/PonderAnswerCommentController.php',
@ -6194,6 +6195,7 @@ phutil_register_library_map(array(
'PhrictionTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhrictionTransactionComment' => 'PhabricatorApplicationTransactionComment',
'PhrictionTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'PhrictionTransactionEditor' => 'PhabricatorApplicationTransactionEditor',
'PhrictionTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhrictionTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PolicyLockOptionType' => 'PhabricatorConfigJSONOptionType',
'PonderAddAnswerView' => 'AphrontView', 'PonderAddAnswerView' => 'AphrontView',
'PonderAnswer' => array( 'PonderAnswer' => array(
'PonderDAO', 'PonderDAO',

View file

@ -3,23 +3,17 @@
final class PhabricatorApplicationEditController final class PhabricatorApplicationEditController
extends PhabricatorApplicationsController { extends PhabricatorApplicationsController {
private $application;
public function shouldRequireAdmin() { public function shouldRequireAdmin() {
return true; return true;
} }
public function willProcessRequest(array $data) { public function handleRequest(AphrontRequest $request) {
$this->application = $data['application'];
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser(); $user = $request->getUser();
$application = $request->getURIData('application');
$application = id(new PhabricatorApplicationQuery()) $application = id(new PhabricatorApplicationQuery())
->setViewer($user) ->setViewer($user)
->withClasses(array($this->application)) ->withClasses(array($application))
->requireCapabilities( ->requireCapabilities(
array( array(
PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_VIEW,
@ -107,7 +101,7 @@ final class PhabricatorApplicationEditController
$user, $user,
$config_entry, $config_entry,
$value, $value,
PhabricatorContentSource::newFromRequest($this->getRequest())); PhabricatorContentSource::newFromRequest($request));
} }
return id(new AphrontRedirectResponse())->setURI($view_uri); return id(new AphrontRedirectResponse())->setURI($view_uri);
@ -120,12 +114,15 @@ final class PhabricatorApplicationEditController
$form = id(new AphrontFormView()) $form = id(new AphrontFormView())
->setUser($user); ->setUser($user);
$locked_policies = PhabricatorEnv::getEnvConfig('policy.locked');
$locked_map = array_fill_keys($locked_policies, true);
foreach ($application->getCapabilities() as $capability) { foreach ($application->getCapabilities() as $capability) {
$label = $application->getCapabilityLabel($capability); $label = $application->getCapabilityLabel($capability);
$can_edit = $application->isCapabilityEditable($capability); $can_edit = $application->isCapabilityEditable($capability);
$locked = idx($locked_map, $capability);
$caption = $application->getCapabilityCaption($capability); $caption = $application->getCapabilityCaption($capability);
if (!$can_edit) { if (!$can_edit || $locked) {
$form->appendChild( $form->appendChild(
id(new AphrontFormStaticControl()) id(new AphrontFormStaticControl())
->setLabel($label) ->setLabel($label)
@ -135,6 +132,7 @@ final class PhabricatorApplicationEditController
$form->appendChild( $form->appendChild(
id(new AphrontFormPolicyControl()) id(new AphrontFormPolicyControl())
->setUser($user) ->setUser($user)
->setDisabled(idx($locked_map, $capability))
->setCapability($capability) ->setCapability($capability)
->setPolicyObject($application) ->setPolicyObject($application)
->setPolicies($policies) ->setPolicies($policies)

View file

@ -12,6 +12,12 @@ final class PhabricatorPolicyConfigOptions
} }
public function getOptions() { public function getOptions() {
$policy_locked_type = 'custom:PolicyLockOptionType';
$policy_locked_example = array(
'people.create.users' => 'admin',);
$json = new PhutilJSON();
$policy_locked_example = $json->encodeFormatted($policy_locked_example);
return array( return array(
$this->newOption('policy.allow-public', 'bool', false) $this->newOption('policy.allow-public', 'bool', false)
->setBoolOptions( ->setBoolOptions(
@ -39,6 +45,16 @@ final class PhabricatorPolicyConfigOptions
"With this setting disabled, the 'Public' policy is not ". "With this setting disabled, the 'Public' policy is not ".
"available, and the most open policy is 'All Users' (which means ". "available, and the most open policy is 'All Users' (which means ".
"users must have accounts and be logged in to view things).")), "users must have accounts and be logged in to view things).")),
$this->newOption('policy.locked', $policy_locked_type, array())
->setSummary(pht(
'Lock specific application policies so they can not be edited.'))
->setDescription(pht(
'Phabricator has application policies which can dictate whether '.
'users can take certain actions, such as creating new users. '."\n\n".
'This setting allows for "locking" these policies such that no '.
'further edits can be made on a per-policy basis.'))
->addExample($policy_locked_example,
pht('Lock Create User Policy To Admins')),
); );
} }

View file

@ -0,0 +1,63 @@
<?php
final class PolicyLockOptionType
extends PhabricatorConfigJSONOptionType {
public function validateOption(PhabricatorConfigOption $option, $value) {
$capabilities = id(new PhutilSymbolLoader())
->setAncestorClass('PhabricatorPolicyCapability')
->loadObjects();
$capabilities = mpull($capabilities, null, 'getCapabilityKey');
$policy_phids = array();
foreach ($value as $capability_key => $policy) {
$capability = idx($capabilities, $capability_key);
if (!$capability) {
throw new Exception(pht(
'Capability "%s" does not exist.', $capability_key));
}
if (phid_get_type($policy) !=
PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) {
$policy_phids[$policy] = $policy;
} else {
try {
$policy_object = PhabricatorPolicyQuery::getGlobalPolicy($policy);
// this exception is not helpful here as its about global policy;
// throw a better exception
} catch (Exception $ex) {
throw new Exception(pht(
'Capability "%s" has invalid policy "%s".',
$capability_key,
$policy));
}
}
if ($policy == PhabricatorPolicies::POLICY_PUBLIC) {
if (!$capability->shouldAllowPublicPolicySetting()) {
throw new Exception(pht(
'Capability "%s" does not support public policy.',
$capability_key));
}
}
}
if ($policy_phids) {
$handles = id(new PhabricatorHandleQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPhids($policy_phids)
->execute();
$handles = mpull($handles, null, 'getPHID');
foreach ($value as $capability_key => $policy) {
$handle = $handles[$policy];
if (!$handle->isComplete()) {
throw new Exception(pht(
'Capability "%s" has invalid policy "%s"; "%s" does not exist.',
$capability_key,
$policy,
$policy));
}
}
}
}
}