2011-03-18 04:23:47 +01:00
< ? php
2016-06-16 06:57:19 +02:00
2017-03-21 05:26:46 +01:00
use SilverStripe\Security\Group ;
2017-05-21 05:15:00 +02:00
use SilverStripe\Security\Security ;
2017-03-21 05:26:46 +01:00
use SilverStripe\SiteConfig\SiteConfig ;
use SilverStripe\Versioned\Versioned ;
2016-06-23 01:51:20 +02:00
use SilverStripe\Security\Member ;
2016-07-22 01:32:32 +02:00
use SilverStripe\CMS\Model\SiteTree ;
2016-09-09 01:26:24 +02:00
use SilverStripe\Control\HTTPResponse_Exception ;
2016-08-23 04:36:06 +02:00
use SilverStripe\Core\Config\Config ;
use SilverStripe\Dev\FunctionalTest ;
2011-03-18 04:23:47 +01:00
/**
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 ()
*/
2017-01-25 21:59:25 +01:00
class SiteTreePermissionsTest extends FunctionalTest
{
protected static $fixture_file = " SiteTreePermissionsTest.yml " ;
2017-03-30 00:07:04 +02:00
protected static $illegal_extensions = array (
2017-03-21 05:26:46 +01:00
SiteTree :: class => array ( 'SiteTreeSubsites' )
2017-01-25 21:59:25 +01:00
);
public function setUp ()
{
parent :: setUp ();
$this -> useDraftSite ();
// we're testing HTTP status codes before being redirected to login forms
$this -> autoFollowRedirection = false ;
}
public function testAccessingStageWithBlankStage ()
{
$this -> useDraftSite ( false );
$this -> autoFollowRedirection = false ;
2017-06-21 06:29:40 +02:00
/** @var Page $draftOnlyPage */
$draftOnlyPage = $this -> objFromFixture ( 'Page' , 'draftOnlyPage' );
$this -> logOut ();
2017-01-25 21:59:25 +01:00
2017-06-21 06:29:40 +02:00
$response = $this -> get ( $draftOnlyPage -> URLSegment . '?stage=Live' );
2017-01-25 21:59:25 +01:00
$this -> assertEquals ( $response -> getStatusCode (), '404' );
2017-06-21 06:29:40 +02:00
$response = $this -> get ( $draftOnlyPage -> URLSegment );
2017-01-25 21:59:25 +01:00
$this -> assertEquals ( $response -> getStatusCode (), '404' );
// should be prompted for a login
try {
2017-06-21 06:29:40 +02:00
$response = $this -> get ( $draftOnlyPage -> URLSegment . '?stage=Stage' );
2017-01-25 21:59:25 +01:00
} catch ( HTTPResponse_Exception $responseException ) {
$response = $responseException -> getResponse ();
}
$this -> assertEquals ( $response -> getStatusCode (), '302' );
$this -> assertContains (
2017-06-21 06:29:40 +02:00
Security :: config () -> get ( 'login_url' ),
2017-01-25 21:59:25 +01:00
$response -> getHeader ( 'Location' )
);
$this -> logInWithPermission ( 'ADMIN' );
2017-06-21 06:29:40 +02:00
$response = $this -> get ( $draftOnlyPage -> URLSegment . '?stage=Live' );
$this -> assertEquals ( '404' , $response -> getStatusCode ());
2017-01-25 21:59:25 +01:00
2017-06-21 06:29:40 +02:00
$response = $this -> get ( $draftOnlyPage -> URLSegment . '?stage=Stage' );
$this -> assertEquals ( '200' , $response -> getStatusCode ());
2017-01-25 21:59:25 +01:00
2017-06-21 06:29:40 +02:00
// Stage is remembered from last request
$response = $this -> get ( $draftOnlyPage -> URLSegment );
$this -> assertEquals ( '200' , $response -> getStatusCode ());
2017-01-25 21:59:25 +01:00
}
public function testPermissionCheckingWorksOnDeletedPages ()
{
// Set up fixture - a published page deleted from draft
$this -> logInWithPermission ( " ADMIN " );
$page = $this -> objFromFixture ( 'Page' , 'restrictedEditOnlySubadminGroup' );
$pageID = $page -> ID ;
$this -> assertTrue ( $page -> publishRecursive ());
$page -> delete ();
// Re-fetch the page from the live site
2017-06-21 06:29:40 +02:00
$page = Versioned :: get_one_by_stage ( SiteTree :: class , 'Live' , " \" SiteTree \" . \" ID \" = $pageID " );
2017-01-25 21:59:25 +01:00
// subadmin has edit rights on that page
2017-03-21 05:26:46 +01:00
$member = $this -> objFromFixture ( Member :: class , 'subadmin' );
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( $member );
2017-01-25 21:59:25 +01:00
// Test can_edit_multiple
$this -> assertEquals (
2017-05-12 02:47:46 +02:00
[ $pageID => true ],
SiteTree :: getPermissionChecker () -> canEditMultiple ([ $pageID ], $member )
2017-01-25 21:59:25 +01:00
);
// Test canEdit
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( $member );
2017-01-25 21:59:25 +01:00
$this -> assertTrue ( $page -> canEdit ());
}
public function testPermissionCheckingWorksOnUnpublishedPages ()
{
// 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
2017-03-21 05:26:46 +01:00
$member = $this -> objFromFixture ( Member :: class , 'subadmin' );
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( $member );
2017-01-25 21:59:25 +01:00
// Test can_edit_multiple
$this -> assertEquals (
2017-05-12 02:47:46 +02:00
[ $pageID => true ],
SiteTree :: getPermissionChecker () -> canEditMultiple ([ $pageID ], $member )
2017-01-25 21:59:25 +01:00
);
// Test canEdit
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( $member );
2017-01-25 21:59:25 +01:00
$this -> assertTrue ( $page -> canEdit ());
}
public function testCanEditOnPageDeletedFromStageAndLiveReturnsFalse ()
{
// 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
2017-06-21 06:29:40 +02:00
$page = Versioned :: get_latest_version ( SiteTree :: class , $pageID );
2017-01-25 21:59:25 +01:00
// subadmin had edit rights on that page, but now it's gone
2017-03-21 05:26:46 +01:00
$member = $this -> objFromFixture ( Member :: class , 'subadmin' );
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( $member );
2017-01-25 21:59:25 +01:00
$this -> assertFalse ( $page -> canEdit ());
}
public function testCanViewStage ()
{
$this -> useDraftSite ( false ); // useDraftSite deliberately disables checking the stage as part of canView
// Get page & make sure it exists on Live
$page = $this -> objFromFixture ( 'Page' , 'standardpage' );
$page -> copyVersionToStage ( Versioned :: DRAFT , Versioned :: LIVE );
// Then make sure there's a new version on Stage
$page -> Title = 1 ;
$page -> write ();
2017-03-21 05:26:46 +01:00
$editor = $this -> objFromFixture ( Member :: class , 'editor' );
$websiteuser = $this -> objFromFixture ( Member :: class , 'websiteuser' );
2017-01-25 21:59:25 +01:00
$this -> assertTrue ( $page -> canViewStage ( 'Live' , $websiteuser ));
$this -> assertFalse ( $page -> canViewStage ( 'Stage' , $websiteuser ));
$this -> assertTrue ( $page -> canViewStage ( 'Live' , $editor ));
$this -> assertTrue ( $page -> canViewStage ( 'Stage' , $editor ));
$this -> useDraftSite ();
}
public function testAccessTabOnlyDisplaysWithGrantAccessPermissions ()
{
$page = $this -> objFromFixture ( 'Page' , 'standardpage' );
2017-03-21 05:26:46 +01:00
$subadminuser = $this -> objFromFixture ( Member :: class , 'subadmin' );
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( $subadminuser );
2017-01-25 21:59:25 +01:00
$fields = $page -> getSettingsFields ();
$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'
);
2017-03-21 05:26:46 +01:00
$editoruser = $this -> objFromFixture ( Member :: class , 'editor' );
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( $editoruser );
2017-01-25 21:59:25 +01:00
$fields = $page -> getSettingsFields ();
$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'
);
2017-06-19 03:00:47 +02:00
$this -> session () -> set ( 'loggedInAs' , null );
2017-01-25 21:59:25 +01:00
}
public function testRestrictedViewLoggedInUsers ()
{
$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"'
);
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( null );
2017-01-25 21:59:25 +01:00
$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
2017-03-21 05:26:46 +01:00
$websiteuser = $this -> objFromFixture ( Member :: class , 'websiteuser' );
2017-01-25 21:59:25 +01:00
$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'
);
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( $websiteuser );
2017-01-25 21:59:25 +01:00
$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'
);
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( null );
2017-01-25 21:59:25 +01:00
}
public function testRestrictedViewOnlyTheseUsers ()
{
$page = $this -> objFromFixture ( 'Page' , 'restrictedViewOnlyWebsiteUsers' );
// unauthenticcated users
$this -> assertFalse (
$page -> canView ( false ),
'Unauthenticated members cant view a page marked as "Viewable by these groups"'
);
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( null );
2017-01-25 21:59:25 +01:00
$response = $this -> get ( $page -> RelativeLink ());
$this -> assertEquals (
$response -> getStatusCode (),
302 ,
'Unauthenticated members cant view a page marked as "Viewable by these groups"'
);
// subadmin users
2017-03-21 05:26:46 +01:00
$subadminuser = $this -> objFromFixture ( Member :: class , 'subadmin' );
2017-01-25 21:59:25 +01:00
$this -> assertFalse (
$page -> canView ( $subadminuser ),
'Authenticated members cant view a page marked as "Viewable by these groups" if theyre not in the listed groups'
);
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( $subadminuser );
2017-01-25 21:59:25 +01:00
$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'
);
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( null );
2017-01-25 21:59:25 +01:00
// website users
2017-03-21 05:26:46 +01:00
$websiteuser = $this -> objFromFixture ( Member :: class , 'websiteuser' );
2017-01-25 21:59:25 +01:00
$this -> assertTrue (
$page -> canView ( $websiteuser ),
'Authenticated members can view a page marked as "Viewable by these groups" if theyre in the listed groups'
);
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( $websiteuser );
2017-01-25 21:59:25 +01:00
$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'
);
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( null );
2017-01-25 21:59:25 +01:00
}
public function testRestrictedEditLoggedInUsers ()
{
$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
2017-03-21 05:26:46 +01:00
$websiteuser = $this -> objFromFixture ( Member :: class , 'websiteuser' );
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( $websiteuser );
2017-01-25 21:59:25 +01:00
$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
2017-03-21 05:26:46 +01:00
$subadminuser = $this -> objFromFixture ( Member :: class , 'subadmin' );
2017-01-25 21:59:25 +01:00
$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'
);
}
public function testRestrictedEditOnlySubadminGroup ()
{
$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
2017-03-21 05:26:46 +01:00
$subadminuser = $this -> objFromFixture ( Member :: class , 'subadmin' );
2017-01-25 21:59:25 +01:00
$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
2017-03-21 05:26:46 +01:00
$websiteuser = $this -> objFromFixture ( Member :: class , 'websiteuser' );
2017-01-25 21:59:25 +01:00
$this -> assertFalse (
$page -> canEdit ( $websiteuser ),
'Authenticated members cant edit a page marked as "Editable by these groups" if theyre not in the listed groups'
);
}
public function testRestrictedViewInheritance ()
{
$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'
);
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( null );
2017-01-25 21:59:25 +01:00
$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
2017-03-21 05:26:46 +01:00
$subadminuser = $this -> objFromFixture ( Member :: class , 'subadmin' );
2017-01-25 21:59:25 +01:00
$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'
);
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( $subadminuser );
2017-01-25 21:59:25 +01:00
$response = $this -> get ( $childPage -> RelativeLink ());
$this -> assertEquals (
$response -> getStatusCode (),
200 ,
'Authenticated members can view a page marked as "Viewable by these groups" if theyre in the listed groups by inherited permission'
);
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( null );
2017-01-25 21:59:25 +01:00
}
public function testRestrictedEditInheritance ()
{
$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
2017-03-21 05:26:46 +01:00
$subadminuser = $this -> objFromFixture ( Member :: class , 'subadmin' );
2017-01-25 21:59:25 +01:00
$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'
);
}
public function testDeleteRestrictedChild ()
{
$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"'
);
}
public function testRestrictedEditLoggedInUsersDeletedFromStage ()
{
$page = $this -> objFromFixture ( 'Page' , 'restrictedEditLoggedInUsers' );
$pageID = $page -> ID ;
$this -> logInWithPermission ( " ADMIN " );
$page -> publishRecursive ();
$page -> deleteFromStage ( 'Stage' );
// Get the live version of the page
2017-03-21 05:26:46 +01:00
$page = Versioned :: get_one_by_stage ( SiteTree :: class , Versioned :: LIVE , " \" SiteTree \" . \" ID \" = $pageID " );
2017-01-25 21:59:25 +01:00
$this -> assertTrue ( is_object ( $page ), 'Versioned::get_one_by_stage() is returning an object' );
// subadmin users
2017-03-21 05:26:46 +01:00
$subadminuser = $this -> objFromFixture ( Member :: class , 'subadmin' );
2017-01-25 21:59:25 +01:00
$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'
);
}
public function testInheritCanViewFromSiteConfig ()
{
$page = $this -> objFromFixture ( 'Page' , 'inheritWithNoParent' );
2017-03-21 05:26:46 +01:00
$siteconfig = $this -> objFromFixture ( SiteConfig :: class , 'default' );
$editor = $this -> objFromFixture ( Member :: class , 'editor' );
$editorGroup = $this -> objFromFixture ( Group :: class , 'editorgroup' );
2017-01-25 21:59:25 +01:00
$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' );
}
public function testInheritCanEditFromSiteConfig ()
{
$page = $this -> objFromFixture ( 'Page' , 'inheritWithNoParent' );
2017-03-21 05:26:46 +01:00
$siteconfig = $this -> objFromFixture ( SiteConfig :: class , 'default' );
$editor = $this -> objFromFixture ( Member :: class , 'editor' );
$user = $this -> objFromFixture ( Member :: class , 'websiteuser' );
$editorGroup = $this -> objFromFixture ( Group :: class , 'editorgroup' );
2017-01-25 21:59:25 +01:00
$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' );
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( $editor );
2017-01-25 21:59:25 +01:00
$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' );
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( null );
2017-01-25 21:59:25 +01:00
$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' );
2017-05-21 05:15:00 +02:00
Security :: setCurrentUser ( $user );
2017-01-25 21:59:25 +01:00
$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' );
}
2011-03-18 04:23:47 +01:00
}