From 9bf32459394dbf78d6035d05b12dff479963c320 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Mon, 3 Nov 2008 14:56:36 +0000 Subject: [PATCH] BUGFIX Enforce permission checks in LeftAndMain and CMSMain through SiteTree->canView()/canEdit()/canAddChildren()/canPublish()/canDelete() (see #2701) git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@65152 467b73ca-7a2a-4603-9d3b-597d59a354a9 --- code/CMSMain.php | 48 ++++++++++++++++++++++++++++++++++---------- code/LeftAndMain.php | 21 +++++++++++++++++-- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/code/CMSMain.php b/code/CMSMain.php index 9dce12be..03238ccb 100644 --- a/code/CMSMain.php +++ b/code/CMSMain.php @@ -444,6 +444,9 @@ JS; if(is_numeric($parent)) $parentObj = DataObject::get_by_id("SiteTree", $parent); if(!$parentObj || !$parentObj->ID) $parent = 0; + + if($parentObj && !$parentObj->canAddChildren()) return Security::permissionFailure($this); + if(!singleton($className)->canCreate()) return Security::permissionFailure($this); $p = $this->getNewItem("new-$className-$parent".$suffix, false); $p->write(); @@ -454,14 +457,16 @@ JS; public function getNewItem($id, $setID = true) { list($dummy, $className, $parentID, $suffix) = explode('-',$id); - if (!Translatable::is_default_lang()) { - $originalItem = Translatable::get_original($className,Session::get("{$id}_originalLangID")); - if ($setID) $originalItem->ID = $id; - else { - $originalItem->ID = null; - Translatable::creating_from(Session::get($id.'_originalLangID')); + if(Translatable::is_enabled()) { + if (!Translatable::is_default_lang()) { + $originalItem = Translatable::get_original($className,Session::get("{$id}_originalLangID")); + if ($setID) $originalItem->ID = $id; + else { + $originalItem->ID = null; + Translatable::creating_from(Session::get($id.'_originalLangID')); + } + return $originalItem; } - return $originalItem; } $newItem = new $className(); @@ -503,6 +508,8 @@ JS; $id = $_REQUEST['ID']; Versioned::reading_stage('Live'); $record = DataObject::get_by_id("SiteTree", $id); + if($record && !$record->canDelete()) return Security::permissionFailure($this); + $descRemoved = ''; $descendantsRemoved = 0; @@ -541,12 +548,16 @@ JS; * Actually perform the publication step */ public function performPublish($record) { + if($record && !$record->canPublish()) return Security::permissionFailure($this); + $record->doPublish(); } public function revert($urlParams, $form) { $id = $_REQUEST['ID']; $obj = DataObject::get_by_id("SiteTree", $id); + if($record && !$record->canEdit()) return Security::permissionFailure($this); + $obj->doRevertToLive(); $title = Convert::raw2js($obj->Title); @@ -563,6 +574,8 @@ JS; public function delete($urlParams, $form) { $id = $_REQUEST['ID']; $record = DataObject::get_one("SiteTree", "SiteTree.ID = $id"); + if($record && !$record->canDelete()) return Security::permissionFailure(); + $recordID = $record->ID; $record->delete(); $record->ID = $recordID; @@ -743,6 +756,8 @@ HTML; $SQL_id = Convert::raw2sql($_REQUEST['ID']); $page = DataObject::get_by_id("SiteTree", $SQL_id); + if($page && !$page->canPublish()) return Security::permissionFailure($this); + $page->doUnpublish(); return $this->tellBrowserAboutPublicationChange($page, sprintf(_t('CMSMain.REMOVEDPAGE',"Removed '%s' from the published site"),$page->Title)); @@ -783,6 +798,8 @@ HTML; function performRollback($id, $version) { $record = DataObject::get_by_id($this->stat('tree_class'), $id); + if($record && !$record->canPublish()) return Security::permissionFailure($this); + $record->doRollbackTo($version); return $record; } @@ -793,6 +810,8 @@ HTML; $record = Versioned::get_version("SiteTree", $id, $version); if($record) { + if($record && !$record->canView()) return Security::permissionFailure($this); + $fields = $record->getCMSFields($this); $fields->removeByName("Status"); @@ -850,6 +869,8 @@ HTML; } $page = DataObject::get_by_id("SiteTree", $id); + if($page && !$page->canView()) return Security::permissionFailure($this); + $record = $page->compareVersions($fromVersion, $toVersion); if($record) { $fields = $record->getCMSFields($this); @@ -949,8 +970,10 @@ HTML; $brokenPageList = ''; if(is_numeric($id)) { $record = DataObject::get_by_id($this->stat('tree_class'), $id); - + if($record) { + if($record && !$record->canPublish()) return Security::permissionFailure($this); + // Publish this page $record->doPublish(); @@ -997,10 +1020,9 @@ HTML; if(is_numeric($id)) { $record = DataObject::get_by_id($this->stat('tree_class'), $id); - // if(!$record) Debug::message( "Can't find record #$id" ); - if($record) { - + if($record && !$record->canDelete()) return Security::permissionFailure($this); + // add all the children for this record if they are not already in the list // this check is a little slower but will prevent circular dependencies // (should they exist, which they probably shouldn't) from causing @@ -1159,6 +1181,8 @@ HTML; $count = 0; while(true) { foreach($pages as $page) { + if($page && !$page->canPublish()) return Security::permissionFailure($this); + $page->doPublish(); $page->destroy(); unset($page); @@ -1207,6 +1231,7 @@ HTML; function duplicate() { if(($id = $this->urlParams['ID']) && is_numeric($id)) { $page = DataObject::get_by_id("SiteTree", $id); + if($page && !$page->canEdit()) return Security::permissionFailure($this); $newPage = $page->duplicate(); @@ -1225,6 +1250,7 @@ HTML; function duplicatewithchildren() { if(($id = $this->urlParams['ID']) && is_numeric($id)) { $page = DataObject::get_by_id("SiteTree", $id); + if($page && !$page->canEdit()) return Security::permissionFailure($this); $newPage = $page->duplicateWithChildren(); diff --git a/code/LeftAndMain.php b/code/LeftAndMain.php index ba80275e..f1b449a0 100644 --- a/code/LeftAndMain.php +++ b/code/LeftAndMain.php @@ -280,7 +280,11 @@ class LeftAndMain extends Controller { public function getitem() { $this->setCurrentPageID($_REQUEST['ID']); SSViewer::setOption('rewriteHashlinks', false); - // Changed 3/11/2006 to not use getLastFormIn because that didn't have _form_action, _form_name, etc. + + if(isset($_REQUEST['ID'])) { + $record = DataObject::get_by_id($this->stat('tree_class'), $_REQUEST['ID']); + if($record && !$record->canView()) return Security::permissionFailure($this); + } $form = $this->EditForm(); if($form) return $form->formHtmlContent(); @@ -458,7 +462,9 @@ JS; $SQL_id = Convert::raw2sql($_REQUEST['ID']); if(substr($SQL_id,0,3) != 'new') { $record = DataObject::get_one($className, "`$className`.ID = {$SQL_id}"); + if($record && !$record->canEdit()) return Security::permissionFailure($this); } else { + if(!singleton($this->stat('tree_class'))->canCreate()) return Security::permissionFailure($this); $record = $this->getNewItem($SQL_id, false); } @@ -660,6 +666,8 @@ JS; if(is_numeric($id) && is_numeric($parentID) && $id != $parentID) { $node = DataObject::get_by_id($this->stat('tree_class'), $id); if($node){ + if($node && !$node->canEdit()) return Security::permissionFailure($this); + $node->ParentID = $parentID; $node->Status = "Saved (update)"; $node->write(); @@ -743,6 +751,9 @@ JS; $script = "st = \$('sitetree'); \n"; foreach($ids as $id) { if(is_numeric($id)) { + $record = DataObject::get_by_id($id); + if($record && !$record->canDelete()) return Security::permissionFailure($this); + DataObject::delete_by_id($this->stat('tree_class'), $id); $script .= "node = st.getTreeNodeByIdx($id); if(node) node.parentTreeNode.removeTreeNode(node); $('Form_EditForm').closeIfSetTo($id); \n"; } @@ -754,7 +765,13 @@ JS; public function EditForm() { $id = isset($_REQUEST['ID']) ? $_REQUEST['ID'] : $this->currentPageID(); - if($id) return $this->getEditForm($id); + + if(!$id) return false; + + $record = DataObject::get_by_id($this->stat('tree_class'), $id); + if($record && !$record->canView()) return Security::permissionFailure($this); + + return $this->getEditForm($id); } public function myprofile() {