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:
parent
3227292073
commit
6eaa9faec7
8 changed files with 226 additions and 2 deletions
|
@ -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',
|
||||
|
|
|
@ -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,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorCalendarEventDefaultEditCapability
|
||||
extends PhabricatorPolicyCapability {
|
||||
|
||||
const CAPABILITY = 'calendar.event.default.edit';
|
||||
|
||||
public function getCapabilityName() {
|
||||
return pht('Default Edit Policy');
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue