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
* based the value of another EditableFormField.
*
* @method EditableFormField Parent()
* @package userforms
*/
class EditableCustomRule extends DataObject {
@ -57,4 +58,83 @@ class EditableCustomRule extends DataObject {
public function doDeleteFromStage($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
*
* @property string Name
*
* @method UserDefinedForm Parent() Parent page
* @method DataList DisplayRules() List of EditableCustomRule objects
*/
class EditableFormField extends DataObject {
@ -320,34 +320,108 @@ class EditableFormField extends DataObject {
return false;
}
/**
* Return whether a user can delete this form field
* based on whether they can edit the page
*
* @return bool
*/
/**
* Return whether a user can delete this form field
* based on whether they can edit the page
*
* @param Member $member
* @return bool
*/
public function canDelete($member = null) {
if($this->Parent()) {
return $this->Parent()->canEdit($member) && !$this->isReadonly();
return $this->canEdit($member);
}
/**
* Return whether a user can edit this form field
* based on whether they can edit the page
*
* @param Member $member
* @return bool
*/
public function canEdit($member = null) {
$parent = $this->Parent();
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 whether a user can edit this form field
* based on whether they can edit the page
* 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 canEdit($member = null) {
if($this->Parent()) {
return $this->Parent()->canEdit($member) && !$this->isReadonly();
}
public function canCreate($member = null) {
// Check parent page
$parent = $this->getCanCreateContext(func_get_args());
if($parent) {
return $parent->canEdit($member);
}
return true;
// 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
*

View File

@ -4,9 +4,9 @@
* Base Class for EditableOption Fields such as the ones used in
* dropdown fields and in radio check box groups
*
* @method EditableMultipleOptionField Parent()
* @package userforms
*/
class EditableOption extends DataObject {
private static $default_sort = "Sort";
@ -37,7 +37,7 @@ class EditableOption extends DataObject {
* @return boolean
*/
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
*/
public function canDelete($member = null) {
return ($this->Parent()->canDelete($member));
return $this->canEdit($member);
}
public function getEscapedTitle() {
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,21 +265,50 @@ 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) {
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;
}
/**
* @param Member
*
* @return boolean
*/
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
*/
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
*/
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
*
* @method UserDefinedForm_EmailRecipient Parent()
*/
class UserDefinedForm_EmailRecipientCondition extends DataObject {
@ -51,4 +53,69 @@ class UserDefinedForm_EmailRecipientCondition extends DataObject {
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');
$this->logInWithPermission('ADMIN');
$this->assertTrue($text->canCreate());
$this->assertTrue($text->canView());
$this->assertTrue($text->canEdit());
$this->assertTrue($text->canDelete());
$text->setReadonly(true);
$this->assertTrue($text->canView());
$this->assertFalse($text->canEdit());
$this->assertFalse($text->canDelete());
$text->setReadonly(false);
$this->assertTrue($text->canView());
$this->assertTrue($text->canEdit());
$this->assertTrue($text->canDelete());
@ -27,11 +31,15 @@ class EditableFormFieldTest extends FunctionalTest {
$member->logout();
$this->logInWithPermission('SITETREE_VIEW_ALL');
$this->assertFalse($text->canCreate());
$text->setReadonly(false);
$this->assertTrue($text->canView());
$this->assertFalse($text->canEdit());
$this->assertFalse($text->canDelete());
$text->setReadonly(true);
$this->assertTrue($text->canView());
$this->assertFalse($text->canEdit());
$this->assertFalse($text->canDelete());
}