2011-03-18 04:23:47 +01:00
< ? php
/**
2011-03-22 10:47:26 +01:00
* @ package cms
2011-03-18 04:23:47 +01:00
* @ subpackage tests
2016-01-06 00:42:07 +01:00
*
2011-03-18 04:23:47 +01:00
* @ todo Test canAddChildren ()
* @ todo Test canCreate ()
*/
class SiteTreePermissionsTest extends FunctionalTest {
2013-03-18 11:47:15 +01:00
protected static $fixture_file = " SiteTreePermissionsTest.yml " ;
2011-03-18 04:23:47 +01:00
protected $illegalExtensions = array (
'SiteTree' => array ( 'SiteTreeSubsites' )
);
2012-09-19 12:07:46 +02:00
public function setUp () {
2011-03-18 04:23:47 +01:00
parent :: setUp ();
$this -> useDraftSite ();
// we're testing HTTP status codes before being redirected to login forms
$this -> autoFollowRedirection = false ;
}
2012-09-19 12:07:46 +02:00
public function testAccessingStageWithBlankStage () {
2011-03-18 04:23:47 +01:00
$this -> useDraftSite ( false );
$this -> autoFollowRedirection = false ;
$page = $this -> objFromFixture ( 'Page' , 'draftOnlyPage' );
if ( $member = Member :: currentUser ()) {
$member -> logOut ();
}
$response = $this -> get ( $page -> URLSegment . '?stage=Live' );
$this -> assertEquals ( $response -> getStatusCode (), '404' );
$response = $this -> get ( $page -> URLSegment . '?stage=' );
$this -> assertEquals ( $response -> getStatusCode (), '404' );
// should be prompted for a login
2015-12-22 05:46:07 +01:00
try {
$response = $this -> get ( $page -> URLSegment . '?stage=Stage' );
} catch ( SS_HTTPResponse_Exception $responseException ) {
$response = $responseException -> getResponse ();
}
2011-03-18 04:23:47 +01:00
$this -> assertEquals ( $response -> getStatusCode (), '302' );
2013-01-29 17:31:25 +01:00
$this -> assertContains (
2016-01-06 00:42:07 +01:00
Config :: inst () -> get ( 'Security' , 'login_url' ),
2013-01-29 17:31:25 +01:00
$response -> getHeader ( 'Location' )
);
2011-03-18 04:23:47 +01:00
$this -> logInWithPermission ( 'ADMIN' );
$response = $this -> get ( $page -> URLSegment . '?stage=Live' );
$this -> assertEquals ( $response -> getStatusCode (), '404' );
$response = $this -> get ( $page -> URLSegment . '?stage=Stage' );
2011-07-21 11:49:55 +02:00
$this -> assertEquals ( $response -> getStatusCode (), '200' );
2011-03-18 04:23:47 +01:00
$response = $this -> get ( $page -> URLSegment . '?stage=' );
$this -> assertEquals ( $response -> getStatusCode (), '404' );
}
2012-09-19 12:07:46 +02:00
public function testPermissionCheckingWorksOnDeletedPages () {
2011-03-18 04:23:47 +01:00
// Set up fixture - a published page deleted from draft
$this -> logInWithPermission ( " ADMIN " );
$page = $this -> objFromFixture ( 'Page' , 'restrictedEditOnlySubadminGroup' );
$pageID = $page -> ID ;
$this -> assertTrue ( $page -> doPublish ());
$page -> delete ();
// Re-fetch the page from the live site
$page = Versioned :: get_one_by_stage ( 'SiteTree' , 'Live' , " \" SiteTree \" . \" ID \" = $pageID " );
// subadmin has edit rights on that page
$member = $this -> objFromFixture ( 'Member' , 'subadmin' );
$member -> logIn ();
// Test can_edit_multiple
$this -> assertEquals (
array ( $pageID => true ),
SiteTree :: can_edit_multiple ( array ( $pageID ), $member -> ID )
);
// Test canEdit
$member -> logIn ();
$this -> assertTrue ( $page -> canEdit ());
}
2012-09-19 12:07:46 +02:00
public function testPermissionCheckingWorksOnUnpublishedPages () {
2011-03-18 04:23:47 +01:00
// Set up fixture - an unpublished page
$this -> logInWithPermission ( " ADMIN " );
$page = $this -> objFromFixture ( 'Page' , 'restrictedEditOnlySubadminGroup' );
$pageID = $page -> ID ;
$page -> doUnpublish ();
// subadmin has edit rights on that page
$member = $this -> objFromFixture ( 'Member' , 'subadmin' );
$member -> logIn ();
// Test can_edit_multiple
$this -> assertEquals (
array ( $pageID => true ),
SiteTree :: can_edit_multiple ( array ( $pageID ), $member -> ID )
);
// Test canEdit
$member -> logIn ();
$this -> assertTrue ( $page -> canEdit ());
}
2012-09-19 12:07:46 +02:00
public function testCanEditOnPageDeletedFromStageAndLiveReturnsFalse () {
2011-03-18 04:23:47 +01:00
// Find a page that exists and delete it from both stage and published
$this -> logInWithPermission ( " ADMIN " );
$page = $this -> objFromFixture ( 'Page' , 'restrictedEditOnlySubadminGroup' );
$pageID = $page -> ID ;
$page -> doUnpublish ();
$page -> delete ();
// We'll need to resurrect the page from the version cache to test this case
$page = Versioned :: get_latest_version ( 'SiteTree' , $pageID );
// subadmin had edit rights on that page, but now it's gone
$member = $this -> objFromFixture ( 'Member' , 'subadmin' );
$member -> logIn ();
$this -> assertFalse ( $page -> canEdit ());
}
2012-09-19 12:07:46 +02:00
public function testCanViewStage () {
2013-07-04 04:54:13 +02:00
$this -> useDraftSite ( false ); // useDraftSite deliberately disables checking the stage as part of canView
// Get page & make sure it exists on Live
2011-03-18 04:23:47 +01:00
$page = $this -> objFromFixture ( 'Page' , 'standardpage' );
2013-07-04 04:54:13 +02:00
$page -> publish ( 'Stage' , 'Live' );
// Then make sure there's a new version on Stage
$page -> Title = 1 ;
$page -> write ();
2011-03-18 04:23:47 +01:00
$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 ));
2013-07-04 04:54:13 +02:00
$this -> useDraftSite ();
2011-03-18 04:23:47 +01:00
}
2012-09-19 12:07:46 +02:00
public function testAccessTabOnlyDisplaysWithGrantAccessPermissions () {
2011-03-18 04:23:47 +01:00
$page = $this -> objFromFixture ( 'Page' , 'standardpage' );
$subadminuser = $this -> objFromFixture ( 'Member' , 'subadmin' );
$this -> session () -> inst_set ( 'loggedInAs' , $subadminuser -> ID );
2011-04-15 06:35:19 +02:00
$fields = $page -> getSettingsFields ();
2011-03-18 04:23:47 +01:00
$this -> assertFalse (
$fields -> dataFieldByName ( 'CanViewType' ) -> isReadonly (),
'Users with SITETREE_GRANT_ACCESS permission can change "view" permissions in cms fields'
);
$this -> assertFalse (
$fields -> dataFieldByName ( 'CanEditType' ) -> isReadonly (),
'Users with SITETREE_GRANT_ACCESS permission can change "edit" permissions in cms fields'
);
$editoruser = $this -> objFromFixture ( 'Member' , 'editor' );
$this -> session () -> inst_set ( 'loggedInAs' , $editoruser -> ID );
2011-04-15 06:35:19 +02:00
$fields = $page -> getSettingsFields ();
2011-03-18 04:23:47 +01:00
$this -> assertTrue (
$fields -> dataFieldByName ( 'CanViewType' ) -> isReadonly (),
'Users without SITETREE_GRANT_ACCESS permission cannot change "view" permissions in cms fields'
);
$this -> assertTrue (
$fields -> dataFieldByName ( 'CanEditType' ) -> isReadonly (),
'Users without SITETREE_GRANT_ACCESS permission cannot change "edit" permissions in cms fields'
);
$this -> session () -> inst_set ( 'loggedInAs' , null );
}
2012-09-19 12:07:46 +02:00
public function testRestrictedViewLoggedInUsers () {
2011-03-18 04:23:47 +01:00
$page = $this -> objFromFixture ( 'Page' , 'restrictedViewLoggedInUsers' );
// unauthenticated users
$this -> assertFalse (
$page -> canView ( FALSE ),
'Unauthenticated members cant view a page marked as "Viewable for any logged in users"'
);
$this -> session () -> inst_set ( 'loggedInAs' , null );
$response = $this -> get ( $page -> RelativeLink ());
$this -> assertEquals (
$response -> getStatusCode (),
302 ,
'Unauthenticated members cant view a page marked as "Viewable for any logged in users"'
);
// website users
$websiteuser = $this -> objFromFixture ( 'Member' , 'websiteuser' );
$this -> assertTrue (
$page -> canView ( $websiteuser ),
'Authenticated members can view a page marked as "Viewable for any logged in users" even if they dont have access to the CMS'
);
$this -> session () -> inst_set ( 'loggedInAs' , $websiteuser -> ID );
$response = $this -> get ( $page -> RelativeLink ());
$this -> assertEquals (
$response -> getStatusCode (),
200 ,
'Authenticated members can view a page marked as "Viewable for any logged in users" even if they dont have access to the CMS'
);
$this -> session () -> inst_set ( 'loggedInAs' , null );
}
2012-09-19 12:07:46 +02:00
public function testRestrictedViewOnlyTheseUsers () {
2011-03-18 04:23:47 +01:00
$page = $this -> objFromFixture ( 'Page' , 'restrictedViewOnlyWebsiteUsers' );
// unauthenticcated users
$this -> assertFalse (
$page -> canView ( FALSE ),
'Unauthenticated members cant view a page marked as "Viewable by these groups"'
);
$this -> session () -> inst_set ( 'loggedInAs' , null );
$response = $this -> get ( $page -> RelativeLink ());
$this -> assertEquals (
$response -> getStatusCode (),
302 ,
'Unauthenticated members cant view a page marked as "Viewable by these groups"'
);
// subadmin users
$subadminuser = $this -> objFromFixture ( 'Member' , 'subadmin' );
$this -> assertFalse (
$page -> canView ( $subadminuser ),
'Authenticated members cant view a page marked as "Viewable by these groups" if theyre not in the listed groups'
);
$this -> session () -> inst_set ( 'loggedInAs' , $subadminuser -> ID );
$response = $this -> get ( $page -> RelativeLink ());
$this -> assertEquals (
$response -> getStatusCode (),
403 ,
'Authenticated members cant view a page marked as "Viewable by these groups" if theyre not in the listed groups'
);
$this -> session () -> inst_set ( 'loggedInAs' , null );
// website users
$websiteuser = $this -> objFromFixture ( 'Member' , 'websiteuser' );
$this -> assertTrue (
$page -> canView ( $websiteuser ),
'Authenticated members can view a page marked as "Viewable by these groups" if theyre in the listed groups'
);
$this -> session () -> inst_set ( 'loggedInAs' , $websiteuser -> ID );
$response = $this -> get ( $page -> RelativeLink ());
$this -> assertEquals (
$response -> getStatusCode (),
200 ,
'Authenticated members can view a page marked as "Viewable by these groups" if theyre in the listed groups'
);
$this -> session () -> inst_set ( 'loggedInAs' , null );
}
2012-09-19 12:07:46 +02:00
public function testRestrictedEditLoggedInUsers () {
2011-03-18 04:23:47 +01:00
$page = $this -> objFromFixture ( 'Page' , 'restrictedEditLoggedInUsers' );
// unauthenticcated users
$this -> assertFalse (
$page -> canEdit ( FALSE ),
'Unauthenticated members cant edit a page marked as "Editable by logged in users"'
);
// website users
$websiteuser = $this -> objFromFixture ( 'Member' , 'websiteuser' );
$websiteuser -> logIn ();
$this -> assertFalse (
$page -> canEdit ( $websiteuser ),
'Authenticated members cant edit a page marked as "Editable by logged in users" if they dont have cms permissions'
);
// subadmin users
$subadminuser = $this -> objFromFixture ( 'Member' , 'subadmin' );
$this -> assertTrue (
$page -> canEdit ( $subadminuser ),
'Authenticated members can edit a page marked as "Editable by logged in users" if they have cms permissions and belong to any of these groups'
);
}
2012-09-19 12:07:46 +02:00
public function testRestrictedEditOnlySubadminGroup () {
2011-03-18 04:23:47 +01:00
$page = $this -> objFromFixture ( 'Page' , 'restrictedEditOnlySubadminGroup' );
// unauthenticated users
$this -> assertFalse (
$page -> canEdit ( FALSE ),
'Unauthenticated members cant edit a page marked as "Editable by these groups"'
);
// subadmin users
$subadminuser = $this -> objFromFixture ( 'Member' , 'subadmin' );
$this -> assertTrue (
$page -> canEdit ( $subadminuser ),
'Authenticated members can view a page marked as "Editable by these groups" if theyre in the listed groups'
);
// website users
$websiteuser = $this -> objFromFixture ( 'Member' , 'websiteuser' );
$this -> assertFalse (
$page -> canEdit ( $websiteuser ),
'Authenticated members cant edit a page marked as "Editable by these groups" if theyre not in the listed groups'
);
}
2012-09-19 12:07:46 +02:00
public function testRestrictedViewInheritance () {
2011-03-18 04:23:47 +01:00
$parentPage = $this -> objFromFixture ( 'Page' , 'parent_restrictedViewOnlySubadminGroup' );
$childPage = $this -> objFromFixture ( 'Page' , 'child_restrictedViewOnlySubadminGroup' );
// unauthenticated users
$this -> assertFalse (
$childPage -> canView ( FALSE ),
'Unauthenticated members cant view a page marked as "Viewable by these groups" by inherited permission'
);
$this -> session () -> inst_set ( 'loggedInAs' , null );
$response = $this -> get ( $childPage -> RelativeLink ());
$this -> assertEquals (
$response -> getStatusCode (),
302 ,
'Unauthenticated members cant view a page marked as "Viewable by these groups" by inherited permission'
);
// subadmin users
$subadminuser = $this -> objFromFixture ( 'Member' , 'subadmin' );
$this -> assertTrue (
$childPage -> canView ( $subadminuser ),
'Authenticated members can view a page marked as "Viewable by these groups" if theyre in the listed groups by inherited permission'
);
$this -> session () -> inst_set ( 'loggedInAs' , $subadminuser -> ID );
$response = $this -> get ( $childPage -> RelativeLink ());
$this -> assertEquals (
$response -> getStatusCode (),
2011-07-21 11:49:55 +02:00
200 ,
2011-03-18 04:23:47 +01:00
'Authenticated members can view a page marked as "Viewable by these groups" if theyre in the listed groups by inherited permission'
);
$this -> session () -> inst_set ( 'loggedInAs' , null );
}
2012-09-19 12:07:46 +02:00
public function testRestrictedEditInheritance () {
2011-03-18 04:23:47 +01:00
$parentPage = $this -> objFromFixture ( 'Page' , 'parent_restrictedEditOnlySubadminGroup' );
$childPage = $this -> objFromFixture ( 'Page' , 'child_restrictedEditOnlySubadminGroup' );
// unauthenticated users
$this -> assertFalse (
$childPage -> canEdit ( FALSE ),
'Unauthenticated members cant edit a page marked as "Editable by these groups" by inherited permission'
);
// subadmin users
$subadminuser = $this -> objFromFixture ( 'Member' , 'subadmin' );
$this -> assertTrue (
$childPage -> canEdit ( $subadminuser ),
'Authenticated members can edit a page marked as "Editable by these groups" if theyre in the listed groups by inherited permission'
);
}
2012-09-19 12:07:46 +02:00
public function testDeleteRestrictedChild () {
2011-03-18 04:23:47 +01:00
$parentPage = $this -> objFromFixture ( 'Page' , 'deleteTestParentPage' );
$childPage = $this -> objFromFixture ( 'Page' , 'deleteTestChildPage' );
// unauthenticated users
$this -> assertFalse (
$parentPage -> canDelete ( FALSE ),
'Unauthenticated members cant delete a page if it doesnt have delete permissions on any of its descendants'
);
$this -> assertFalse (
$childPage -> canDelete ( FALSE ),
'Unauthenticated members cant delete a child page marked as "Editable by these groups"'
);
}
2012-09-19 12:07:46 +02:00
public function testRestrictedEditLoggedInUsersDeletedFromStage () {
2011-03-18 04:23:47 +01:00
$page = $this -> objFromFixture ( 'Page' , 'restrictedEditLoggedInUsers' );
$pageID = $page -> ID ;
$this -> logInWithPermission ( " ADMIN " );
$page -> doPublish ();
$page -> deleteFromStage ( 'Stage' );
// Get the live version of the page
$page = Versioned :: get_one_by_stage ( " SiteTree " , " Live " , " \" SiteTree \" . \" ID \" = $pageID " );
$this -> assertTrue ( is_object ( $page ), 'Versioned::get_one_by_stage() is returning an object' );
// subadmin users
$subadminuser = $this -> objFromFixture ( 'Member' , 'subadmin' );
$this -> assertTrue (
$page -> canEdit ( $subadminuser ),
'Authenticated members can edit a page that was deleted from stage and marked as "Editable by logged in users" if they have cms permissions and belong to any of these groups'
);
}
2012-09-19 12:07:46 +02:00
public function testInheritCanViewFromSiteConfig () {
2011-03-18 04:23:47 +01:00
$page = $this -> objFromFixture ( 'Page' , 'inheritWithNoParent' );
$siteconfig = $this -> objFromFixture ( 'SiteConfig' , 'default' );
$editor = $this -> objFromFixture ( 'Member' , 'editor' );
$editorGroup = $this -> objFromFixture ( 'Group' , 'editorgroup' );
$siteconfig -> CanViewType = 'Anyone' ;
$siteconfig -> write ();
$this -> assertTrue ( $page -> canView ( FALSE ), 'Anyone can view a page when set to inherit from the SiteConfig, and SiteConfig has canView set to LoggedInUsers' );
$siteconfig -> CanViewType = 'LoggedInUsers' ;
$siteconfig -> write ();
$this -> assertFalse ( $page -> canView ( FALSE ), 'Anonymous can\'t view a page when set to inherit from the SiteConfig, and SiteConfig has canView set to LoggedInUsers' );
$siteconfig -> CanViewType = 'LoggedInUsers' ;
$siteconfig -> write ();
$this -> assertTrue ( $page -> canView ( $editor ), 'Users can view a page when set to inherit from the SiteConfig, and SiteConfig has canView set to LoggedInUsers' );
$siteconfig -> CanViewType = 'OnlyTheseUsers' ;
$siteconfig -> ViewerGroups () -> add ( $editorGroup );
$siteconfig -> write ();
$this -> assertTrue ( $page -> canView ( $editor ), 'Editors can view a page when set to inherit from the SiteConfig, and SiteConfig has canView set to OnlyTheseUsers' );
$this -> assertFalse ( $page -> canView ( FALSE ), 'Anonymous can\'t view a page when set to inherit from the SiteConfig, and SiteConfig has canView set to OnlyTheseUsers' );
}
2012-09-19 12:07:46 +02:00
public function testInheritCanEditFromSiteConfig () {
2011-03-18 04:23:47 +01:00
$page = $this -> objFromFixture ( 'Page' , 'inheritWithNoParent' );
$siteconfig = $this -> objFromFixture ( 'SiteConfig' , 'default' );
$editor = $this -> objFromFixture ( 'Member' , 'editor' );
$user = $this -> objFromFixture ( 'Member' , 'websiteuser' );
$editorGroup = $this -> objFromFixture ( 'Group' , 'editorgroup' );
$siteconfig -> CanEditType = 'LoggedInUsers' ;
$siteconfig -> write ();
$this -> assertFalse ( $page -> canEdit ( FALSE ), 'Anonymous can\'t edit a page when set to inherit from the SiteConfig, and SiteConfig has canEdit set to LoggedInUsers' );
$this -> session () -> inst_set ( 'loggedInAs' , $editor -> ID );
$this -> assertTrue ( $page -> canEdit (), 'Users can edit a page when set to inherit from the SiteConfig, and SiteConfig has canEdit set to LoggedInUsers' );
$siteconfig -> CanEditType = 'OnlyTheseUsers' ;
$siteconfig -> EditorGroups () -> add ( $editorGroup );
$siteconfig -> write ();
$this -> assertTrue ( $page -> canEdit ( $editor ), 'Editors can edit a page when set to inherit from the SiteConfig, and SiteConfig has canEdit set to OnlyTheseUsers' );
$this -> session () -> inst_set ( 'loggedInAs' , null );
$this -> assertFalse ( $page -> canEdit ( FALSE ), 'Anonymous can\'t edit a page when set to inherit from the SiteConfig, and SiteConfig has canEdit set to OnlyTheseUsers' );
$this -> session () -> inst_set ( 'loggedInAs' , $user -> ID );
$this -> assertFalse ( $page -> canEdit ( $user ), 'Website user can\'t edit a page when set to inherit from the SiteConfig, and SiteConfig has canEdit set to OnlyTheseUsers' );
}
2017-05-30 17:34:39 +02:00
/**
* Ensure that flipping parent / child relationship on live doesn ' t
* cause infinite loop
*/
public function testMobiusHierarchy ()
{
// login as admin to be able to publish
$adminID = $this -> logInWithPermission ( 'ADMIN' );
$parentPage = new Page ();
$parentPage -> Title = 'Parent Page' ;
$parentPage -> doPublish ();
$childPage = new Page ();
$childPage -> Title = 'Child Page' ;
$childPage -> ParentID = $parentPage -> ID ;
$childPage -> doPublish ();
//flip parent/child relation
$childPage -> ParentID = 0 ;
$childPage -> write ();
$parentPage -> ParentID = $childPage -> ID ;
$parentPage -> write ();
$this -> assertTrue ( $childPage -> isPublished ());
$this -> assertTrue ( $parentPage -> isPublished ());
$result = SiteTree :: batch_permission_check ( array (
$parentPage -> ID ,
$childPage -> ID ,
), $adminID , 'CanEditType' , 'SiteTree_EditorGroups' , 'canEditPages' );
$this -> assertArrayHasKey ( $childPage -> ID , $result );
$this -> assertArrayHasKey ( $parentPage -> ID , $result );
// mr potato head can't edit
$this -> assertTrue ( $result [ $parentPage -> ID ]);
$this -> assertTrue ( $result [ $childPage -> ID ]);
}
2011-03-18 04:23:47 +01:00
}