mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
MINOR Added per-record canView, canDelete, canCreate and canEdit checks on gridfield and gridfield components #6890
This commit is contained in:
parent
f86e53bad8
commit
8b2213d56c
@ -384,8 +384,11 @@ class GridField extends FormField {
|
||||
if($total > 0) {
|
||||
$rows = array();
|
||||
foreach($list as $idx => $record) {
|
||||
if(!$record->canView()) {
|
||||
continue;
|
||||
}
|
||||
$rowContent = '';
|
||||
foreach($columns as $column) {
|
||||
foreach($this->getColumns() as $column) {
|
||||
$colContent = $this->getColumnContent($record, $column);
|
||||
// A return value of null means this columns should be skipped altogether.
|
||||
if($colContent === null) continue;
|
||||
@ -409,8 +412,10 @@ class GridField extends FormField {
|
||||
$rows[] = $row;
|
||||
}
|
||||
$content['body'] = implode("\n", $rows);
|
||||
|
||||
} else { //display a message when the grid field is empty
|
||||
}
|
||||
|
||||
// Display a message when the grid field is empty
|
||||
if(!(isset($content['body']) && $content['body'])) {
|
||||
$content['body'] = $this->createTag(
|
||||
'tr',
|
||||
array("class" => 'ss-gridfield-item ss-gridfield-no-items'),
|
||||
|
@ -69,6 +69,9 @@ class GridFieldDeleteAction implements GridField_ColumnProvider, GridField_Actio
|
||||
* @return string - the HTML for the column
|
||||
*/
|
||||
public function getColumnContent($gridField, $record, $columnName) {
|
||||
if(!$record->canDelete()) {
|
||||
return;
|
||||
}
|
||||
$field = Object::create('GridField_FormAction',
|
||||
$gridField,
|
||||
'DeleteRecord'.$record->ID,
|
||||
@ -96,6 +99,9 @@ class GridFieldDeleteAction implements GridField_ColumnProvider, GridField_Actio
|
||||
$id = $arguments['RecordID'];
|
||||
// Always deletes a record. Use GridFieldRelationDelete to detach it from the current relationship.
|
||||
$item = $gridField->getList()->byID($id);
|
||||
if(!$item->canDelete()) {
|
||||
throw new ValidationException(_t('GridFieldAction_Delete.DeletePermissionsFailure',"No delete permissions"),0);
|
||||
}
|
||||
if(!$item) return;
|
||||
$item->delete();
|
||||
}
|
||||
|
@ -72,6 +72,9 @@ class GridFieldEditAction implements GridField_ColumnProvider {
|
||||
* @return string - the HTML for the column
|
||||
*/
|
||||
public function getColumnContent($gridField, $record, $columnName) {
|
||||
if(!$record->canEdit()){
|
||||
return;
|
||||
}
|
||||
$data = new ArrayData(array(
|
||||
'Link' => Controller::join_links($gridField->Link('item'), $record->ID, 'edit')
|
||||
));
|
||||
|
@ -16,9 +16,20 @@
|
||||
*/
|
||||
class GridFieldTitle implements GridField_HTMLProvider {
|
||||
|
||||
/**
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $newEnabled = true;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var type
|
||||
*/
|
||||
protected $gridField = null;
|
||||
|
||||
function getHTMLFragments($gridField) {
|
||||
public function getHTMLFragments( $gridField) {
|
||||
$this->gridField = $gridField;
|
||||
return array(
|
||||
'header' => $gridField->customise(array(
|
||||
'NewLink' => Controller::join_links($gridField->Link('item'), 'new'),
|
||||
@ -31,7 +42,14 @@ class GridFieldTitle implements GridField_HTMLProvider {
|
||||
* Returns whether or not the "add new" button will appear when rendering this DataGrid title
|
||||
* @return bool
|
||||
*/
|
||||
function getNewEnabled() {
|
||||
public function getNewEnabled() {
|
||||
if($this->gridField) {
|
||||
$model = singleton($this->gridField->getModelClass());
|
||||
if(!$model->canCreate()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->newEnabled;
|
||||
}
|
||||
|
||||
@ -39,9 +57,7 @@ class GridFieldTitle implements GridField_HTMLProvider {
|
||||
* Enable or disable the "add new" button to add new DataGrid object instances
|
||||
* @param $enabled
|
||||
*/
|
||||
function setNewEnabled($enabled) {
|
||||
public function setNewEnabled($enabled) {
|
||||
$this->newEnabled = $enabled;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -417,6 +417,34 @@ class GridFieldTest extends SapphireTest {
|
||||
$this->setExpectedException('LogicException');
|
||||
$field->FieldHolder();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers GridField::FieldHolder
|
||||
*/
|
||||
public function testCanViewOnlyOddIDs() {
|
||||
$this->logInWithPermission();
|
||||
$list = new ArrayList(array(
|
||||
new GridFieldTest_Permissions(array("ID" => 1, "Email" => "ongi.schwimmer@example.org", 'Name' => 'Ongi Schwimmer')),
|
||||
new GridFieldTest_Permissions(array("ID" => 2, "Email" => "klaus.lozenge@example.org", 'Name' => 'Klaus Lozenge')),
|
||||
new GridFieldTest_Permissions(array("ID" => 3, "Email" => "otto.fischer@example.org", 'Name' => 'Otto Fischer'))
|
||||
));
|
||||
|
||||
$config = new GridFieldConfig();
|
||||
$config->addComponent(new GridFieldDefaultColumns());
|
||||
$obj = new GridField('testfield', 'testfield', $list, $config);
|
||||
$form = new Form(new Controller(), 'mockform', new FieldList(array($obj)), new FieldList());
|
||||
$content = new CSSContentParser($obj->FieldHolder());
|
||||
|
||||
$members = $content->getBySelector('.ss-gridfield-item tr');
|
||||
|
||||
$this->assertEquals(2, count($members));
|
||||
|
||||
$this->assertEquals((string)$members[0]->td[0], 'Ongi Schwimmer', 'First object Name should be Ongi Schwimmer');
|
||||
$this->assertEquals((string)$members[0]->td[1], 'ongi.schwimmer@example.org', 'First object Email should be ongi.schwimmer@example.org');
|
||||
|
||||
$this->assertEquals((string)$members[1]->td[0], 'Otto Fischer', 'Second object Name should be Otto Fischer');
|
||||
$this->assertEquals((string)$members[1]->td[1], 'otto.fischer@example.org', 'Second object Email should be otto.fischer@example.org');
|
||||
}
|
||||
}
|
||||
|
||||
class GridFieldTest_Component implements GridField_ColumnProvider, GridField_ActionProvider, TestOnly{
|
||||
@ -473,7 +501,6 @@ class GridFieldTest_Player extends DataObject implements TestOnly {
|
||||
static $belongs_many_many = array('Teams' => 'GridFieldTest_Team');
|
||||
}
|
||||
|
||||
|
||||
class GridFieldTest_HTMLFragments implements GridField_HTMLProvider, TestOnly{
|
||||
function __construct($fragments) {
|
||||
$this->fragments = $fragments;
|
||||
@ -482,4 +509,22 @@ class GridFieldTest_HTMLFragments implements GridField_HTMLProvider, TestOnly{
|
||||
function getHTMLFragments($gridField) {
|
||||
return $this->fragments;
|
||||
}
|
||||
}
|
||||
|
||||
class GridFieldTest_Permissions extends DataObject implements TestOnly {
|
||||
public static $db = array(
|
||||
'Name' => 'Varchar',
|
||||
'Email' => 'Varchar',
|
||||
);
|
||||
|
||||
public static $summary_fields = array(
|
||||
'Name',
|
||||
'Email'
|
||||
);
|
||||
|
||||
public function canView($member = null) {
|
||||
// Only records with odd numbers are viewable
|
||||
if(!($this->ID % 2)){ return false; }
|
||||
return true;
|
||||
}
|
||||
}
|
18
tests/forms/gridfield/GridFieldActionTest.yml
Normal file
18
tests/forms/gridfield/GridFieldActionTest.yml
Normal file
@ -0,0 +1,18 @@
|
||||
GridFieldAction_Delete_Team:
|
||||
team1:
|
||||
Name: Team 1
|
||||
City: Cologne
|
||||
team2:
|
||||
Name: Team 2
|
||||
City: Wellington
|
||||
team3:
|
||||
Name: Team 3
|
||||
City: Auckland
|
||||
|
||||
GridFieldAction_Edit_Team:
|
||||
team1:
|
||||
Name: Team 1
|
||||
City: Cologne
|
||||
team2:
|
||||
Name: Team 2
|
||||
City: Wellington
|
78
tests/forms/gridfield/GridFieldDeleteActionTest.php
Normal file
78
tests/forms/gridfield/GridFieldDeleteActionTest.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
class GridFieldDeleteActionTest extends SapphireTest {
|
||||
|
||||
/** @var ArrayList */
|
||||
protected $list;
|
||||
|
||||
/** @var GridField */
|
||||
protected $gridField;
|
||||
|
||||
/** @var Form */
|
||||
protected $form;
|
||||
|
||||
/** @var string */
|
||||
public static $fixture_file = 'sapphire/tests/forms/gridfield/GridFieldActionTest.yml';
|
||||
|
||||
/** @var array */
|
||||
protected $extraDataObjects = array('GridFieldAction_Delete_Team', 'GridFieldAction_Edit_Team');
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->list = new DataList('GridFieldAction_Delete_Team');
|
||||
$config = GridFieldConfig::create()->addComponent(new GridFieldDeleteAction());
|
||||
$this->gridField = new GridField('testfield', 'testfield', $this->list, $config);
|
||||
$this->form = new Form(new Controller(), 'mockform', new FieldList(array($this->gridField)), new FieldList());
|
||||
}
|
||||
|
||||
public function testDontShowDeleteButtons() {
|
||||
if(Member::currentUser()) { Member::currentUser()->logOut(); }
|
||||
$content = new CSSContentParser($this->gridField->FieldHolder());
|
||||
// Check that there are content
|
||||
$this->assertEquals(4, count($content->getBySelector('.ss-gridfield-item')));
|
||||
// Make sure that there are no delete buttons
|
||||
$this->assertEmpty($content->getBySelector('.gridfield-button-delete'), 'Delete buttons should not show when not logged in.');
|
||||
}
|
||||
|
||||
public function testShowDeleteButtonsWithAdminPermission() {
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$content = new CSSContentParser($this->gridField->FieldHolder());
|
||||
$deleteButtons = $content->getBySelector('.gridfield-button-delete');
|
||||
$this->assertEquals(3, count($deleteButtons), 'Delete buttons should show when logged in.');
|
||||
}
|
||||
|
||||
public function testDeleteActionWithoutCorrectPermission() {
|
||||
if(Member::currentUser()) { Member::currentUser()->logOut(); }
|
||||
$this->setExpectedException('ValidationException');
|
||||
|
||||
$stateID = 'testGridStateActionField';
|
||||
Session::set($stateID, array('grid'=>'', 'actionName'=>'deleterecord','args'=>array('RecordID'=>1)));
|
||||
$request = new SS_HTTPRequest('POST', 'url', array(), array('action_gridFieldAlterAction?StateID='.$stateID=>true));
|
||||
$this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request);
|
||||
$this->assertEquals(3, $this->list->count(), 'User should\'t be able to delete records without correct permissions.');
|
||||
}
|
||||
|
||||
public function testDeleteActionWithAdminPermission() {
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$stateID = 'testGridStateActionField';
|
||||
Session::set($stateID, array('grid'=>'', 'actionName'=>'deleterecord','args'=>array('RecordID'=>1)));
|
||||
$request = new SS_HTTPRequest('POST', 'url', array(), array('action_gridFieldAlterAction?StateID='.$stateID=>true));
|
||||
$this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request);
|
||||
$this->assertEquals(2, $this->list->count(), 'User should be able to delete records with ADMIN permission.');
|
||||
}
|
||||
}
|
||||
|
||||
class GridFieldAction_Delete_Team extends DataObject implements TestOnly {
|
||||
static $db = array(
|
||||
'Name' => 'Varchar',
|
||||
'City' => 'Varchar'
|
||||
);
|
||||
|
||||
public function canView($member = null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function canDelete($member = null) {
|
||||
return parent::canDelete($member);
|
||||
}
|
||||
}
|
55
tests/forms/gridfield/GridFieldEditActionTest.php
Normal file
55
tests/forms/gridfield/GridFieldEditActionTest.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
class GridFieldEditActionTest extends SapphireTest {
|
||||
|
||||
/** @var ArrayList */
|
||||
protected $list;
|
||||
|
||||
/** @var GridField */
|
||||
protected $gridField;
|
||||
|
||||
/** @var Form */
|
||||
protected $form;
|
||||
|
||||
/** @var string */
|
||||
public static $fixture_file = 'sapphire/tests/forms/gridfield/GridFieldActionTest.yml';
|
||||
|
||||
/** @var array */
|
||||
protected $extraDataObjects = array('GridFieldAction_Delete_Team', 'GridFieldAction_Edit_Team');
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->list = new DataList('GridFieldAction_Edit_Team');
|
||||
$config = GridFieldConfig::create()->addComponent(new GridFieldEditAction());
|
||||
$this->gridField = new GridField('testfield', 'testfield', $this->list, $config);
|
||||
$this->form = new Form(new Controller(), 'mockform', new FieldList(array($this->gridField)), new FieldList());
|
||||
}
|
||||
|
||||
public function testDontShowEditLinks() {
|
||||
if(Member::currentUser()) { Member::currentUser()->logOut(); }
|
||||
|
||||
$content = new CSSContentParser($this->gridField->FieldHolder());
|
||||
// Check that there are content
|
||||
$this->assertEquals(3, count($content->getBySelector('.ss-gridfield-item')));
|
||||
// Make sure that there are no edit links
|
||||
$this->assertEmpty($content->getBySelector('.edit-link'), 'Edit links should not show when not logged in.');
|
||||
}
|
||||
|
||||
public function testShowEditLinksWithAdminPermission() {
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$content = new CSSContentParser($this->gridField->FieldHolder());
|
||||
$editLinks = $content->getBySelector('.edit-link');
|
||||
$this->assertEquals(2, count($editLinks), 'Edit links should show when logged in.');
|
||||
}
|
||||
}
|
||||
|
||||
class GridFieldAction_Edit_Team extends DataObject implements TestOnly {
|
||||
static $db = array(
|
||||
'Name' => 'Varchar',
|
||||
'City' => 'Varchar'
|
||||
);
|
||||
|
||||
public function canView($member = null) {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@ class GridFieldPopupFormsTest extends FunctionalTest {
|
||||
|
||||
|
||||
function testAddForm() {
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$group = DataList::create('GridFieldPopupFormsTest_PeopleGroup')
|
||||
->filter('Name', 'My Group')
|
||||
->First();
|
||||
@ -45,6 +46,7 @@ class GridFieldPopupFormsTest extends FunctionalTest {
|
||||
}
|
||||
|
||||
function testEditForm() {
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$group = DataList::create('GridFieldPopupFormsTest_PeopleGroup')
|
||||
->filter('Name', 'My Group')
|
||||
->First();
|
||||
|
@ -37,6 +37,7 @@ class GridFieldRelationAddTest extends FunctionalTest {
|
||||
}
|
||||
|
||||
function testAdd() {
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$team1 = $this->objFromFixture('GridFieldTest_Team', 'team1');
|
||||
$team2 = $this->objFromFixture('GridFieldTest_Team', 'team2');
|
||||
|
||||
|
@ -3,6 +3,7 @@ class GridFieldTitleTest extends SapphireTest {
|
||||
|
||||
|
||||
public function testGridTitleAddNewEnabled() {
|
||||
$this->logInWithPermission('ADMIN');
|
||||
//construct a fake form field to render out the grid field within it
|
||||
$config = new GridFieldConfig();
|
||||
$config->addComponent($titleField = new GridFieldTitle());
|
||||
@ -17,6 +18,7 @@ class GridFieldTitleTest extends SapphireTest {
|
||||
}
|
||||
|
||||
public function testGridTitleAddNewDisabled() {
|
||||
$this->logInWithPermission('ADMIN');
|
||||
//construct a fake form field to render out the grid field within it
|
||||
$config = new GridFieldConfig();
|
||||
$config->addComponent($titleField = new GridFieldTitle());
|
||||
@ -29,5 +31,16 @@ class GridFieldTitleTest extends SapphireTest {
|
||||
$html = $form->forTemplate();
|
||||
$this->assertNotContains('data-icon="add"', $html,"HTML does not contain the 'add new' button");
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
public function testGridTitleAddNewWithoutPermission() {
|
||||
if(Member::currentUser()) { Member::currentUser()->logOut(); }
|
||||
$config = new GridFieldConfig();
|
||||
$config->addComponent($titleField = new GridFieldTitle());
|
||||
$grid = new GridField('TestField', 'Test Field', new DataList('Company'),$config);
|
||||
$fields = new FieldList(new TabSet("Root",$tabMain = new Tab('Main',$grid)));
|
||||
$form = new Form(Controller::curr(), "TestForm", $fields, new FieldList());
|
||||
|
||||
$html = $form->forTemplate();
|
||||
$this->assertNotContains('data-icon="add"', $html, "HTML should not contain the 'add new' button");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user