From d1983560a6bc02035756d087b7469893f0091838 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 22 Jun 2015 11:46:59 -0700 Subject: [PATCH] Show when objects have a non-default policy Summary: Fixes T6787. I'm kind of cheating a little bit here by not unifying default selection with `initializeNew(...)` methods, but I figure we can let this settle for a bit and then go do that later. It's pretty minor. Since we're not doing templates I kind of want to swap the `'template'` key to `'type'` so maybe I'll do that too at some point. @chad, freel free to change these, I was just trying to make them pretty obvious. I //do// think it's good for them to stand out, but my approach is probably a bit inconsistent/heavy-handed in the new design. Test Plan: {F525024} {F525025} {F525026} {F525027} Reviewers: btrahan, chad Reviewed By: btrahan Subscribers: johnny-bit, joshuaspence, chad, epriestley Maniphest Tasks: T6787 Differential Revision: https://secure.phabricator.com/D13387 --- resources/celerity/map.php | 6 +- .../base/PhabricatorApplication.php | 17 +++++ .../PhabricatorCountdownApplication.php | 1 + .../PhabricatorDifferentialApplication.php | 1 + .../PhabricatorDiffusionApplication.php | 2 + .../PhabricatorDivinerApplication.php | 2 + .../PhabricatorDrydockApplication.php | 2 + .../PhabricatorFilesApplication.php | 1 + .../PhabricatorLegalpadApplication.php | 2 + .../PhabricatorManiphestApplication.php | 2 + .../PhabricatorNuanceApplication.php | 2 + .../PhabricatorPassphraseApplication.php | 2 + .../PhabricatorPasteApplication.php | 2 + .../PhabricatorPholioApplication.php | 2 + .../PhabricatorPolicyEditController.php | 4 -- .../PhabricatorPolicyExplainController.php | 65 +++++++++++++++---- .../policy/query/PhabricatorPolicyQuery.php | 41 ++++++++++++ .../PhabricatorProjectApplication.php | 3 + .../PhabricatorSlowvoteApplication.php | 1 + .../PhabricatorSpacesApplication.php | 2 + src/view/phui/PHUIHeaderView.php | 41 +++++++++++- webroot/rsrc/css/phui/phui-header-view.css | 35 ++++++++++ 22 files changed, 214 insertions(+), 22 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 6cb0832e1d..90b596da99 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => 'd7ecac6d', + 'core.pkg.css' => 'eb51e6dc', 'core.pkg.js' => 'e0117d99', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '02273347', @@ -136,7 +136,7 @@ return array( 'rsrc/css/phui/phui-fontkit.css' => 'dd8ddf27', 'rsrc/css/phui/phui-form-view.css' => '808329f2', 'rsrc/css/phui/phui-form.css' => '25876baf', - 'rsrc/css/phui/phui-header-view.css' => '2dd74fe0', + 'rsrc/css/phui/phui-header-view.css' => 'a8e1d0ac', 'rsrc/css/phui/phui-icon.css' => 'bc766998', 'rsrc/css/phui/phui-image-mask.css' => '5a8b09c8', 'rsrc/css/phui/phui-info-panel.css' => '27ea50a1', @@ -779,7 +779,7 @@ return array( 'phui-fontkit-css' => 'dd8ddf27', 'phui-form-css' => '25876baf', 'phui-form-view-css' => '808329f2', - 'phui-header-view-css' => '2dd74fe0', + 'phui-header-view-css' => 'a8e1d0ac', 'phui-icon-view-css' => 'bc766998', 'phui-image-mask-css' => '5a8b09c8', 'phui-info-panel-css' => '27ea50a1', diff --git a/src/applications/base/PhabricatorApplication.php b/src/applications/base/PhabricatorApplication.php index 1f605476bc..d91ccad4c7 100644 --- a/src/applications/base/PhabricatorApplication.php +++ b/src/applications/base/PhabricatorApplication.php @@ -606,6 +606,23 @@ abstract class PhabricatorApplication return idx($spec, 'template'); } + final public function getDefaultObjectTypePolicyMap() { + $map = array(); + + foreach ($this->getCustomCapabilities() as $capability => $spec) { + if (empty($spec['template'])) { + continue; + } + if (empty($spec['capability'])) { + continue; + } + $default = $this->getPolicy($capability); + $map[$spec['template']][$spec['capability']] = $default; + } + + return $map; + } + public function getApplicationSearchDocumentTypes() { return array(); } diff --git a/src/applications/countdown/application/PhabricatorCountdownApplication.php b/src/applications/countdown/application/PhabricatorCountdownApplication.php index 24e796a4a6..d4b99f9ed7 100644 --- a/src/applications/countdown/application/PhabricatorCountdownApplication.php +++ b/src/applications/countdown/application/PhabricatorCountdownApplication.php @@ -53,6 +53,7 @@ final class PhabricatorCountdownApplication extends PhabricatorApplication { PhabricatorCountdownDefaultViewCapability::CAPABILITY => array( 'caption' => pht('Default view policy for new countdowns.'), 'template' => PhabricatorCountdownCountdownPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_VIEW, ), ); } diff --git a/src/applications/differential/application/PhabricatorDifferentialApplication.php b/src/applications/differential/application/PhabricatorDifferentialApplication.php index d73236668a..2cc611027f 100644 --- a/src/applications/differential/application/PhabricatorDifferentialApplication.php +++ b/src/applications/differential/application/PhabricatorDifferentialApplication.php @@ -187,6 +187,7 @@ final class PhabricatorDifferentialApplication extends PhabricatorApplication { DifferentialDefaultViewCapability::CAPABILITY => array( 'caption' => pht('Default view policy for newly created revisions.'), 'template' => DifferentialRevisionPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_VIEW, ), ); } diff --git a/src/applications/diffusion/application/PhabricatorDiffusionApplication.php b/src/applications/diffusion/application/PhabricatorDiffusionApplication.php index 271efc2a53..0314318643 100644 --- a/src/applications/diffusion/application/PhabricatorDiffusionApplication.php +++ b/src/applications/diffusion/application/PhabricatorDiffusionApplication.php @@ -142,10 +142,12 @@ final class PhabricatorDiffusionApplication extends PhabricatorApplication { return array( DiffusionDefaultViewCapability::CAPABILITY => array( 'template' => PhabricatorRepositoryRepositoryPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_VIEW, ), DiffusionDefaultEditCapability::CAPABILITY => array( 'default' => PhabricatorPolicies::POLICY_ADMIN, 'template' => PhabricatorRepositoryRepositoryPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_EDIT, ), DiffusionDefaultPushCapability::CAPABILITY => array( 'template' => PhabricatorRepositoryRepositoryPHIDType::TYPECONST, diff --git a/src/applications/diviner/application/PhabricatorDivinerApplication.php b/src/applications/diviner/application/PhabricatorDivinerApplication.php index 4d0691d990..23a1e91a7c 100644 --- a/src/applications/diviner/application/PhabricatorDivinerApplication.php +++ b/src/applications/diviner/application/PhabricatorDivinerApplication.php @@ -57,10 +57,12 @@ final class PhabricatorDivinerApplication extends PhabricatorApplication { return array( DivinerDefaultViewCapability::CAPABILITY => array( 'template' => DivinerBookPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_VIEW, ), DivinerDefaultEditCapability::CAPABILITY => array( 'default' => PhabricatorPolicies::POLICY_ADMIN, 'template' => DivinerBookPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_EDIT, ), ); } diff --git a/src/applications/drydock/application/PhabricatorDrydockApplication.php b/src/applications/drydock/application/PhabricatorDrydockApplication.php index 6e7b0fcfdc..7919f1c9cf 100644 --- a/src/applications/drydock/application/PhabricatorDrydockApplication.php +++ b/src/applications/drydock/application/PhabricatorDrydockApplication.php @@ -74,10 +74,12 @@ final class PhabricatorDrydockApplication extends PhabricatorApplication { return array( DrydockDefaultViewCapability::CAPABILITY => array( 'template' => DrydockBlueprintPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_VIEW, ), DrydockDefaultEditCapability::CAPABILITY => array( 'default' => PhabricatorPolicies::POLICY_ADMIN, 'template' => DrydockBlueprintPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_EDIT, ), DrydockCreateBlueprintsCapability::CAPABILITY => array( 'default' => PhabricatorPolicies::POLICY_ADMIN, diff --git a/src/applications/files/application/PhabricatorFilesApplication.php b/src/applications/files/application/PhabricatorFilesApplication.php index 1714719f8e..6fed230fd2 100644 --- a/src/applications/files/application/PhabricatorFilesApplication.php +++ b/src/applications/files/application/PhabricatorFilesApplication.php @@ -61,6 +61,7 @@ final class PhabricatorFilesApplication extends PhabricatorApplication { FilesDefaultViewCapability::CAPABILITY => array( 'caption' => pht('Default view policy for newly created files.'), 'template' => PhabricatorFileFilePHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_VIEW, ), ); } diff --git a/src/applications/legalpad/application/PhabricatorLegalpadApplication.php b/src/applications/legalpad/application/PhabricatorLegalpadApplication.php index e1394e0507..e47049ef30 100644 --- a/src/applications/legalpad/application/PhabricatorLegalpadApplication.php +++ b/src/applications/legalpad/application/PhabricatorLegalpadApplication.php @@ -77,9 +77,11 @@ final class PhabricatorLegalpadApplication extends PhabricatorApplication { LegalpadCreateDocumentsCapability::CAPABILITY => array(), LegalpadDefaultViewCapability::CAPABILITY => array( 'template' => PhabricatorLegalpadDocumentPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_VIEW, ), LegalpadDefaultEditCapability::CAPABILITY => array( 'template' => PhabricatorLegalpadDocumentPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_EDIT, ), ); } diff --git a/src/applications/maniphest/application/PhabricatorManiphestApplication.php b/src/applications/maniphest/application/PhabricatorManiphestApplication.php index 3debdb44ca..758d85f879 100644 --- a/src/applications/maniphest/application/PhabricatorManiphestApplication.php +++ b/src/applications/maniphest/application/PhabricatorManiphestApplication.php @@ -132,10 +132,12 @@ final class PhabricatorManiphestApplication extends PhabricatorApplication { ManiphestDefaultViewCapability::CAPABILITY => array( 'caption' => pht('Default view policy for newly created tasks.'), 'template' => ManiphestTaskPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_VIEW, ), ManiphestDefaultEditCapability::CAPABILITY => array( 'caption' => pht('Default edit policy for newly created tasks.'), 'template' => ManiphestTaskPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_EDIT, ), ManiphestEditStatusCapability::CAPABILITY => array(), ManiphestEditAssignCapability::CAPABILITY => array(), diff --git a/src/applications/nuance/application/PhabricatorNuanceApplication.php b/src/applications/nuance/application/PhabricatorNuanceApplication.php index 20c58f841c..2d82f3f0b0 100644 --- a/src/applications/nuance/application/PhabricatorNuanceApplication.php +++ b/src/applications/nuance/application/PhabricatorNuanceApplication.php @@ -73,10 +73,12 @@ final class PhabricatorNuanceApplication extends PhabricatorApplication { NuanceSourceDefaultViewCapability::CAPABILITY => array( 'caption' => pht('Default view policy for newly created sources.'), 'template' => NuanceSourcePHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_VIEW, ), NuanceSourceDefaultEditCapability::CAPABILITY => array( 'caption' => pht('Default edit policy for newly created sources.'), 'template' => NuanceSourcePHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_EDIT, ), NuanceSourceManageCapability::CAPABILITY => array(), ); diff --git a/src/applications/passphrase/application/PhabricatorPassphraseApplication.php b/src/applications/passphrase/application/PhabricatorPassphraseApplication.php index 92e9abe9d0..daf794180f 100644 --- a/src/applications/passphrase/application/PhabricatorPassphraseApplication.php +++ b/src/applications/passphrase/application/PhabricatorPassphraseApplication.php @@ -71,11 +71,13 @@ final class PhabricatorPassphraseApplication extends PhabricatorApplication { PassphraseDefaultViewCapability::CAPABILITY => array( 'caption' => pht('Default view policy for newly created credentials.'), 'template' => PassphraseCredentialPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_VIEW, 'default' => $policy_key, ), PassphraseDefaultEditCapability::CAPABILITY => array( 'caption' => pht('Default edit policy for newly created credentials.'), 'template' => PassphraseCredentialPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_EDIT, 'default' => $policy_key, ), ); diff --git a/src/applications/paste/application/PhabricatorPasteApplication.php b/src/applications/paste/application/PhabricatorPasteApplication.php index f9cd03dd74..a3f11bb9a8 100644 --- a/src/applications/paste/application/PhabricatorPasteApplication.php +++ b/src/applications/paste/application/PhabricatorPasteApplication.php @@ -65,10 +65,12 @@ final class PhabricatorPasteApplication extends PhabricatorApplication { PasteDefaultViewCapability::CAPABILITY => array( 'caption' => pht('Default view policy for newly created pastes.'), 'template' => PhabricatorPastePastePHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_VIEW, ), PasteDefaultEditCapability::CAPABILITY => array( 'caption' => pht('Default edit policy for newly created pastes.'), 'template' => PhabricatorPastePastePHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_EDIT, ), ); } diff --git a/src/applications/pholio/application/PhabricatorPholioApplication.php b/src/applications/pholio/application/PhabricatorPholioApplication.php index 52309ba078..e019adf04b 100644 --- a/src/applications/pholio/application/PhabricatorPholioApplication.php +++ b/src/applications/pholio/application/PhabricatorPholioApplication.php @@ -73,9 +73,11 @@ final class PhabricatorPholioApplication extends PhabricatorApplication { return array( PholioDefaultViewCapability::CAPABILITY => array( 'template' => PholioMockPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_VIEW, ), PholioDefaultEditCapability::CAPABILITY => array( 'template' => PholioMockPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_EDIT, ), ); } diff --git a/src/applications/policy/controller/PhabricatorPolicyEditController.php b/src/applications/policy/controller/PhabricatorPolicyEditController.php index 30c9836557..abd9c5b41b 100644 --- a/src/applications/policy/controller/PhabricatorPolicyEditController.php +++ b/src/applications/policy/controller/PhabricatorPolicyEditController.php @@ -6,9 +6,6 @@ final class PhabricatorPolicyEditController public function handleRequest(AphrontRequest $request) { $viewer = $this->getViewer(); - // TODO: This doesn't do anything yet, but sets up template policies; see - // T6860. - $is_template = false; $object_phid = $request->getURIData('objectPHID'); if ($object_phid) { @@ -23,7 +20,6 @@ final class PhabricatorPolicyEditController $object_type = $request->getURIData('objectType'); if (!$object_type) { $object_type = $request->getURIData('templateType'); - $is_template = true; } $phid_types = PhabricatorPHIDType::getAllInstalledTypes($viewer); diff --git a/src/applications/policy/controller/PhabricatorPolicyExplainController.php b/src/applications/policy/controller/PhabricatorPolicyExplainController.php index 46dfad3f57..2639c967d4 100644 --- a/src/applications/policy/controller/PhabricatorPolicyExplainController.php +++ b/src/applications/policy/controller/PhabricatorPolicyExplainController.php @@ -3,24 +3,15 @@ final class PhabricatorPolicyExplainController extends PhabricatorPolicyController { - private $phid; - private $capability; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->phid = $data['phid']; - $this->capability = $data['capability']; - } + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); - - $phid = $this->phid; - $capability = $this->capability; + $phid = $request->getURIData('phid'); + $capability = $request->getURIData('capability'); $object = id(new PhabricatorObjectQuery()) ->setViewer($viewer) @@ -84,11 +75,15 @@ final class PhabricatorPolicyExplainController $handle->getTypeName(), $handle->getObjectName()); - return $dialog + $dialog ->setTitle(pht('Policy Details: %s', $object_name)) ->appendParagraph($intro) ->appendChild($auto_info) ->addCancelButton($object_uri, pht('Done')); + + $this->appendStrengthInformation($dialog, $object, $policy, $capability); + + return $dialog; } private function appendSpaceInformation( @@ -180,4 +175,46 @@ final class PhabricatorPolicyExplainController 'object policy checks.')); } + private function appendStrengthInformation( + AphrontDialogView $dialog, + PhabricatorPolicyInterface $object, + PhabricatorPolicy $policy, + $capability) { + $viewer = $this->getViewer(); + + $default_policy = PhabricatorPolicyQuery::getDefaultPolicyForObject( + $viewer, + $object, + $capability); + if (!$default_policy) { + return; + } + + if ($default_policy->getPHID() == $policy->getPHID()) { + return; + } + + if ($default_policy->isStrongerThan($policy)) { + $info = pht( + 'This object has a less restrictive policy ("%s") than the default '. + 'policy for similar objects (which is "%s").', + $policy->getShortName(), + $default_policy->getShortName()); + } else if ($policy->isStrongerThan($default_policy)) { + $info = pht( + 'This object has a more restrictive policy ("%s") than the default '. + 'policy for similar objects (which is "%s").', + $policy->getShortName(), + $default_policy->getShortName()); + } else { + $info = pht( + 'This object has a different policy ("%s") than the default policy '. + 'for similar objects (which is "%s").', + $policy->getShortName(), + $default_policy->getShortName()); + } + + $dialog->appendParagraph($info); + } + } diff --git a/src/applications/policy/query/PhabricatorPolicyQuery.php b/src/applications/policy/query/PhabricatorPolicyQuery.php index 496c704b71..daa7012223 100644 --- a/src/applications/policy/query/PhabricatorPolicyQuery.php +++ b/src/applications/policy/query/PhabricatorPolicyQuery.php @@ -342,5 +342,46 @@ final class PhabricatorPolicyQuery return $results; } + public static function getDefaultPolicyForObject( + PhabricatorUser $viewer, + PhabricatorPolicyInterface $object, + $capability) { + + $phid = $object->getPHID(); + if (!$phid) { + return null; + } + + $type = phid_get_type($phid); + + $map = self::getDefaultObjectTypePolicyMap(); + + if (empty($map[$type][$capability])) { + return null; + } + + $policy_phid = $map[$type][$capability]; + + return id(new PhabricatorPolicyQuery()) + ->setViewer($viewer) + ->withPHIDs(array($policy_phid)) + ->executeOne(); + } + + private static function getDefaultObjectTypePolicyMap() { + static $map; + + if ($map === null) { + $map = array(); + + $apps = PhabricatorApplication::getAllApplications(); + foreach ($apps as $app) { + $map += $app->getDefaultObjectTypePolicyMap(); + } + } + + return $map; + } + } diff --git a/src/applications/project/application/PhabricatorProjectApplication.php b/src/applications/project/application/PhabricatorProjectApplication.php index adf6378e2a..0a2ae190d9 100644 --- a/src/applications/project/application/PhabricatorProjectApplication.php +++ b/src/applications/project/application/PhabricatorProjectApplication.php @@ -121,14 +121,17 @@ final class PhabricatorProjectApplication extends PhabricatorApplication { ProjectDefaultViewCapability::CAPABILITY => array( 'caption' => pht('Default view policy for newly created projects.'), 'template' => PhabricatorProjectProjectPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_VIEW, ), ProjectDefaultEditCapability::CAPABILITY => array( 'caption' => pht('Default edit policy for newly created projects.'), 'template' => PhabricatorProjectProjectPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_EDIT, ), ProjectDefaultJoinCapability::CAPABILITY => array( 'caption' => pht('Default join policy for newly created projects.'), 'template' => PhabricatorProjectProjectPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_JOIN, ), ); } diff --git a/src/applications/slowvote/application/PhabricatorSlowvoteApplication.php b/src/applications/slowvote/application/PhabricatorSlowvoteApplication.php index 40791659b1..e7ea30dfed 100644 --- a/src/applications/slowvote/application/PhabricatorSlowvoteApplication.php +++ b/src/applications/slowvote/application/PhabricatorSlowvoteApplication.php @@ -65,6 +65,7 @@ final class PhabricatorSlowvoteApplication extends PhabricatorApplication { PhabricatorSlowvoteDefaultViewCapability::CAPABILITY => array( 'caption' => pht('Default view policy for new polls.'), 'template' => PhabricatorSlowvotePollPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_VIEW, ), ); } diff --git a/src/applications/spaces/application/PhabricatorSpacesApplication.php b/src/applications/spaces/application/PhabricatorSpacesApplication.php index 7942caf919..2f4ba394d1 100644 --- a/src/applications/spaces/application/PhabricatorSpacesApplication.php +++ b/src/applications/spaces/application/PhabricatorSpacesApplication.php @@ -74,11 +74,13 @@ final class PhabricatorSpacesApplication extends PhabricatorApplication { PhabricatorSpacesCapabilityDefaultView::CAPABILITY => array( 'caption' => pht('Default view policy for newly created spaces.'), 'template' => PhabricatorSpacesNamespacePHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_VIEW, ), PhabricatorSpacesCapabilityDefaultEdit::CAPABILITY => array( 'caption' => pht('Default edit policy for newly created spaces.'), 'default' => PhabricatorPolicies::POLICY_ADMIN, 'template' => PhabricatorSpacesNamespacePHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_EDIT, ), ); } diff --git a/src/view/phui/PHUIHeaderView.php b/src/view/phui/PHUIHeaderView.php index 100ee93d4b..0557424f7b 100644 --- a/src/view/phui/PHUIHeaderView.php +++ b/src/view/phui/PHUIHeaderView.php @@ -292,6 +292,7 @@ final class PHUIHeaderView extends AphrontTagView { // NOTE: We'll do this even if the viewer has access to only one space, and // show them information about the existence of spaces if they click // through. + $use_space_policy = false; if ($object instanceof PhabricatorSpacesInterface) { $space_phid = PhabricatorSpacesNamespaceQuery::getObjectSpacePHID( $object); @@ -306,13 +307,46 @@ final class PHUIHeaderView extends AphrontTagView { if ($space_policy) { if ($space_policy->isStrongerThan($policy)) { $policy = $space_policy; + $use_space_policy = true; } } } } + $container_classes = array(); + $container_classes[] = 'policy-header-callout'; $phid = $object->getPHID(); + // If we're going to show the object policy, try to determine if the object + // policy differs from the default policy. If it does, we'll call it out + // as changed. + if (!$use_space_policy) { + $default_policy = PhabricatorPolicyQuery::getDefaultPolicyForObject( + $viewer, + $object, + $view_capability); + if ($default_policy) { + if ($default_policy->getPHID() != $policy->getPHID()) { + $container_classes[] = 'policy-adjusted'; + if ($default_policy->isStrongerThan($policy)) { + // The policy has strictly been weakened. For example, the + // default might be "All Users" and the current policy is "Public". + $container_classes[] = 'policy-adjusted-weaker'; + } else if ($policy->isStrongerThan($default_policy)) { + // The policy has strictly been strengthened, and is now more + // restrictive than the default. For example, "All Users" has + // been replaced with "No One". + $container_classes[] = 'policy-adjusted-stronger'; + } else { + // The policy has been adjusted but not strictly strengthened + // or weakened. For example, "Members of X" has been replaced with + // "Members of Y". + $container_classes[] = 'policy-adjusted-different'; + } + } + } + } + $icon = id(new PHUIIconView()) ->setIconFont($policy->getIcon().' bluegrey'); @@ -325,7 +359,12 @@ final class PHUIHeaderView extends AphrontTagView { ), $policy->getShortName()); - return array($icon, $link); + return phutil_tag( + 'span', + array( + 'class' => implode(' ', $container_classes), + ), + array($icon, $link)); } } diff --git a/webroot/rsrc/css/phui/phui-header-view.css b/webroot/rsrc/css/phui/phui-header-view.css index 842441dae0..6a80aaa8c3 100644 --- a/webroot/rsrc/css/phui/phui-header-view.css +++ b/webroot/rsrc/css/phui/phui-header-view.css @@ -116,6 +116,41 @@ body.device-phone .phui-header-view { color: {$darkbluetext}; } +.policy-header-callout.policy-adjusted { + padding: 0 4px; + border-radius: 3px; +} + +.policy-header-callout.policy-adjusted-weaker { + background: {$lightgreen}; + border: 1px solid {$green}; +} + +.policy-header-callout.policy-adjusted-weaker .policy-link, +.policy-header-callout.policy-adjusted-weaker .phui-icon-view { + color: {$green}; +} + +.policy-header-callout.policy-adjusted-stronger { + background: {$lightred}; + border: 1px solid {$red}; +} + +.policy-header-callout.policy-adjusted-stronger .policy-link, +.policy-header-callout.policy-adjusted-stronger .phui-icon-view { + color: {$red}; +} + +.policy-header-callout.policy-adjusted-different { + background: {$lightorange}; + border: 1px solid {$orange}; +} + +.policy-header-callout.policy-adjusted-different .policy-link, +.policy-header-callout.policy-adjusted-different .phui-icon-view { + color: {$orange}; +} + .phui-header-subheader .phui-header-status-dark { color: {$indigo}; text-shadow: 0 1px #fff;