1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-18 11:30:55 +01:00

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
This commit is contained in:
epriestley 2015-06-22 11:46:59 -07:00
parent e6b7f655ee
commit d1983560a6
22 changed files with 214 additions and 22 deletions

View file

@ -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',

View file

@ -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();
}

View file

@ -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,
),
);
}

View file

@ -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,
),
);
}

View file

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

View file

@ -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,
),
);
}

View file

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

View file

@ -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,
),
);
}

View file

@ -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,
),
);
}

View file

@ -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(),

View file

@ -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(),
);

View file

@ -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,
),
);

View file

@ -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,
),
);
}

View file

@ -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,
),
);
}

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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,
),
);
}

View file

@ -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,
),
);
}

View file

@ -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,
),
);
}

View file

@ -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));
}
}

View file

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