mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-26 22:48:19 +01:00
Explain policy exception rules to users
Summary: Ref T603. Adds clarifying text which expands on policies and explains exceptions and rules. The goal is to provide an easy way for users to learn about special policy rules, like "task owners can always see a task". This presentation might be a little aggressive. That's probably OK as we introduce policies, but something a little more tempered might be better down the road. Test Plan: See screenshot. Reviewers: btrahan, chad Reviewed By: chad CC: aran Maniphest Tasks: T603 Differential Revision: https://secure.phabricator.com/D7150
This commit is contained in:
parent
e0f99484ac
commit
2e5ac128b3
63 changed files with 565 additions and 56 deletions
|
@ -836,7 +836,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'aphront-dialog-view-css' =>
|
||||
array(
|
||||
'uri' => '/res/337bd2a9/rsrc/css/aphront/dialog-view.css',
|
||||
'uri' => '/res/609ccc78/rsrc/css/aphront/dialog-view.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -1176,7 +1176,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'herald-rule-editor' =>
|
||||
array(
|
||||
'uri' => '/res/f8ee0e9c/rsrc/js/application/herald/HeraldRuleEditor.js',
|
||||
'uri' => '/res/36222dde/rsrc/js/application/herald/HeraldRuleEditor.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -4162,7 +4162,7 @@ celerity_register_resource_map(array(
|
|||
), array(
|
||||
'packages' =>
|
||||
array(
|
||||
'15affac5' =>
|
||||
'de5898ae' =>
|
||||
array(
|
||||
'name' => 'core.pkg.css',
|
||||
'symbols' =>
|
||||
|
@ -4209,7 +4209,7 @@ celerity_register_resource_map(array(
|
|||
39 => 'phabricator-property-list-view-css',
|
||||
40 => 'phabricator-tag-view-css',
|
||||
),
|
||||
'uri' => '/res/pkg/15affac5/core.pkg.css',
|
||||
'uri' => '/res/pkg/de5898ae/core.pkg.css',
|
||||
'type' => 'css',
|
||||
),
|
||||
'8977e356' =>
|
||||
|
@ -4399,15 +4399,15 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'reverse' =>
|
||||
array(
|
||||
'aphront-dialog-view-css' => '15affac5',
|
||||
'aphront-error-view-css' => '15affac5',
|
||||
'aphront-list-filter-view-css' => '15affac5',
|
||||
'aphront-pager-view-css' => '15affac5',
|
||||
'aphront-panel-view-css' => '15affac5',
|
||||
'aphront-table-view-css' => '15affac5',
|
||||
'aphront-tokenizer-control-css' => '15affac5',
|
||||
'aphront-tooltip-css' => '15affac5',
|
||||
'aphront-typeahead-control-css' => '15affac5',
|
||||
'aphront-dialog-view-css' => 'de5898ae',
|
||||
'aphront-error-view-css' => 'de5898ae',
|
||||
'aphront-list-filter-view-css' => 'de5898ae',
|
||||
'aphront-pager-view-css' => 'de5898ae',
|
||||
'aphront-panel-view-css' => 'de5898ae',
|
||||
'aphront-table-view-css' => 'de5898ae',
|
||||
'aphront-tokenizer-control-css' => 'de5898ae',
|
||||
'aphront-tooltip-css' => 'de5898ae',
|
||||
'aphront-typeahead-control-css' => 'de5898ae',
|
||||
'differential-changeset-view-css' => '44bfe40c',
|
||||
'differential-core-view-css' => '44bfe40c',
|
||||
'differential-inline-comment-editor' => '5e9e5c4e',
|
||||
|
@ -4421,7 +4421,7 @@ celerity_register_resource_map(array(
|
|||
'differential-table-of-contents-css' => '44bfe40c',
|
||||
'diffusion-commit-view-css' => 'c8ce2d88',
|
||||
'diffusion-icons-css' => 'c8ce2d88',
|
||||
'global-drag-and-drop-css' => '15affac5',
|
||||
'global-drag-and-drop-css' => 'de5898ae',
|
||||
'inline-comment-summary-css' => '44bfe40c',
|
||||
'javelin-aphlict' => '8977e356',
|
||||
'javelin-behavior' => '9564fa17',
|
||||
|
@ -4494,54 +4494,54 @@ celerity_register_resource_map(array(
|
|||
'javelin-util' => '9564fa17',
|
||||
'javelin-vector' => '9564fa17',
|
||||
'javelin-workflow' => '9564fa17',
|
||||
'lightbox-attachment-css' => '15affac5',
|
||||
'lightbox-attachment-css' => 'de5898ae',
|
||||
'maniphest-task-summary-css' => '49898640',
|
||||
'phabricator-action-list-view-css' => '15affac5',
|
||||
'phabricator-application-launch-view-css' => '15affac5',
|
||||
'phabricator-action-list-view-css' => 'de5898ae',
|
||||
'phabricator-application-launch-view-css' => 'de5898ae',
|
||||
'phabricator-busy' => '8977e356',
|
||||
'phabricator-content-source-view-css' => '44bfe40c',
|
||||
'phabricator-core-css' => '15affac5',
|
||||
'phabricator-crumbs-view-css' => '15affac5',
|
||||
'phabricator-core-css' => 'de5898ae',
|
||||
'phabricator-crumbs-view-css' => 'de5898ae',
|
||||
'phabricator-drag-and-drop-file-upload' => '5e9e5c4e',
|
||||
'phabricator-dropdown-menu' => '8977e356',
|
||||
'phabricator-file-upload' => '8977e356',
|
||||
'phabricator-filetree-view-css' => '15affac5',
|
||||
'phabricator-flag-css' => '15affac5',
|
||||
'phabricator-filetree-view-css' => 'de5898ae',
|
||||
'phabricator-flag-css' => 'de5898ae',
|
||||
'phabricator-hovercard' => '8977e356',
|
||||
'phabricator-jump-nav' => '15affac5',
|
||||
'phabricator-jump-nav' => 'de5898ae',
|
||||
'phabricator-keyboard-shortcut' => '8977e356',
|
||||
'phabricator-keyboard-shortcut-manager' => '8977e356',
|
||||
'phabricator-main-menu-view' => '15affac5',
|
||||
'phabricator-main-menu-view' => 'de5898ae',
|
||||
'phabricator-menu-item' => '8977e356',
|
||||
'phabricator-nav-view-css' => '15affac5',
|
||||
'phabricator-nav-view-css' => 'de5898ae',
|
||||
'phabricator-notification' => '8977e356',
|
||||
'phabricator-notification-css' => '15affac5',
|
||||
'phabricator-notification-menu-css' => '15affac5',
|
||||
'phabricator-notification-css' => 'de5898ae',
|
||||
'phabricator-notification-menu-css' => 'de5898ae',
|
||||
'phabricator-object-selector-css' => '44bfe40c',
|
||||
'phabricator-phtize' => '8977e356',
|
||||
'phabricator-prefab' => '8977e356',
|
||||
'phabricator-project-tag-css' => '49898640',
|
||||
'phabricator-property-list-view-css' => '15affac5',
|
||||
'phabricator-remarkup-css' => '15affac5',
|
||||
'phabricator-property-list-view-css' => 'de5898ae',
|
||||
'phabricator-remarkup-css' => 'de5898ae',
|
||||
'phabricator-shaped-request' => '5e9e5c4e',
|
||||
'phabricator-side-menu-view-css' => '15affac5',
|
||||
'phabricator-standard-page-view' => '15affac5',
|
||||
'phabricator-tag-view-css' => '15affac5',
|
||||
'phabricator-side-menu-view-css' => 'de5898ae',
|
||||
'phabricator-standard-page-view' => 'de5898ae',
|
||||
'phabricator-tag-view-css' => 'de5898ae',
|
||||
'phabricator-textareautils' => '8977e356',
|
||||
'phabricator-tooltip' => '8977e356',
|
||||
'phabricator-transaction-view-css' => '15affac5',
|
||||
'phabricator-zindex-css' => '15affac5',
|
||||
'phui-button-css' => '15affac5',
|
||||
'phui-form-css' => '15affac5',
|
||||
'phui-form-view-css' => '15affac5',
|
||||
'phui-header-view-css' => '15affac5',
|
||||
'phui-icon-view-css' => '15affac5',
|
||||
'phui-object-item-list-view-css' => '15affac5',
|
||||
'phui-spacing-css' => '15affac5',
|
||||
'sprite-apps-large-css' => '15affac5',
|
||||
'sprite-gradient-css' => '15affac5',
|
||||
'sprite-icons-css' => '15affac5',
|
||||
'sprite-menu-css' => '15affac5',
|
||||
'syntax-highlighting-css' => '15affac5',
|
||||
'phabricator-transaction-view-css' => 'de5898ae',
|
||||
'phabricator-zindex-css' => 'de5898ae',
|
||||
'phui-button-css' => 'de5898ae',
|
||||
'phui-form-css' => 'de5898ae',
|
||||
'phui-form-view-css' => 'de5898ae',
|
||||
'phui-header-view-css' => 'de5898ae',
|
||||
'phui-icon-view-css' => 'de5898ae',
|
||||
'phui-object-item-list-view-css' => 'de5898ae',
|
||||
'phui-spacing-css' => 'de5898ae',
|
||||
'sprite-apps-large-css' => 'de5898ae',
|
||||
'sprite-gradient-css' => 'de5898ae',
|
||||
'sprite-icons-css' => 'de5898ae',
|
||||
'sprite-menu-css' => 'de5898ae',
|
||||
'syntax-highlighting-css' => 'de5898ae',
|
||||
),
|
||||
));
|
||||
|
|
|
@ -846,6 +846,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorApplicationPhortune' => 'applications/phortune/application/PhabricatorApplicationPhortune.php',
|
||||
'PhabricatorApplicationPhrequent' => 'applications/phrequent/application/PhabricatorApplicationPhrequent.php',
|
||||
'PhabricatorApplicationPhriction' => 'applications/phriction/application/PhabricatorApplicationPhriction.php',
|
||||
'PhabricatorApplicationPolicy' => 'applications/policy/application/PhabricatorApplicationPolicy.php',
|
||||
'PhabricatorApplicationPonder' => 'applications/ponder/application/PhabricatorApplicationPonder.php',
|
||||
'PhabricatorApplicationProject' => 'applications/project/application/PhabricatorApplicationProject.php',
|
||||
'PhabricatorApplicationReleeph' => 'applications/releeph/application/PhabricatorApplicationReleeph.php',
|
||||
|
@ -1459,8 +1460,10 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPolicyCapability' => 'applications/policy/constants/PhabricatorPolicyCapability.php',
|
||||
'PhabricatorPolicyConfigOptions' => 'applications/config/option/PhabricatorPolicyConfigOptions.php',
|
||||
'PhabricatorPolicyConstants' => 'applications/policy/constants/PhabricatorPolicyConstants.php',
|
||||
'PhabricatorPolicyController' => 'applications/policy/controller/PhabricatorPolicyController.php',
|
||||
'PhabricatorPolicyDataTestCase' => 'applications/policy/__tests__/PhabricatorPolicyDataTestCase.php',
|
||||
'PhabricatorPolicyException' => 'applications/policy/exception/PhabricatorPolicyException.php',
|
||||
'PhabricatorPolicyExplainController' => 'applications/policy/controller/PhabricatorPolicyExplainController.php',
|
||||
'PhabricatorPolicyFilter' => 'applications/policy/filter/PhabricatorPolicyFilter.php',
|
||||
'PhabricatorPolicyInterface' => 'applications/policy/interface/PhabricatorPolicyInterface.php',
|
||||
'PhabricatorPolicyQuery' => 'applications/policy/query/PhabricatorPolicyQuery.php',
|
||||
|
@ -2941,6 +2944,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorApplicationPhortune' => 'PhabricatorApplication',
|
||||
'PhabricatorApplicationPhrequent' => 'PhabricatorApplication',
|
||||
'PhabricatorApplicationPhriction' => 'PhabricatorApplication',
|
||||
'PhabricatorApplicationPolicy' => 'PhabricatorApplication',
|
||||
'PhabricatorApplicationPonder' => 'PhabricatorApplication',
|
||||
'PhabricatorApplicationProject' => 'PhabricatorApplication',
|
||||
'PhabricatorApplicationReleeph' => 'PhabricatorApplication',
|
||||
|
@ -3612,8 +3616,10 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPolicyAwareTestQuery' => 'PhabricatorPolicyAwareQuery',
|
||||
'PhabricatorPolicyCapability' => 'PhabricatorPolicyConstants',
|
||||
'PhabricatorPolicyConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||
'PhabricatorPolicyController' => 'PhabricatorController',
|
||||
'PhabricatorPolicyDataTestCase' => 'PhabricatorTestCase',
|
||||
'PhabricatorPolicyException' => 'Exception',
|
||||
'PhabricatorPolicyExplainController' => 'PhabricatorPolicyController',
|
||||
'PhabricatorPolicyQuery' => 'PhabricatorQuery',
|
||||
'PhabricatorPolicyTestCase' => 'PhabricatorTestCase',
|
||||
'PhabricatorPolicyTestObject' => 'PhabricatorPolicyInterface',
|
||||
|
|
|
@ -81,4 +81,8 @@ final class PhabricatorAuthProviderConfig extends PhabricatorAuthDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,5 +32,9 @@ final class PhabricatorChatLogChannel
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,10 @@ final class PhabricatorChatLogEvent
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_TIMESTAMPS => false,
|
||||
|
|
|
@ -183,4 +183,8 @@ abstract class ConduitAPIMethod
|
|||
return true;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,4 +30,8 @@ final class PhabricatorConduitMethodCallLog extends PhabricatorConduitDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -59,4 +59,8 @@ final class PhabricatorConfigEntry extends PhabricatorConfigEntryDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -189,4 +189,8 @@ final class ConpherenceThread extends ConpherenceDAO
|
|||
return isset($participants[$user->getPHID()]);
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht("Participants in a thread can always view and edit it.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -53,4 +53,8 @@ final class PhabricatorCountdown
|
|||
return ($viewer->getPHID() == $this->getAuthorPHID());
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht('The author of a countdown can always view and edit it.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -41,4 +41,8 @@ final class PhabricatorDaemonLog extends PhabricatorDaemonDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -320,4 +320,12 @@ final class DifferentialDiff
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
if ($this->getRevision()) {
|
||||
return pht(
|
||||
'This diff is attached to a revision, and inherits its policies.');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -329,6 +329,26 @@ final class DifferentialRevision extends DifferentialDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
$description = array(
|
||||
pht('The owner of a revision can always view and edit it.'),
|
||||
);
|
||||
|
||||
switch ($capability) {
|
||||
case PhabricatorPolicyCapability::CAN_VIEW:
|
||||
$description[] = pht(
|
||||
"A revision's reviewers can always view it.");
|
||||
if ($this->getRepository()) {
|
||||
$description[] = pht(
|
||||
'This revision belongs to a repository. Other users must be able '.
|
||||
'to view the repository in order to view this revision.');
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $description;
|
||||
}
|
||||
|
||||
public function getUsersToNotifyOfTokenGiven() {
|
||||
return array(
|
||||
$this->getAuthorPHID(),
|
||||
|
|
|
@ -61,4 +61,8 @@ final class DivinerLiveBook extends DivinerDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -143,6 +143,10 @@ final class DivinerLiveSymbol extends DivinerDAO
|
|||
return $this->getBook()->hasAutomaticCapability($capability, $viewer);
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht('Atoms inherit the policies of the books they are part of.');
|
||||
}
|
||||
|
||||
|
||||
/* -( Markup Interface )--------------------------------------------------- */
|
||||
|
||||
|
|
|
@ -77,4 +77,8 @@ final class DoorkeeperExternalObject extends DoorkeeperDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -324,4 +324,8 @@ abstract class PhabricatorFeedStory implements PhabricatorPolicyInterface {
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -830,6 +830,10 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorSubscribableInterface Implementation )-------------------- */
|
||||
|
||||
|
|
|
@ -50,4 +50,8 @@ final class PhabricatorFlag extends PhabricatorFlagDAO
|
|||
return ($viewer->getPHID() == $this->getOwnerPHID());
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht('Flags are private. Only you can view or edit your flags.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -202,4 +202,10 @@ final class HeraldRule extends HeraldDAO
|
|||
}
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
// TODO: (T603) Sort this out.
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -96,6 +96,12 @@ final class LegalpadDocument extends LegalpadDAO
|
|||
return ($user->getPHID() == $this->getCreatorPHID());
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht(
|
||||
'The author of a document can always view and edit it.');
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
|
||||
|
||||
public function getApplicationTransactionEditor() {
|
||||
|
|
|
@ -61,5 +61,9 @@ final class PhabricatorFileImageMacro extends PhabricatorFileDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -37,4 +37,8 @@ final class PhabricatorMetaMTAMailingList extends PhabricatorMetaMTADAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -221,6 +221,11 @@ final class ManiphestTask extends ManiphestDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht(
|
||||
'The owner of a task can always view and edit it.');
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorTokenReceiverInterface )---------------------------------- */
|
||||
|
||||
|
|
|
@ -30,6 +30,10 @@ final class PhabricatorOwnersPackage extends PhabricatorOwnersDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getConfiguration() {
|
||||
return array(
|
||||
// This information is better available from the history table.
|
||||
|
|
|
@ -61,6 +61,11 @@ final class PhabricatorPaste extends PhabricatorPasteDAO
|
|||
return ($user->getPHID() == $this->getAuthorPHID());
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht(
|
||||
'The author of a paste can always view and edit it.');
|
||||
}
|
||||
|
||||
public function getFullName() {
|
||||
$title = $this->getTitle();
|
||||
if (!$title) {
|
||||
|
|
|
@ -102,4 +102,9 @@ final class PhabricatorExternalAccount extends PhabricatorUserDAO
|
|||
return ($viewer->getPHID() == $this->getUserPHID());
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
// TODO: (T603) This is complicated.
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -834,6 +834,15 @@ EOBODY;
|
|||
return $this->getPHID() && ($viewer->getPHID() === $this->getPHID());
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
switch ($capability) {
|
||||
case PhabricatorPolicyCapability::CAN_EDIT:
|
||||
return pht('Only you can edit your information.');
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorCustomFieldInterface )------------------------------------ */
|
||||
|
||||
|
|
|
@ -188,6 +188,20 @@ final class PhameBlog extends PhameDAO
|
|||
}
|
||||
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
switch ($capability) {
|
||||
case PhabricatorPolicyCapability::CAN_VIEW:
|
||||
return pht(
|
||||
'Users who can edit or post on a blog can always view it.');
|
||||
case PhabricatorPolicyCapability::CAN_JOIN:
|
||||
return pht(
|
||||
'Users who can edit a blog can always post on it.');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorMarkupInterface Implementation )-------------------------- */
|
||||
|
||||
|
||||
|
|
|
@ -150,6 +150,12 @@ final class PhamePost extends PhameDAO
|
|||
}
|
||||
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht(
|
||||
'The author of a blog post can always view and edit it.');
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorMarkupInterface Implementation )-------------------------- */
|
||||
|
||||
|
||||
|
|
|
@ -236,4 +236,8 @@ final class PhabricatorObjectHandle
|
|||
return true;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -45,4 +45,8 @@ final class PhluxVariable extends PhluxDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -104,4 +104,8 @@ final class PholioImage extends PholioDAO
|
|||
return $this->getMock()->hasAutomaticCapability($capability, $viewer);
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -149,6 +149,10 @@ final class PholioMock extends PholioDAO
|
|||
return ($viewer->getPHID() == $this->getAuthorPHID());
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht("A mock's owner can always view and edit it.");
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorMarkupInterface )----------------------------------------- */
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ final class PhortuneAccount extends PhortuneDAO
|
|||
}
|
||||
|
||||
public function getPolicy($capability) {
|
||||
return false;
|
||||
return PhabricatorPolicies::POLICY_NOONE;
|
||||
}
|
||||
|
||||
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
||||
|
@ -54,4 +54,9 @@ final class PhortuneAccount extends PhortuneDAO
|
|||
return isset($members[$viewer->getPHID()]);
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht('Members of an account can always view and edit it.');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -107,4 +107,9 @@ final class PhortunePaymentMethod extends PhortuneDAO
|
|||
$viewer);
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht(
|
||||
'Members of an account can always view and edit its payment methods.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -73,4 +73,8 @@ final class PhortuneProduct extends PhortuneDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -126,6 +126,14 @@ final class PhrictionDocument extends PhrictionDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
if ($this->hasProject()) {
|
||||
return pht(
|
||||
"This is a project wiki page, and inherits the project's policies.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function isAutomaticallySubscribed($phid) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -38,4 +38,8 @@ final class PhabricatorPolicyTestObject
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorApplicationPolicy extends PhabricatorApplication {
|
||||
|
||||
public function shouldAppearInLaunchView() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function canUninstall() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getRoutes() {
|
||||
return array(
|
||||
'/policy/' => array(
|
||||
'explain/(?P<phid>[^/]+)/(?P<capability>[^/]+)/'
|
||||
=> 'PhabricatorPolicyExplainController',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorPolicyController extends PhabricatorController {
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
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 processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$viewer = $request->getUser();
|
||||
|
||||
$phid = $this->phid;
|
||||
$capability = $this->capability;
|
||||
|
||||
$object = id(new PhabricatorObjectQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs(array($phid))
|
||||
->executeOne();
|
||||
if (!$object) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$policies = PhabricatorPolicyQuery::loadPolicies(
|
||||
$viewer,
|
||||
$object);
|
||||
|
||||
$policy = idx($policies, $capability);
|
||||
if (!$policy) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$handle = id(new PhabricatorHandleQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs(array($phid))
|
||||
->executeOne();
|
||||
$object_uri = $handle->getURI();
|
||||
|
||||
$explanation = $policy->getExplanation($capability);
|
||||
$auto_info = (array)$object->describeAutomaticCapability($capability);
|
||||
|
||||
foreach ($auto_info as $key => $info) {
|
||||
$auto_info[$key] = phutil_tag('li', array(), $info);
|
||||
}
|
||||
if ($auto_info) {
|
||||
$auto_info = phutil_tag('ul', array(), $auto_info);
|
||||
}
|
||||
|
||||
$content = array(
|
||||
$explanation,
|
||||
$auto_info,
|
||||
);
|
||||
|
||||
$dialog = id(new AphrontDialogView())
|
||||
->setUser($viewer)
|
||||
->setClass('aphront-access-dialog')
|
||||
->setTitle(pht('Policy Details'))
|
||||
->appendChild($content)
|
||||
->addCancelButton($object_uri, pht('Done'));
|
||||
|
||||
return id(new AphrontDialogResponse())->setDialog($dialog);
|
||||
}
|
||||
|
||||
}
|
|
@ -130,6 +130,35 @@ final class PhabricatorPolicy {
|
|||
return $this->getName();
|
||||
}
|
||||
|
||||
public function getExplanation($capability) {
|
||||
switch ($capability) {
|
||||
case PhabricatorPolicyCapability::CAN_VIEW:
|
||||
switch ($this->getPHID()) {
|
||||
case PhabricatorPolicies::POLICY_PUBLIC:
|
||||
return pht('Visible to the entire internet.');
|
||||
case PhabricatorPolicies::POLICY_USER:
|
||||
return pht('Visible to all logged in users.');
|
||||
case PhabricatorPolicies::POLICY_ADMIN:
|
||||
return pht('Visible to all administrators.');
|
||||
case PhabricatorPolicies::POLICY_NOONE:
|
||||
return pht('Not visible to anyone by default.');
|
||||
}
|
||||
|
||||
switch ($this->getType()) {
|
||||
case PhabricatorPolicyType::TYPE_PROJECT:
|
||||
return pht(
|
||||
'Visible to members of the project "%s".',
|
||||
$this->getName());
|
||||
case PhabricatorPolicyType::TYPE_MASKED:
|
||||
return pht('Other: %s', $this->getName());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return pht('?');
|
||||
}
|
||||
|
||||
public function getFullName() {
|
||||
switch ($this->getType()) {
|
||||
case PhabricatorPolicyType::TYPE_PROJECT:
|
||||
|
|
|
@ -6,4 +6,32 @@ interface PhabricatorPolicyInterface {
|
|||
public function getPolicy($capability);
|
||||
public function hasAutomaticCapability($capability, PhabricatorUser $viewer);
|
||||
|
||||
/**
|
||||
* Describe exceptions to an object's policy setting.
|
||||
*
|
||||
* The intent of this method is to explain and inform users about special
|
||||
* cases which override configured policy settings. If this object has any
|
||||
* such exceptions, explain them by returning one or more human-readable
|
||||
* strings which describe the exception in a broad, categorical way. For
|
||||
* example:
|
||||
*
|
||||
* - "The owner of an X can always view and edit it."
|
||||
* - "Members of a Y can always view it."
|
||||
*
|
||||
* You can return `null`, a single string, or a list of strings.
|
||||
*
|
||||
* The relevant capability to explain (like "view") is passed as a parameter.
|
||||
* You should tailor any messages to be relevant to that capability, although
|
||||
* they do not need to exclusively describe the capability, and in some cases
|
||||
* being more general ("The author can view and edit...") will be more clear.
|
||||
*
|
||||
* Messages should describe general rules, not specific objects, because the
|
||||
* main goal is to teach the user the rules. For example, write "the author",
|
||||
* not the specific author's name.
|
||||
*
|
||||
* @param const @{class:PhabricatorPolicyCapability} constant.
|
||||
* @return wild Description of policy exceptions. See above.
|
||||
*/
|
||||
public function describeAutomaticCapability($capability);
|
||||
|
||||
}
|
||||
|
|
|
@ -15,10 +15,9 @@ final class PhabricatorPolicyQuery extends PhabricatorQuery {
|
|||
return $this;
|
||||
}
|
||||
|
||||
public static function renderPolicyDescriptions(
|
||||
public static function loadPolicies(
|
||||
PhabricatorUser $viewer,
|
||||
PhabricatorPolicyInterface $object,
|
||||
$icon=false) {
|
||||
PhabricatorPolicyInterface $object) {
|
||||
|
||||
$results = array();
|
||||
$policies = null;
|
||||
|
@ -32,7 +31,7 @@ final class PhabricatorPolicyQuery extends PhabricatorQuery {
|
|||
}
|
||||
|
||||
if (isset($global[$policy])) {
|
||||
$results[$capability] = $global[$policy]->renderDescription($icon);
|
||||
$results[$capability] = $global[$policy];
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -45,12 +44,26 @@ final class PhabricatorPolicyQuery extends PhabricatorQuery {
|
|||
->execute();
|
||||
}
|
||||
|
||||
$results[$capability] = $policies[$policy]->renderDescription($icon);
|
||||
$results[$capability] = $policies[$policy];
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
public static function renderPolicyDescriptions(
|
||||
PhabricatorUser $viewer,
|
||||
PhabricatorPolicyInterface $object,
|
||||
$icon = false) {
|
||||
|
||||
$policies = self::loadPolicies($viewer, $object);
|
||||
|
||||
foreach ($policies as $capability => $policy) {
|
||||
$policies[$capability] = $policy->renderDescription($icon);
|
||||
}
|
||||
|
||||
return $policies;
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
if (!$this->viewer) {
|
||||
throw new Exception('Call setViewer() before execute()!');
|
||||
|
|
|
@ -145,6 +145,9 @@ final class PonderAnswer extends PonderDAO
|
|||
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
||||
switch ($capability) {
|
||||
case PhabricatorPolicyCapability::CAN_VIEW:
|
||||
if ($this->getAuthorPHID() == $viewer->getPHID()) {
|
||||
return true;
|
||||
}
|
||||
return $this->getQuestion()->hasAutomaticCapability(
|
||||
$capability,
|
||||
$viewer);
|
||||
|
@ -154,6 +157,19 @@ final class PonderAnswer extends PonderDAO
|
|||
}
|
||||
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
$out = array();
|
||||
$out[] = pht("The author of an answer can always view and edit it.");
|
||||
switch ($capability) {
|
||||
case PhabricatorPolicyCapability::CAN_VIEW:
|
||||
$out[] = pht(
|
||||
"The user who asks a question can always view the answers.");
|
||||
break;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorTokenReceiverInterface )---------------------------------- */
|
||||
|
||||
|
||||
|
|
|
@ -203,6 +203,12 @@ final class PonderQuestion extends PonderDAO
|
|||
return ($viewer->getPHID() == $this->getAuthorPHID());
|
||||
}
|
||||
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht(
|
||||
'The user who asked a question can always view and edit it.');
|
||||
}
|
||||
|
||||
public function getOriginalTitle() {
|
||||
// TODO: Make this actually save/return the original title.
|
||||
return $this->getTitle();
|
||||
|
|
|
@ -60,6 +60,16 @@ final class PhabricatorProject extends PhabricatorProjectDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
switch ($capability) {
|
||||
case PhabricatorPolicyCapability::CAN_VIEW:
|
||||
return pht("Members of a project can always view it.");
|
||||
case PhabricatorPolicyCapability::CAN_JOIN:
|
||||
return pht("Users who can edit a project can always join it.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function isUserMember($user_phid) {
|
||||
return $this->assertAttachedKey($this->sparseMembers, $user_phid);
|
||||
}
|
||||
|
|
|
@ -189,4 +189,9 @@ final class ReleephBranch extends ReleephDAO
|
|||
return $this->getProject()->hasAutomaticCapability($capability, $viewer);
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -193,4 +193,9 @@ final class ReleephProject extends ReleephDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -306,6 +306,11 @@ final class ReleephRequest extends ReleephDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -( PhabricatorCustomFieldInterface )------------------------------------ */
|
||||
|
||||
|
|
|
@ -701,6 +701,11 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -( PhabricatorMarkupInterface )----------------------------------------- */
|
||||
|
||||
|
|
|
@ -87,4 +87,8 @@ final class PhabricatorRepositoryArcanistProject
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -167,6 +167,12 @@ final class PhabricatorRepositoryCommit
|
|||
return $this->getRepository()->hasAutomaticCapability($capability, $viewer);
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht(
|
||||
'Commits inherit the policies of the repository they belong to.');
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorTokenReceiverInterface )---------------------------------- */
|
||||
|
||||
public function getUsersToNotifyOfTokenGiven() {
|
||||
|
|
|
@ -39,4 +39,11 @@ final class PhabricatorNamedQuery extends PhabricatorSearchDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht(
|
||||
'The queries you have saved are private. Only you can view or edit '.
|
||||
'them.');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -63,4 +63,8 @@ final class PhabricatorSavedQuery extends PhabricatorSearchDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -96,6 +96,12 @@ final class PhabricatorSlowvotePoll extends PhabricatorSlowvoteDAO
|
|||
return ($viewer->getPHID() == $this->getAuthorPHID());
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht(
|
||||
'The author of a poll can always view and edit it.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -( PhabricatorSubscribableInterface )----------------------------------- */
|
||||
|
||||
|
|
|
@ -27,6 +27,10 @@ final class PhabricatorToken extends PhabricatorTokenDAO
|
|||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function renderIcon() {
|
||||
// TODO: Maybe move to a View class?
|
||||
|
||||
|
|
|
@ -48,4 +48,17 @@ final class PhabricatorTokenGiven extends PhabricatorTokenDAO
|
|||
}
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
switch ($capability) {
|
||||
case PhabricatorPolicyCapability::CAN_VIEW:
|
||||
return pht(
|
||||
'A token inherits the policies of the object it is awarded to.');
|
||||
case PhabricatorPolicyCapability::CAN_EDIT:
|
||||
return pht(
|
||||
'The user who gave a token can always edit it.');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -537,4 +537,10 @@ abstract class PhabricatorApplicationTransaction
|
|||
return ($viewer->getPHID() == $this->getAuthorPHID());
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
// TODO: (T603) Exact policies are unclear here.
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -113,4 +113,9 @@ abstract class PhabricatorApplicationTransactionComment
|
|||
return ($viewer->getPHID() == $this->getAuthorPHID());
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
// TODO: (T603) Policies are murky.
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -148,11 +148,7 @@ final class PHUIHeaderView extends AphrontView {
|
|||
}
|
||||
|
||||
if ($this->policyObject) {
|
||||
$descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions(
|
||||
$this->getUser(),
|
||||
$this->policyObject,
|
||||
true);
|
||||
$property_list[] = $descriptions[PhabricatorPolicyCapability::CAN_VIEW];
|
||||
$property_list[] = $this->renderPolicyProperty($this->policyObject);
|
||||
}
|
||||
|
||||
$header[] = phutil_tag(
|
||||
|
@ -179,5 +175,31 @@ final class PHUIHeaderView extends AphrontView {
|
|||
));
|
||||
}
|
||||
|
||||
private function renderPolicyProperty(PhabricatorPolicyInterface $object) {
|
||||
$policies = PhabricatorPolicyQuery::loadPolicies(
|
||||
$this->getUser(),
|
||||
$object);
|
||||
|
||||
$view_capability = PhabricatorPolicyCapability::CAN_VIEW;
|
||||
$policy = idx($policies, $view_capability);
|
||||
if (!$policy) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$phid = $object->getPHID();
|
||||
|
||||
$icon = id(new PHUIIconView())
|
||||
->setSpriteSheet(PHUIIconView::SPRITE_STATUS)
|
||||
->setSpriteIcon($policy->getIcon());
|
||||
|
||||
$link = javelin_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/policy/explain/'.$phid.'/'.$view_capability.'/',
|
||||
'sigil' => 'workflow',
|
||||
),
|
||||
$policy->getName());
|
||||
|
||||
return array($icon, $link);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,3 +111,8 @@
|
|||
.aphront-access-dialog {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.aphront-access-dialog ul {
|
||||
margin: 12px 24px;
|
||||
list-style: circle;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue