1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-26 23:40:57 +01:00

Provide default view and edit policies in Calendar, plus "Event Host" and "Event Invitees"

Summary:
Fixes T9224. This adds:

  - A "Default Edit Policy" and "Default View Policy" to Calendar, similar to other applications.
  - "Event Host" and "Event Invitees" objects policies.

These policies often end up being redundant (the host can always view/edit, the invitees can always view), but they can be more clear than setting "No One", and "Editable By: Event Invitees" is a legitimately useful policy.

Test Plan:
  - Created and edited events.
  - Fiddled with defaults.
  - Tried to remove myself as the event host for an "Editable By: Host" event, got an error ("you wouldn't be able to edit").
  - Tried to remove myself as host/invitee for an "Editable By: Invitees" event, got an error.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9224

Differential Revision: https://secure.phabricator.com/D16294
This commit is contained in:
epriestley 2016-07-13 12:55:22 -07:00
parent 3227292073
commit 6eaa9faec7
8 changed files with 226 additions and 2 deletions

View file

@ -2026,6 +2026,8 @@ phutil_register_library_map(array(
'PhabricatorCalendarEventCancelTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventCancelTransaction.php',
'PhabricatorCalendarEventDateTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventDateTransaction.php',
'PhabricatorCalendarEventDeclineTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventDeclineTransaction.php',
'PhabricatorCalendarEventDefaultEditCapability' => 'applications/calendar/capability/PhabricatorCalendarEventDefaultEditCapability.php',
'PhabricatorCalendarEventDefaultViewCapability' => 'applications/calendar/capability/PhabricatorCalendarEventDefaultViewCapability.php',
'PhabricatorCalendarEventDescriptionTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventDescriptionTransaction.php',
'PhabricatorCalendarEventDragController' => 'applications/calendar/controller/PhabricatorCalendarEventDragController.php',
'PhabricatorCalendarEventEditConduitAPIMethod' => 'applications/calendar/conduit/PhabricatorCalendarEventEditConduitAPIMethod.php',
@ -2036,11 +2038,13 @@ phutil_register_library_map(array(
'PhabricatorCalendarEventEndDateTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventEndDateTransaction.php',
'PhabricatorCalendarEventFrequencyTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventFrequencyTransaction.php',
'PhabricatorCalendarEventFulltextEngine' => 'applications/calendar/search/PhabricatorCalendarEventFulltextEngine.php',
'PhabricatorCalendarEventHostPolicyRule' => 'applications/calendar/policyrule/PhabricatorCalendarEventHostPolicyRule.php',
'PhabricatorCalendarEventHostTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventHostTransaction.php',
'PhabricatorCalendarEventIconTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventIconTransaction.php',
'PhabricatorCalendarEventInviteTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventInviteTransaction.php',
'PhabricatorCalendarEventInvitee' => 'applications/calendar/storage/PhabricatorCalendarEventInvitee.php',
'PhabricatorCalendarEventInviteeQuery' => 'applications/calendar/query/PhabricatorCalendarEventInviteeQuery.php',
'PhabricatorCalendarEventInviteesPolicyRule' => 'applications/calendar/policyrule/PhabricatorCalendarEventInviteesPolicyRule.php',
'PhabricatorCalendarEventJoinController' => 'applications/calendar/controller/PhabricatorCalendarEventJoinController.php',
'PhabricatorCalendarEventListController' => 'applications/calendar/controller/PhabricatorCalendarEventListController.php',
'PhabricatorCalendarEventMailReceiver' => 'applications/calendar/mail/PhabricatorCalendarEventMailReceiver.php',
@ -6654,6 +6658,8 @@ phutil_register_library_map(array(
'PhabricatorCalendarEventCancelTransaction' => 'PhabricatorCalendarEventTransactionType',
'PhabricatorCalendarEventDateTransaction' => 'PhabricatorCalendarEventTransactionType',
'PhabricatorCalendarEventDeclineTransaction' => 'PhabricatorCalendarEventReplyTransaction',
'PhabricatorCalendarEventDefaultEditCapability' => 'PhabricatorPolicyCapability',
'PhabricatorCalendarEventDefaultViewCapability' => 'PhabricatorPolicyCapability',
'PhabricatorCalendarEventDescriptionTransaction' => 'PhabricatorCalendarEventTransactionType',
'PhabricatorCalendarEventDragController' => 'PhabricatorCalendarController',
'PhabricatorCalendarEventEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
@ -6664,6 +6670,7 @@ phutil_register_library_map(array(
'PhabricatorCalendarEventEndDateTransaction' => 'PhabricatorCalendarEventDateTransaction',
'PhabricatorCalendarEventFrequencyTransaction' => 'PhabricatorCalendarEventTransactionType',
'PhabricatorCalendarEventFulltextEngine' => 'PhabricatorFulltextEngine',
'PhabricatorCalendarEventHostPolicyRule' => 'PhabricatorPolicyRule',
'PhabricatorCalendarEventHostTransaction' => 'PhabricatorCalendarEventTransactionType',
'PhabricatorCalendarEventIconTransaction' => 'PhabricatorCalendarEventTransactionType',
'PhabricatorCalendarEventInviteTransaction' => 'PhabricatorCalendarEventTransactionType',
@ -6672,6 +6679,7 @@ phutil_register_library_map(array(
'PhabricatorPolicyInterface',
),
'PhabricatorCalendarEventInviteeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorCalendarEventInviteesPolicyRule' => 'PhabricatorPolicyRule',
'PhabricatorCalendarEventJoinController' => 'PhabricatorCalendarController',
'PhabricatorCalendarEventListController' => 'PhabricatorCalendarController',
'PhabricatorCalendarEventMailReceiver' => 'PhabricatorObjectMailReceiver',

View file

@ -83,4 +83,19 @@ final class PhabricatorCalendarApplication extends PhabricatorApplication {
);
}
protected function getCustomCapabilities() {
return array(
PhabricatorCalendarEventDefaultViewCapability::CAPABILITY => array(
'caption' => pht('Default view policy for newly created events.'),
'template' => PhabricatorCalendarEventPHIDType::TYPECONST,
'capability' => PhabricatorPolicyCapability::CAN_VIEW,
),
PhabricatorCalendarEventDefaultEditCapability::CAPABILITY => array(
'caption' => pht('Default edit policy for newly created events.'),
'template' => PhabricatorCalendarEventPHIDType::TYPECONST,
'capability' => PhabricatorPolicyCapability::CAN_EDIT,
),
);
}
}

View file

@ -0,0 +1,12 @@
<?php
final class PhabricatorCalendarEventDefaultEditCapability
extends PhabricatorPolicyCapability {
const CAPABILITY = 'calendar.event.default.edit';
public function getCapabilityName() {
return pht('Default Edit Policy');
}
}

View file

@ -0,0 +1,16 @@
<?php
final class PhabricatorCalendarEventDefaultViewCapability
extends PhabricatorPolicyCapability {
const CAPABILITY = 'calendar.event.default.view';
public function getCapabilityName() {
return pht('Default View Policy');
}
public function shouldAllowPublicPolicySetting() {
return true;
}
}

View file

@ -65,6 +65,29 @@ final class PhabricatorCalendarEventEditor
return $types;
}
protected function adjustObjectForPolicyChecks(
PhabricatorLiskDAO $object,
array $xactions) {
$copy = parent::adjustObjectForPolicyChecks($object, $xactions);
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorCalendarEventHostTransaction::TRANSACTIONTYPE:
$copy->setHostPHID($xaction->getNewValue());
break;
case PhabricatorCalendarEventInviteTransaction::TRANSACTIONTYPE:
PhabricatorPolicyRule::passTransactionHintToRule(
$copy,
new PhabricatorCalendarEventInviteesPolicyRule(),
array_fuse($xaction->getNewValue()));
break;
}
}
return $copy;
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {

View file

@ -0,0 +1,43 @@
<?php
final class PhabricatorCalendarEventHostPolicyRule
extends PhabricatorPolicyRule {
public function getObjectPolicyKey() {
return 'calendar.event.host';
}
public function getObjectPolicyName() {
return pht('Event Host');
}
public function getPolicyExplanation() {
return pht('The host of this event can take this action.');
}
public function getRuleDescription() {
return pht('event host');
}
public function canApplyToObject(PhabricatorPolicyInterface $object) {
return ($object instanceof PhabricatorCalendarEvent);
}
public function applyRule(
PhabricatorUser $viewer,
$value,
PhabricatorPolicyInterface $object) {
$viewer_phid = $viewer->getPHID();
if (!$viewer_phid) {
return false;
}
return ($object->getHostPHID() == $viewer_phid);
}
public function getValueControlType() {
return self::CONTROL_TYPE_NONE;
}
}

View file

@ -0,0 +1,104 @@
<?php
final class PhabricatorCalendarEventInviteesPolicyRule
extends PhabricatorPolicyRule {
private $invited = array();
private $sourcePHIDs = array();
public function getObjectPolicyKey() {
return 'calendar.event.invitees';
}
public function getObjectPolicyName() {
return pht('Event Invitees');
}
public function getPolicyExplanation() {
return pht('Users invited to this event can take this action.');
}
public function getRuleDescription() {
return pht('event invitees');
}
public function canApplyToObject(PhabricatorPolicyInterface $object) {
return ($object instanceof PhabricatorCalendarEvent);
}
public function willApplyRules(
PhabricatorUser $viewer,
array $values,
array $objects) {
$viewer_phid = $viewer->getPHID();
if (!$viewer_phid) {
return;
}
if (empty($this->invited[$viewer_phid])) {
$this->invited[$viewer_phid] = array();
}
if (!isset($this->sourcePHIDs[$viewer_phid])) {
$source_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
$viewer_phid,
PhabricatorProjectMemberOfProjectEdgeType::EDGECONST);
$source_phids[] = $viewer_phid;
$this->sourcePHIDs[$viewer_phid] = $source_phids;
}
foreach ($objects as $key => $object) {
$cache = $this->getTransactionHint($object);
if ($cache === null) {
// We don't have a hint for this object, so we'll deal with it below.
continue;
}
// We have a hint, so use that as the source of truth.
unset($objects[$key]);
foreach ($this->sourcePHIDs[$viewer_phid] as $source_phid) {
if (isset($cache[$source_phid])) {
$this->invited[$viewer_phid][$object->getPHID()] = true;
break;
}
}
}
$phids = mpull($objects, 'getPHID');
if (!$phids) {
return;
}
$invited = id(new PhabricatorCalendarEventInvitee())->loadAllWhere(
'eventPHID IN (%Ls)
AND inviteePHID IN (%Ls)
AND status != %s',
$phids,
$this->sourcePHIDs[$viewer_phid],
PhabricatorCalendarEventInvitee::STATUS_UNINVITED);
$invited = mpull($invited, 'getEventPHID');
$this->invited[$viewer_phid] += array_fill_keys($invited, true);
}
public function applyRule(
PhabricatorUser $viewer,
$value,
PhabricatorPolicyInterface $object) {
$viewer_phid = $viewer->getPHID();
if (!$viewer_phid) {
return false;
}
$invited = idx($this->invited, $viewer_phid);
return isset($invited[$object->getPHID()]);
}
public function getValueControlType() {
return self::CONTROL_TYPE_NONE;
}
}

View file

@ -57,7 +57,10 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
->withClasses(array('PhabricatorCalendarApplication'))
->executeOne();
$view_policy = PhabricatorPolicies::getMostOpenPolicy();
$view_default = PhabricatorCalendarEventDefaultViewCapability::CAPABILITY;
$edit_default = PhabricatorCalendarEventDefaultEditCapability::CAPABILITY;
$view_policy = $app->getPolicy($view_default);
$edit_policy = $app->getPolicy($edit_default);
$start = new DateTime('@'.PhabricatorTime::getNow());
$start->setTimeZone($actor->getTimeZone());
@ -83,7 +86,7 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
))
->setIcon($default_icon)
->setViewPolicy($view_policy)
->setEditPolicy($actor->getPHID())
->setEditPolicy($edit_policy)
->setSpacePHID($actor->getDefaultSpacePHID())
->attachInvitees(array())
->setDateFrom($epoch_min)