diff --git a/core/control/ContentController.php b/core/control/ContentController.php index aac155d21..36b592466 100755 --- a/core/control/ContentController.php +++ b/core/control/ContentController.php @@ -112,7 +112,7 @@ class ContentController extends Controller { // Draft/Archive security check - only CMS users should be able to look at stage/archived content if($this->URLSegment != 'Security' && !Session::get('unsecuredDraftSite') && (Versioned::current_archived_date() || (Versioned::current_stage() && Versioned::current_stage() != 'Live'))) { - if(!Permission::check('CMS_ACCESS_CMSMain')) { + if(!$this->dataRecord->canViewStage(Versioned::current_stage())) { $link = $this->Link(); $message = _t("ContentController.DRAFT_SITE_ACCESS_RESTRICTION", 'You must log in with your CMS password in order to view the draft or archived content. Click here to go back to the published site.'); return Security::permissionFailure($this, sprintf($message, "$link?stage=Live")); diff --git a/core/model/SiteTree.php b/core/model/SiteTree.php index e1be1357c..c4306641d 100755 --- a/core/model/SiteTree.php +++ b/core/model/SiteTree.php @@ -740,6 +740,28 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid return false; } + + /** + * Determines permissions for a specific stage (see {@link Versioned}). + * Usually the stage is read from {@link Versioned::current_stage()}. + * Falls back to {@link canView}. + * + * @todo Implement in CMS UI. + * + * @param String $stage + * @param Member $member + * @return boolean + */ + function canViewStage($stage, $member = null) { + if(!$member) $member = Member::currentUser(); + + if( + strtolower($stage) == 'stage' && + !Permission::checkMember($member, 'CMS_ACCESS_CMSMain') + ) return false; + + return $this->canView($member); + } /** * This function should return true if the current user can delete this diff --git a/tests/SiteTreePermissionsTest.php b/tests/SiteTreePermissionsTest.php index 713a26f1c..193b9ad84 100755 --- a/tests/SiteTreePermissionsTest.php +++ b/tests/SiteTreePermissionsTest.php @@ -30,6 +30,18 @@ class SiteTreePermissionsTest extends FunctionalTest { $this->autoFollowRedirection = false; } + function testCanViewStage() { + $page = $this->objFromFixture('Page', 'standardpage'); + $editor = $this->objFromFixture('Member', 'editor'); + $websiteuser = $this->objFromFixture('Member', 'websiteuser'); + + $this->assertTrue($page->canViewStage('Live', $websiteuser)); + $this->assertFalse($page->canViewStage('Stage', $websiteuser)); + + $this->assertTrue($page->canViewStage('Live', $editor)); + $this->assertTrue($page->canViewStage('Stage', $editor)); + } + function testAccessTabOnlyDisplaysWithGrantAccessPermissions() { $page = $this->objFromFixture('Page', 'standardpage'); diff --git a/tests/control/ContentControllerPermissionsTest.php b/tests/control/ContentControllerPermissionsTest.php new file mode 100644 index 000000000..1330a4072 --- /dev/null +++ b/tests/control/ContentControllerPermissionsTest.php @@ -0,0 +1,35 @@ +URLSegment = 'testpage'; + $page->write(); + $page->publish('Stage', 'Live'); + + $response = $this->get('/testpage'); + $this->assertEquals($response->getStatusCode(), 200); + + $response = $this->get('/testpage/?stage=Live'); + $this->assertEquals($response->getStatusCode(), 200); + + $response = $this->get('/testpage/?stage=Stage'); + // should redirect to login + $this->assertEquals($response->getStatusCode(), 302); + + $this->logInWithPermssion('CMS_ACCESS_CMSMain'); + + $response = $this->get('/testpage/?stage=Stage'); + $this->assertEquals($response->getStatusCode(), 200); + } + + +} \ No newline at end of file