Merge pull request #441 from tractorcow/pulls/fix-can-permissions

BUG Fix can* permissions on non-top level objects.
This commit is contained in:
Daniel Hensby 2016-03-21 09:11:17 +00:00
commit 5da95abf27
6 changed files with 346 additions and 26 deletions

View File

@ -4,6 +4,7 @@
* A custom rule for showing / hiding an EditableFormField * A custom rule for showing / hiding an EditableFormField
* based the value of another EditableFormField. * based the value of another EditableFormField.
* *
* @method EditableFormField Parent()
* @package userforms * @package userforms
*/ */
class EditableCustomRule extends DataObject { class EditableCustomRule extends DataObject {
@ -57,4 +58,83 @@ class EditableCustomRule extends DataObject {
public function doDeleteFromStage($stage) { public function doDeleteFromStage($stage) {
$this->deleteFromStage($stage); $this->deleteFromStage($stage);
} }
/**
* @param Member $member
* @return bool
*/
public function canDelete($member = null) {
return $this->canEdit($member);
}
/**
* @param Member $member
* @return bool
*/
public function canEdit($member = null) {
return $this->Parent()->canEdit($member);
}
/**
* @param Member $member
* @return bool
*/
public function canView($member = null) {
return $this->Parent()->canView($member);
}
/**
* Return whether a user can create an object of this type
*
* @param Member $member
* @param array $context Virtual parameter to allow context to be passed in to check
* @return bool
*/
public function canCreate($member = null) {
// Check parent page
$parent = $this->getCanCreateContext(func_get_args());
if($parent) {
return $parent->canEdit($member);
}
// Fall back to secure admin permissions
return parent::canCreate($member);
}
/**
* Helper method to check the parent for this object
*
* @param array $args List of arguments passed to canCreate
* @return DataObject Some parent dataobject to inherit permissions from
*/
protected function getCanCreateContext($args) {
// Inspect second parameter to canCreate for a 'Parent' context
if(isset($args[1]['Parent'])) {
return $args[1]['Parent'];
}
// Hack in currently edited page if context is missing
if(Controller::has_curr() && Controller::curr() instanceof CMSMain) {
return Controller::curr()->currentPage();
}
// No page being edited
return null;
}
/**
* @param Member $member
* @return bool
*/
public function canPublish($member = null) {
return $this->canEdit($member);
}
/**
* @param Member $member
* @return bool
*/
public function canUnpublish($member = null) {
return $this->canDelete($member);
}
} }

View File

@ -9,7 +9,7 @@ use SilverStripe\Forms\SegmentField;
* @package userforms * @package userforms
* *
* @property string Name * @property string Name
* * @method UserDefinedForm Parent() Parent page
* @method DataList DisplayRules() List of EditableCustomRule objects * @method DataList DisplayRules() List of EditableCustomRule objects
*/ */
class EditableFormField extends DataObject { class EditableFormField extends DataObject {
@ -324,30 +324,104 @@ class EditableFormField extends DataObject {
* Return whether a user can delete this form field * Return whether a user can delete this form field
* based on whether they can edit the page * based on whether they can edit the page
* *
* @param Member $member
* @return bool * @return bool
*/ */
public function canDelete($member = null) { public function canDelete($member = null) {
if($this->Parent()) { return $this->canEdit($member);
return $this->Parent()->canEdit($member) && !$this->isReadonly();
}
return true;
} }
/** /**
* Return whether a user can edit this form field * Return whether a user can edit this form field
* based on whether they can edit the page * based on whether they can edit the page
* *
* @param Member $member
* @return bool * @return bool
*/ */
public function canEdit($member = null) { public function canEdit($member = null) {
if($this->Parent()) { $parent = $this->Parent();
return $this->Parent()->canEdit($member) && !$this->isReadonly(); if($parent && $parent->exists()) {
return $parent->canEdit($member) && !$this->isReadonly();
}
// Fallback to secure admin permissions
return parent::canEdit($member);
}
/**
* Return whether a user can view this form field
* based on whether they can view the page, regardless of the ReadOnly status of the field
*
* @param Member $member
* @return bool
*/
public function canView($member = null) {
$parent = $this->Parent();
if($parent && $parent->exists()) {
return $parent->canView($member);
} }
return true; return true;
} }
/**
* Return whether a user can create an object of this type
*
* @param Member $member
* @param array $context Virtual parameter to allow context to be passed in to check
* @return bool
*/
public function canCreate($member = null) {
// Check parent page
$parent = $this->getCanCreateContext(func_get_args());
if($parent) {
return $parent->canEdit($member);
}
// Fall back to secure admin permissions
return parent::canCreate($member);
}
/**
* Helper method to check the parent for this object
*
* @param array $args List of arguments passed to canCreate
* @return SiteTree Parent page instance
*/
protected function getCanCreateContext($args) {
// Inspect second parameter to canCreate for a 'Parent' context
if(isset($args[1]['Parent'])) {
return $args[1]['Parent'];
}
// Hack in currently edited page if context is missing
if(Controller::has_curr() && Controller::curr() instanceof CMSMain) {
return Controller::curr()->currentPage();
}
// No page being edited
return null;
}
/**
* Check if can publish
*
* @param Member $member
* @return bool
*/
public function canPublish($member = null) {
return $this->canEdit($member);
}
/**
* Check if can unpublish
*
* @param Member $member
* @return bool
*/
public function canUnpublish($member = null) {
return $this->canDelete($member);
}
/** /**
* Publish this Form Field to the live site * Publish this Form Field to the live site
* *

View File

@ -4,9 +4,9 @@
* Base Class for EditableOption Fields such as the ones used in * Base Class for EditableOption Fields such as the ones used in
* dropdown fields and in radio check box groups * dropdown fields and in radio check box groups
* *
* @method EditableMultipleOptionField Parent()
* @package userforms * @package userforms
*/ */
class EditableOption extends DataObject { class EditableOption extends DataObject {
private static $default_sort = "Sort"; private static $default_sort = "Sort";
@ -37,7 +37,7 @@ class EditableOption extends DataObject {
* @return boolean * @return boolean
*/ */
public function canEdit($member = null) { public function canEdit($member = null) {
return ($this->Parent()->canEdit($member)); return $this->Parent()->canEdit($member);
} }
/** /**
@ -46,10 +46,72 @@ class EditableOption extends DataObject {
* @return boolean * @return boolean
*/ */
public function canDelete($member = null) { public function canDelete($member = null) {
return ($this->Parent()->canDelete($member)); return $this->canEdit($member);
} }
public function getEscapedTitle() { public function getEscapedTitle() {
return Convert::raw2att($this->Title); return Convert::raw2att($this->Title);
} }
/**
* @param Member $member
* @return bool
*/
public function canView($member = null) {
return $this->Parent()->canView($member);
}
/**
* Return whether a user can create an object of this type
*
* @param Member $member
* @param array $context Virtual parameter to allow context to be passed in to check
* @return bool
*/
public function canCreate($member = null) {
// Check parent page
$parent = $this->getCanCreateContext(func_get_args());
if($parent) {
return $parent->canEdit($member);
}
// Fall back to secure admin permissions
return parent::canCreate($member);
}
/**
* Helper method to check the parent for this object
*
* @param array $args List of arguments passed to canCreate
* @return DataObject Some parent dataobject to inherit permissions from
*/
protected function getCanCreateContext($args) {
// Inspect second parameter to canCreate for a 'Parent' context
if(isset($args[1]['Parent'])) {
return $args[1]['Parent'];
}
// Hack in currently edited page if context is missing
if(Controller::has_curr() && Controller::curr() instanceof CMSMain) {
return Controller::curr()->currentPage();
}
// No page being edited
return null;
}
/**
* @param Member $member
* @return bool
*/
public function canPublish($member = null) {
return $this->canEdit($member);
}
/**
* @param Member $member
* @return bool
*/
public function canUnpublish($member = null) {
return $this->canDelete($member);
}
} }

View File

@ -265,12 +265,41 @@ class UserDefinedForm_EmailRecipient extends DataObject {
} }
/** /**
* @param Member * Return whether a user can create an object of this type
* *
* @return boolean * @param Member $member
* @param array $context Virtual parameter to allow context to be passed in to check
* @return bool
*/ */
public function canCreate($member = null) { public function canCreate($member = null) {
return $this->Form()->canCreate(); // Check parent page
$parent = $this->getCanCreateContext(func_get_args());
if($parent) {
return $parent->canEdit($member);
}
// Fall back to secure admin permissions
return parent::canCreate($member);
}
/**
* Helper method to check the parent for this object
*
* @param array $args List of arguments passed to canCreate
* @return SiteTree Parent page instance
*/
protected function getCanCreateContext($args) {
// Inspect second parameter to canCreate for a 'Parent' context
if(isset($args[1]['Form'])) {
return $args[1]['Form'];
}
// Hack in currently edited page if context is missing
if(Controller::has_curr() && Controller::curr() instanceof CMSMain) {
return Controller::curr()->currentPage();
}
// No page being edited
return null;
} }
/** /**
@ -279,7 +308,7 @@ class UserDefinedForm_EmailRecipient extends DataObject {
* @return boolean * @return boolean
*/ */
public function canView($member = null) { public function canView($member = null) {
return $this->Form()->canView(); return $this->Form()->canView($member);
} }
/** /**
@ -288,7 +317,7 @@ class UserDefinedForm_EmailRecipient extends DataObject {
* @return boolean * @return boolean
*/ */
public function canEdit($member = null) { public function canEdit($member = null) {
return $this->Form()->canEdit(); return $this->Form()->canEdit($member);
} }
/** /**
@ -297,7 +326,7 @@ class UserDefinedForm_EmailRecipient extends DataObject {
* @return boolean * @return boolean
*/ */
public function canDelete($member = null) { public function canDelete($member = null) {
return $this->Form()->canDelete(); return $this->canEdit($member);
} }
/* /*

View File

@ -3,6 +3,8 @@
/** /**
* Declares a condition that determines whether an email can be sent to a given recipient * Declares a condition that determines whether an email can be sent to a given recipient
*
* @method UserDefinedForm_EmailRecipient Parent()
*/ */
class UserDefinedForm_EmailRecipientCondition extends DataObject { class UserDefinedForm_EmailRecipientCondition extends DataObject {
@ -51,4 +53,69 @@ class UserDefinedForm_EmailRecipientCondition extends DataObject {
return ($this->ConditionOption === 'Equals') === (bool)$matches; return ($this->ConditionOption === 'Equals') === (bool)$matches;
} }
} }
/**
* Return whether a user can create an object of this type
*
* @param Member $member
* @param array $context Virtual parameter to allow context to be passed in to check
* @return bool
*/
public function canCreate($member = null) {
// Check parent page
$parent = $this->getCanCreateContext(func_get_args());
if($parent) {
return $parent->canEdit($member);
}
// Fall back to secure admin permissions
return parent::canCreate($member);
}
/**
* Helper method to check the parent for this object
*
* @param array $args List of arguments passed to canCreate
* @return SiteTree Parent page instance
*/
protected function getCanCreateContext($args) {
// Inspect second parameter to canCreate for a 'Parent' context
if(isset($args[1]['Parent'])) {
return $args[1]['Parent'];
}
// Hack in currently edited page if context is missing
if(Controller::has_curr() && Controller::curr() instanceof CMSMain) {
return Controller::curr()->currentPage();
}
// No page being edited
return null;
}
/**
* @param Member
*
* @return boolean
*/
public function canView($member = null) {
return $this->Parent()->canView($member);
}
/**
* @param Member
*
* @return boolean
*/
public function canEdit($member = null) {
return $this->Parent()->canEdit($member);
}
/**
* @param Member
*
* @return boolean
*/
public function canDelete($member = null) {
return $this->canEdit($member);
}
} }

View File

@ -12,14 +12,18 @@ class EditableFormFieldTest extends FunctionalTest {
$text = $this->objFromFixture('EditableTextField', 'basic-text'); $text = $this->objFromFixture('EditableTextField', 'basic-text');
$this->logInWithPermission('ADMIN'); $this->logInWithPermission('ADMIN');
$this->assertTrue($text->canCreate());
$this->assertTrue($text->canView());
$this->assertTrue($text->canEdit()); $this->assertTrue($text->canEdit());
$this->assertTrue($text->canDelete()); $this->assertTrue($text->canDelete());
$text->setReadonly(true); $text->setReadonly(true);
$this->assertTrue($text->canView());
$this->assertFalse($text->canEdit()); $this->assertFalse($text->canEdit());
$this->assertFalse($text->canDelete()); $this->assertFalse($text->canDelete());
$text->setReadonly(false); $text->setReadonly(false);
$this->assertTrue($text->canView());
$this->assertTrue($text->canEdit()); $this->assertTrue($text->canEdit());
$this->assertTrue($text->canDelete()); $this->assertTrue($text->canDelete());
@ -27,11 +31,15 @@ class EditableFormFieldTest extends FunctionalTest {
$member->logout(); $member->logout();
$this->logInWithPermission('SITETREE_VIEW_ALL'); $this->logInWithPermission('SITETREE_VIEW_ALL');
$this->assertFalse($text->canCreate());
$text->setReadonly(false); $text->setReadonly(false);
$this->assertTrue($text->canView());
$this->assertFalse($text->canEdit()); $this->assertFalse($text->canEdit());
$this->assertFalse($text->canDelete()); $this->assertFalse($text->canDelete());
$text->setReadonly(true); $text->setReadonly(true);
$this->assertTrue($text->canView());
$this->assertFalse($text->canEdit()); $this->assertFalse($text->canEdit());
$this->assertFalse($text->canDelete()); $this->assertFalse($text->canDelete());
} }