mirror of
https://github.com/silverstripe/silverstripe-dms
synced 2024-10-22 14:05:56 +02:00
Merge pull request #168 from creative-commoners/issue/150
FIX document and documentset permissions
This commit is contained in:
commit
d57fc88bfa
@ -316,4 +316,29 @@ class DMSDocumentAddController extends LeftAndMain
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the parent method to allow users with access to DMS admin to access this controller
|
||||
*
|
||||
* @param Member $member
|
||||
* @return bool
|
||||
*/
|
||||
public function canView($member = null)
|
||||
{
|
||||
if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) {
|
||||
$member = Member::currentUser();
|
||||
}
|
||||
|
||||
if ($member &&
|
||||
Permission::checkMember(
|
||||
$member,
|
||||
array(
|
||||
'CMS_ACCESS_DMSDocumentAdmin',
|
||||
)
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return parent::canView($member);
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ class DMSDocumentAdmin extends ModelAdmin
|
||||
parent::init();
|
||||
Requirements::javascript(DMS_DIR . '/javascript/DMSGridField.js');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the default "add" button and replace it with a customised version for DMS
|
||||
*
|
||||
@ -45,6 +44,9 @@ class DMSDocumentAdmin extends ModelAdmin
|
||||
{
|
||||
$gridFieldConfig = $gridField->getConfig();
|
||||
|
||||
$gridFieldConfig->removeComponentsByType('GridFieldEditButton');
|
||||
$gridFieldConfig->addComponent(new DMSGridFieldEditButton(), 'GridFieldDeleteAction');
|
||||
|
||||
if ($this->modelClass === 'DMSDocument') {
|
||||
$gridFieldConfig->removeComponentsByType('GridFieldAddNewButton');
|
||||
$gridFieldConfig->addComponent(
|
||||
|
26
code/cms/DMSGridFieldEditButton.php
Executable file
26
code/cms/DMSGridFieldEditButton.php
Executable file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
class DMSGridFieldEditButton extends GridFieldEditButton implements GridField_ColumnProvider
|
||||
{
|
||||
|
||||
/**
|
||||
* Overriding the parent method to change the template that the DMS edit button will be rendered with based on
|
||||
* whether or not the user has edit permissions.
|
||||
*
|
||||
* @param GridField $gridField
|
||||
* @param DataObject $record
|
||||
* @param string $columnName
|
||||
*
|
||||
* @return string - the HTML for the column
|
||||
*/
|
||||
public function getColumnContent($gridField, $record, $columnName)
|
||||
{
|
||||
$data = new ArrayData(array(
|
||||
'Link' => Controller::join_links($gridField->Link('item'), $record->ID, 'edit')
|
||||
));
|
||||
|
||||
$template = $record->canEdit() ? 'GridFieldEditButton' : 'GridFieldViewButton';
|
||||
|
||||
return $data->renderWith($template);
|
||||
}
|
||||
}
|
@ -16,6 +16,15 @@ class DMSSiteTreeExtension extends DataExtension
|
||||
return;
|
||||
}
|
||||
|
||||
// Hides the DocumentSets tab if the user has no permisions
|
||||
if (!Permission::checkMember(
|
||||
Member::currentUser(),
|
||||
array('ADMIN', 'CMS_ACCESS_DMSDocumentAdmin')
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$gridField = GridField::create(
|
||||
'Document Sets',
|
||||
false,
|
||||
|
@ -116,7 +116,6 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
||||
if (!$this->CanViewType || $this->CanViewType == 'Anyone') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($member && Permission::checkMember($member, array(
|
||||
'ADMIN',
|
||||
'SITETREE_EDIT_ALL',
|
||||
@ -198,6 +197,13 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
||||
}
|
||||
}
|
||||
|
||||
// Do early admin check
|
||||
if ($member &&
|
||||
Permission::checkMember($member, array('CMS_ACCESS_DMSDocumentAdmin'))
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->canEdit($member);
|
||||
}
|
||||
|
||||
@ -220,7 +226,7 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
||||
}
|
||||
}
|
||||
|
||||
return $this->canView();
|
||||
return $this->canEdit($member);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -838,8 +844,6 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
||||
$this->addActionPanelTask('find-versions', 'Versions');
|
||||
}
|
||||
|
||||
$fields->add(LiteralField::create('BottomTaskSelection', $this->getActionTaskHtml()));
|
||||
|
||||
$embargoValue = 'None';
|
||||
if ($this->EmbargoedIndefinitely) {
|
||||
$embargoValue = 'Indefinitely';
|
||||
@ -894,12 +898,19 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
||||
FieldGroup::create($uploadField)->addExtraClass('replace'),
|
||||
FieldGroup::create($pagesGrid)->addExtraClass('find-usage'),
|
||||
FieldGroup::create($referencesGrid)->addExtraClass('find-references'),
|
||||
FieldGroup::create($versionsGrid)->addExtraClass('find-versions'),
|
||||
FieldGroup::create($this->getRelatedDocumentsGridField())->addExtraClass('find-relateddocuments'),
|
||||
FieldGroup::create($this->getPermissionsActionPanel())->addExtraClass('permissions')
|
||||
);
|
||||
|
||||
$actionsPanel->setName("ActionsPanel");
|
||||
if ($this->canEdit()) {
|
||||
$actionsPanel->push(FieldGroup::create($versionsGrid)->addExtraClass('find-versions'));
|
||||
$actionsPanel->push(
|
||||
FieldGroup::create($this->getRelatedDocumentsGridField())->addExtraClass('find-relateddocuments')
|
||||
);
|
||||
} else {
|
||||
$this->removeActionPanelTask('find-relateddocuments')->removeActionPanelTask('find-versions');
|
||||
}
|
||||
$fields->add(LiteralField::create('BottomTaskSelection', $this->getActionTaskHtml()));
|
||||
$actionsPanel->setName('ActionsPanel');
|
||||
$actionsPanel->addExtraClass('dmsdocument-actionspanel');
|
||||
$fields->push($actionsPanel);
|
||||
|
||||
@ -1204,6 +1215,10 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
||||
new GridFieldConfig_RelationEditor
|
||||
);
|
||||
|
||||
$gridFieldConfig = $gridField->getConfig();
|
||||
$gridFieldConfig->removeComponentsByType('GridFieldEditButton');
|
||||
$gridFieldConfig->addComponent(new DMSGridFieldEditButton(), 'GridFieldDeleteAction');
|
||||
|
||||
$gridField->getConfig()->removeComponentsByType('GridFieldAddNewButton');
|
||||
// Move the autocompleter to the left
|
||||
$gridField->getConfig()->removeComponentsByType('GridFieldAddExistingAutocompleter');
|
||||
@ -1219,7 +1234,6 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
||||
$addExisting->setResultsFormat('$Filename');
|
||||
|
||||
$this->extend('updateRelatedDocumentsGridField', $gridField);
|
||||
|
||||
return $gridField;
|
||||
}
|
||||
|
||||
@ -1323,4 +1337,18 @@ class DMSDocument extends DataObject implements DMSDocumentInterface
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an "action panel" tasks
|
||||
*
|
||||
* @param string $panelKey
|
||||
* @return $this
|
||||
*/
|
||||
public function removeActionPanelTask($panelKey)
|
||||
{
|
||||
if (array_key_exists($panelKey, $this->actionTasks)) {
|
||||
unset($this->actionTasks[$panelKey]);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ class DMSDocumentSet extends DataObject
|
||||
new GridFieldFilterHeader(),
|
||||
new GridFieldSortableHeader(),
|
||||
new GridFieldDataColumns(),
|
||||
new GridFieldEditButton(),
|
||||
new DMSGridFieldEditButton(),
|
||||
// Special delete dialog to handle custom behaviour of unlinking and deleting
|
||||
new GridFieldDeleteAction(true),
|
||||
new GridFieldDetailForm()
|
||||
@ -121,6 +121,13 @@ class DMSDocumentSet extends DataObject
|
||||
$fields->fieldByName('Root.Main.PageID')->setTitle(_t('DMSDocumentSet.SHOWONPAGE', 'Show on page'));
|
||||
}
|
||||
|
||||
// Don't show which page this is if we're already editing within a page context
|
||||
if (Controller::curr() instanceof CMSPageEditController) {
|
||||
$fields->removeByName('PageID');
|
||||
} else {
|
||||
$fields->fieldByName('Root.Main.PageID')->setTitle(_t('DMSDocumentSet.SHOWONPAGE', 'Show on page'));
|
||||
}
|
||||
|
||||
$gridFieldConfig->getComponentByType('GridFieldDataColumns')
|
||||
->setDisplayFields($self->getDocumentDisplayFields())
|
||||
->setFieldCasting(array('LastEdited' => 'Datetime->Ago'))
|
||||
@ -348,4 +355,63 @@ class DMSDocumentSet extends DataObject
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function canView($member = null)
|
||||
{
|
||||
$extended = $this->extendedCan(__FUNCTION__, $member);
|
||||
if ($extended !== null) {
|
||||
return $extended;
|
||||
}
|
||||
return $this->getGlobalPermission($member);
|
||||
}
|
||||
|
||||
public function canCreate($member = null)
|
||||
{
|
||||
$extended = $this->extendedCan(__FUNCTION__, $member);
|
||||
if ($extended !== null) {
|
||||
return $extended;
|
||||
}
|
||||
return $this->getGlobalPermission($member);
|
||||
}
|
||||
|
||||
public function canEdit($member = null)
|
||||
{
|
||||
$extended = $this->extendedCan(__FUNCTION__, $member);
|
||||
if ($extended !== null) {
|
||||
return $extended;
|
||||
}
|
||||
return $this->getGlobalPermission($member);
|
||||
}
|
||||
|
||||
public function canDelete($member = null)
|
||||
{
|
||||
$extended = $this->extendedCan(__FUNCTION__, $member);
|
||||
if ($extended !== null) {
|
||||
return $extended;
|
||||
}
|
||||
return $this->getGlobalPermission($member);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a then given (or logged in) member is either an ADMIN, SITETREE_EDIT_ALL or has access
|
||||
* to the DMSDocumentAdmin module, in which case permissions is granted.
|
||||
*
|
||||
* @param Member $member
|
||||
* @return bool
|
||||
*/
|
||||
public function getGlobalPermission(Member $member = null)
|
||||
{
|
||||
if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) {
|
||||
$member = Member::currentUser();
|
||||
}
|
||||
|
||||
$result = ($member &&
|
||||
Permission::checkMember(
|
||||
$member,
|
||||
array('ADMIN', 'SITETREE_EDIT_ALL', 'CMS_ACCESS_DMSDocumentAdmin')
|
||||
)
|
||||
);
|
||||
|
||||
return (bool) $result;
|
||||
}
|
||||
}
|
||||
|
@ -244,4 +244,27 @@ class DMSDocumentSetTest extends SapphireTest
|
||||
$fields = $set->getCMSFields();
|
||||
$this->assertNull($fields->fieldByName('Root.Main.PageID'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests all crud permissions
|
||||
*/
|
||||
public function testPermissions()
|
||||
{
|
||||
if ($member = Member::currentUser()) {
|
||||
$member->logout();
|
||||
}
|
||||
|
||||
$set = $this->objFromFixture('DMSDocumentSet', 'ds1');
|
||||
|
||||
$this->assertFalse($set->canCreate());
|
||||
$this->assertFalse($set->canDelete());
|
||||
$this->assertFalse($set->canEdit());
|
||||
$this->assertFalse($set->canView());
|
||||
|
||||
$this->logInWithPermission('CMS_ACCESS_DMSDocumentAdmin');
|
||||
$this->assertTrue($set->canCreate());
|
||||
$this->assertTrue($set->canDelete());
|
||||
$this->assertTrue($set->canEdit());
|
||||
$this->assertTrue($set->canView());
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,9 @@ class DMSDocumentTest extends SapphireTest
|
||||
public function testDocumentHasCmsFieldForManagingRelatedDocuments()
|
||||
{
|
||||
$document = $this->objFromFixture('DMSDocument', 'document_with_relations');
|
||||
$gridField = $this->getGridFieldFromDocument($document);
|
||||
$gridField = $this->getRelatedDocumentsGridField($document);
|
||||
$this->assertInstanceOf('GridField', $gridField);
|
||||
|
||||
$gridFieldConfig = $gridField->getConfig();
|
||||
|
||||
$this->assertNotNull(
|
||||
@ -64,13 +66,25 @@ class DMSDocumentTest extends SapphireTest
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the DMS Document CMS Related and Versions fields are removed if user can't edit
|
||||
*/
|
||||
public function testDocumentHasNoCMSFieldsForManagingRelatedDocumentsIfCantEdit()
|
||||
{
|
||||
$this->logInWithPermission('another-user');
|
||||
$document = $this->objFromFixture('DMSDocument', 'doc-only-these-users');
|
||||
$gridField = $this->getRelatedDocumentsGridField($document);
|
||||
$this->assertNull($gridField);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the related documents list does not include the current document itself
|
||||
*/
|
||||
public function testGetRelatedDocumentsForAutocompleter()
|
||||
{
|
||||
$document = $this->objFromFixture('DMSDocument', 'd1');
|
||||
$gridField = $this->getGridFieldFromDocument($document);
|
||||
$gridField = $this->getRelatedDocumentsGridField($document);
|
||||
$this->assertInstanceOf('GridField', $gridField);
|
||||
|
||||
$config = $gridField->getConfig();
|
||||
|
||||
@ -90,7 +104,7 @@ class DMSDocumentTest extends SapphireTest
|
||||
/**
|
||||
* @return GridField
|
||||
*/
|
||||
protected function getGridFieldFromDocument(DMSDocument $document)
|
||||
protected function getRelatedDocumentsGridField(DMSDocument $document)
|
||||
{
|
||||
$documentFields = $document->getCMSFields();
|
||||
/** @var FieldGroup $actions */
|
||||
@ -103,7 +117,6 @@ class DMSDocumentTest extends SapphireTest
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->assertInstanceOf('GridField', $gridField);
|
||||
return $gridField;
|
||||
}
|
||||
|
||||
@ -121,6 +134,19 @@ class DMSDocumentTest extends SapphireTest
|
||||
$this->assertContains('<li class="ss-ui-button dmsdocument-action" data-panel="', $result);
|
||||
$this->assertContains('permission', $result);
|
||||
$this->assertContains('Example', $result);
|
||||
|
||||
$actions = array('example', 'embargo','find-usage');
|
||||
foreach ($actions as $action) {
|
||||
// Test remove with string
|
||||
$document->removeActionPanelTask($action);
|
||||
}
|
||||
$result = $document->getActionTaskHtml();
|
||||
|
||||
$this->assertNotContains('Example', $result);
|
||||
$this->assertNotContains('embargo', $result);
|
||||
$this->assertNotContains('find-usage', $result);
|
||||
// Positive test to see some action still remains
|
||||
$this->assertContains('find-references', $result);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -142,11 +168,7 @@ class DMSDocumentTest extends SapphireTest
|
||||
{
|
||||
/** @var DMSDocument $document */
|
||||
$document = $this->objFromFixture('DMSDocument', 'doc-logged-in-users');
|
||||
// Make sure user is logged out
|
||||
if ($member = Member::currentUser()) {
|
||||
$member->logOut();
|
||||
}
|
||||
|
||||
$this->logoutMember();
|
||||
// Logged out user test
|
||||
$this->assertFalse($document->canView());
|
||||
|
||||
@ -178,10 +200,7 @@ class DMSDocumentTest extends SapphireTest
|
||||
*/
|
||||
public function testCanEdit()
|
||||
{
|
||||
// Make sure user is logged out
|
||||
if ($member = Member::currentUser()) {
|
||||
$member->logOut();
|
||||
}
|
||||
$this->logoutMember();
|
||||
|
||||
/** @var DMSDocument $document1 */
|
||||
$document1 = $this->objFromFixture('DMSDocument', 'doc-logged-in-users');
|
||||
@ -204,6 +223,50 @@ class DMSDocumentTest extends SapphireTest
|
||||
$this->assertTrue($document2->canEdit($cableGuy));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests delete permissions
|
||||
*/
|
||||
public function testCanDelete()
|
||||
{
|
||||
$this->logoutMember();
|
||||
$document1 = $this->objFromFixture('DMSDocument', 'doc-logged-in-users');
|
||||
|
||||
// Logged out user test
|
||||
$this->assertFalse($document1->canDelete());
|
||||
|
||||
// Test editors can delete
|
||||
$contentAuthor = $this->objFromFixture('Member', 'editor');
|
||||
$this->assertTrue($document1->canDelete($contentAuthor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests create permission
|
||||
*/
|
||||
public function testCanCreate()
|
||||
{
|
||||
$this->logoutMember();
|
||||
$document1 = $this->objFromFixture('DMSDocument', 'doc-logged-in-users');
|
||||
$this->logInWithPermission('CMS_ACCESS_DMSDocumentAdmin');
|
||||
// Test CMS access can create
|
||||
$this->assertTrue($document1->canCreate());
|
||||
|
||||
$this->logoutMember();
|
||||
|
||||
// Test editors can create
|
||||
$contentAuthor = $this->objFromFixture('Member', 'editor');
|
||||
$this->assertTrue($document1->canCreate($contentAuthor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs out any active member
|
||||
*/
|
||||
protected function logoutMember()
|
||||
{
|
||||
if ($member = Member::currentUser()) {
|
||||
$member->logOut();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test permission denied reasons for documents
|
||||
*/
|
||||
|
@ -12,9 +12,9 @@ class DMSDocumentAdminTest extends FunctionalTest
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the default "add new" button is gone, and replaced with our customised version of it
|
||||
* Check that the default "add new" and "edit" buttons are gone, and replaced with our customised version of it
|
||||
*/
|
||||
public function testGridFieldHasCustomisedAddNewButton()
|
||||
public function testGridFieldHasCustomisedButtons()
|
||||
{
|
||||
$modelAdmin = new DMSDocumentAdmin;
|
||||
$modelAdmin->init();
|
||||
@ -22,23 +22,32 @@ class DMSDocumentAdminTest extends FunctionalTest
|
||||
$form = $modelAdmin->getEditForm();
|
||||
$gridFieldConfig = $form->Fields()->first()->getConfig();
|
||||
|
||||
// Our button is an instance of the original, so is returned when asking for the original
|
||||
$addNewButtons = $gridFieldConfig->getComponentsByType('GridFieldAddNewButton');
|
||||
foreach ($addNewButtons as $key => $addNewButton) {
|
||||
if ($addNewButton instanceof DMSGridFieldAddNewButton) {
|
||||
// Remove our version for testing's sake
|
||||
$addNewButtons->remove($addNewButton);
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertCount(0, $addNewButtons, 'Original add new button is removed');
|
||||
$this->assertInstanceOf(
|
||||
'DMSGridFieldAddNewButton',
|
||||
$gridFieldConfig->getComponentByType('DMSGridFieldAddNewButton'),
|
||||
'Model admin for documents contains customised DMS add new button'
|
||||
$replacements = array(
|
||||
'GridFieldAddNewButton'=>'DMSGridFieldAddNewButton',
|
||||
'GridFieldEditButton'=>'DMSGridFieldEditButton'
|
||||
);
|
||||
|
||||
foreach ($replacements as $oldClass => $newClass) {
|
||||
// Our button is an instance of the original, so is returned when asking for the original
|
||||
$newButtons = $gridFieldConfig->getComponentsByType($oldClass);
|
||||
foreach ($newButtons as $key => $newButton) {
|
||||
if ($newButton instanceof $newClass) {
|
||||
// Remove our version for testing's sake
|
||||
$newButtons->remove($newButton);
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertCount(0, $newButtons, 'Original button is removed');
|
||||
$this->assertInstanceOf(
|
||||
$newClass,
|
||||
$gridFieldConfig->getComponentByType($newClass),
|
||||
"Model admin for documents contains customised {$newClass} button"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Quick check to ensure that the ModelAdmin endpoint is working
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user