mirror of
https://github.com/silverstripe/silverstripe-subsites
synced 2024-10-22 11:05:55 +02:00
Merge pull request #115 from mateusz/admin-access
Fix CMS Admin access issues
This commit is contained in:
commit
7c100f90d2
@ -30,17 +30,4 @@ class SubsiteAdmin extends ModelAdmin {
|
||||
return $form;
|
||||
}
|
||||
|
||||
public function getResponseNegotiator() {
|
||||
$negotiator = parent::getResponseNegotiator();
|
||||
$self = $this;
|
||||
// Register a new callback
|
||||
$negotiator->setCallback('SubsiteList', function() use(&$self) {
|
||||
return $self->SubsiteList();
|
||||
});
|
||||
return $negotiator;
|
||||
}
|
||||
|
||||
public function SubsiteList() {
|
||||
return $this->renderWith('SubsiteList');
|
||||
}
|
||||
}
|
||||
|
38
code/SubsiteXHRController.php
Normal file
38
code/SubsiteXHRController.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Section-agnostic PJAX controller.
|
||||
*/
|
||||
class SubsiteXHRController extends LeftAndMain {
|
||||
|
||||
/**
|
||||
* Relax the access permissions, so anyone who has access to any CMS subsite can access this controller.
|
||||
*/
|
||||
public function canView($member = null) {
|
||||
if (parent::canView()) return true;
|
||||
|
||||
if (Subsite::all_accessible_sites()->count()>0) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getResponseNegotiator() {
|
||||
$negotiator = parent::getResponseNegotiator();
|
||||
$self = $this;
|
||||
|
||||
// Register a new callback
|
||||
$negotiator->setCallback('SubsiteList', function() use(&$self) {
|
||||
return $self->SubsiteList();
|
||||
});
|
||||
|
||||
return $negotiator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the list of available subsites as a cms-section-agnostic PJAX handler.
|
||||
*/
|
||||
public function SubsiteList() {
|
||||
return $this->renderWith('SubsiteList');
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
/**
|
||||
* Decorator designed to add subsites support to LeftAndMain
|
||||
*
|
||||
*
|
||||
* @package subsites
|
||||
*/
|
||||
class LeftAndMainSubsites extends Extension {
|
||||
@ -9,26 +9,9 @@ class LeftAndMainSubsites extends Extension {
|
||||
private static $allowed_actions = array('CopyToSubsite');
|
||||
|
||||
function init() {
|
||||
|
||||
//Use the session variable for current subsite in the CMS only
|
||||
Subsite::$use_session_subsiteid = true;
|
||||
|
||||
Requirements::css('subsites/css/LeftAndMain_Subsites.css');
|
||||
Requirements::javascript('subsites/javascript/LeftAndMain_Subsites.js');
|
||||
Requirements::javascript('subsites/javascript/VirtualPage_Subsites.js');
|
||||
|
||||
if(isset($_GET['SubsiteID'])) {
|
||||
// Clear current page when subsite changes (or is set for the first time)
|
||||
if(!Session::get('SubsiteID') || $_GET['SubsiteID'] != Session::get('SubsiteID')) {
|
||||
Session::clear("{$this->owner->class}.currentPage");
|
||||
}
|
||||
|
||||
// Update current subsite in session
|
||||
Subsite::changeSubsite($_GET['SubsiteID']);
|
||||
|
||||
//Redirect to clear the current page
|
||||
return $this->owner->redirect('admin/');
|
||||
}
|
||||
|
||||
// Set subsite ID based on currently shown record
|
||||
$req = $this->owner->getRequest();
|
||||
@ -50,24 +33,61 @@ class LeftAndMainSubsites extends Extension {
|
||||
function updatePageOptions(&$fields) {
|
||||
$fields->push(new HiddenField('SubsiteID', 'SubsiteID', Subsite::currentSubsiteID()));
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a list of the subsites accessible to the current user
|
||||
|
||||
/**
|
||||
* Find all subsites accessible for current user on this controller.
|
||||
*
|
||||
* @return ArrayList of {@link Subsite} instances.
|
||||
*/
|
||||
public function Subsites() {
|
||||
// figure out what permission the controller needs
|
||||
// Subsite::accessible_sites() expects something, so if there's no permission
|
||||
// then fallback to using CMS_ACCESS_LeftAndMain.
|
||||
$permission = 'CMS_ACCESS_' . $this->owner->class;
|
||||
$available = Permission::get_codes(false);
|
||||
if(!isset($available[$permission])) {
|
||||
$permission = $this->owner->stat('required_permission_codes');
|
||||
if(!$permission) {
|
||||
$permission = 'CMS_ACCESS_LeftAndMain';
|
||||
function sectionSites($includeMainSite = true, $mainSiteTitle = "Main site", $member = null) {
|
||||
// Rationalise member arguments
|
||||
if(!$member) $member = Member::currentUser();
|
||||
if(!$member) return new ArrayList();
|
||||
if(!is_object($member)) $member = DataObject::get_by_id('Member', $member);
|
||||
|
||||
// Collect permissions - honour the LeftAndMain::required_permission_codes, current model requires
|
||||
// us to check if the user satisfies ALL permissions. Code partly copied from LeftAndMain::canView.
|
||||
$codes = array();
|
||||
$extraCodes = Config::inst()->get($this->owner->class, 'required_permission_codes');
|
||||
if($extraCodes !== false) {
|
||||
if($extraCodes) $codes = array_merge($codes, (array)$extraCodes);
|
||||
else $codes[] = "CMS_ACCESS_{$this->owner->class}";
|
||||
} else {
|
||||
// Check overriden - all subsites accessible.
|
||||
return Subsite::all_sites();
|
||||
}
|
||||
|
||||
// Find subsites satisfying all permissions for the Member.
|
||||
$codesPerSite = array();
|
||||
$sitesArray = array();
|
||||
foreach ($codes as $code) {
|
||||
$sites = Subsite::accessible_sites($code, $includeMainSite, $mainSiteTitle, $member);
|
||||
foreach ($sites as $site) {
|
||||
// Build the structure for checking how many codes match.
|
||||
$codesPerSite[$site->ID][$code] = true;
|
||||
|
||||
// Retain Subsite objects for later.
|
||||
$sitesArray[$site->ID] = $site;
|
||||
}
|
||||
}
|
||||
|
||||
return Subsite::accessible_sites($permission);
|
||||
// Find sites that satisfy all codes conjuncitvely.
|
||||
$accessibleSites = new ArrayList();
|
||||
foreach ($codesPerSite as $siteID => $siteCodes) {
|
||||
if (count($siteCodes)==count($codes)) {
|
||||
$accessibleSites->push($sitesArray[$siteID]);
|
||||
}
|
||||
}
|
||||
|
||||
return $accessibleSites;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a list of the subsites accessible to the current user.
|
||||
* It's enough for any section to be accessible for the section to be included.
|
||||
*/
|
||||
public function Subsites() {
|
||||
return Subsite::all_accessible_sites();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -101,38 +121,26 @@ class LeftAndMainSubsites extends Extension {
|
||||
return $output;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a subset of the main menu, filtered by admins that have
|
||||
* a subsiteCMSShowInMenu method returning true
|
||||
*
|
||||
* @return ArrayList
|
||||
*/
|
||||
public function SubsiteMainMenu(){
|
||||
public function alternateMenuDisplayCheck($controllerName) {
|
||||
if(!class_exists($controllerName)){
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check subsite support.
|
||||
if(Subsite::currentSubsiteID() == 0){
|
||||
return $this->owner->MainMenu();
|
||||
}
|
||||
// loop main menu items, add all items that have subsite support
|
||||
$mainMenu = $this->owner->MainMenu();
|
||||
$subsitesMenu = new ArrayList();
|
||||
|
||||
foreach($mainMenu as $menuItem){
|
||||
|
||||
$controllerName = $menuItem->MenuItem->controller;
|
||||
|
||||
if(class_exists($controllerName)){
|
||||
$controller = singleton($controllerName);
|
||||
|
||||
if($controller->hasMethod('subsiteCMSShowInMenu') && $controller->subsiteCMSShowInMenu()){
|
||||
$subsitesMenu->push($menuItem);
|
||||
}
|
||||
// Main site always supports everything.
|
||||
return true;
|
||||
} else {
|
||||
$controller = singleton($controllerName);
|
||||
if($controller->hasMethod('subsiteCMSShowInMenu') && $controller->subsiteCMSShowInMenu()){
|
||||
return true;
|
||||
}
|
||||
|
||||
if($menuItem->Code == 'Help'){
|
||||
$subsitesMenu->push($menuItem);
|
||||
}
|
||||
|
||||
}
|
||||
return $subsitesMenu;
|
||||
|
||||
// It's not necessary to check access permissions here. Framework calls canView on the controller,
|
||||
// which in turn uses the Permission API which is augmented by our GroupSubsites.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function CanAddSubsites() {
|
||||
@ -140,58 +148,88 @@ class LeftAndMainSubsites extends Extension {
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternative security checker for LeftAndMain.
|
||||
* If security isn't found, then it will switch to a subsite where we do have access.
|
||||
* Do some pre-flight checks if a subsite switch is needed.
|
||||
* We redirect the user to something accessible if the current section/subsite is forbidden.
|
||||
*/
|
||||
public function alternateAccessCheck() {
|
||||
public function onBeforeInit() {
|
||||
// We are accessing the CMS, so we need to let Subsites know we will be using the session.
|
||||
Subsite::$use_session_subsiteid = true;
|
||||
|
||||
// Do not try to be smart for AJAX requests.
|
||||
if ($this->owner->request->isAjax()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Catch forced subsite changes that need to cause CMS reloads.
|
||||
if(isset($_GET['SubsiteID'])) {
|
||||
// Clear current page when subsite changes (or is set for the first time)
|
||||
if(!Session::get('SubsiteID') || $_GET['SubsiteID'] != Session::get('SubsiteID')) {
|
||||
Session::clear("{$this->owner->class}.currentPage");
|
||||
}
|
||||
|
||||
// Update current subsite in session
|
||||
Subsite::changeSubsite($_GET['SubsiteID']);
|
||||
|
||||
//Redirect to clear the current page
|
||||
return $this->owner->redirect('admin/');
|
||||
}
|
||||
|
||||
$className = $this->owner->class;
|
||||
|
||||
// Switch to the subsite of the current page
|
||||
// Transparently switch to the subsite of the current page.
|
||||
if ($this->owner->class == 'CMSMain' && $currentPage = $this->owner->currentPage()) {
|
||||
if (Subsite::currentSubsiteID() != $currentPage->SubsiteID) {
|
||||
Subsite::changeSubsite($currentPage->SubsiteID);
|
||||
}
|
||||
}
|
||||
|
||||
// Switch to a subsite that this user can actually access.
|
||||
$member = Member::currentUser();
|
||||
if($member && Permission::checkMember($member, 'ADMIN')) return true; // admin can access all subsites
|
||||
|
||||
$sites = Subsite::accessible_sites("CMS_ACCESS_{$this->owner->class}", true)->map('ID', 'Title');
|
||||
if(is_object($sites)) $sites = $sites->toArray();
|
||||
|
||||
if($sites && !isset($sites[Subsite::currentSubsiteID()])) {
|
||||
$siteIDs = array_keys($sites);
|
||||
Subsite::changeSubsite($siteIDs[0]);
|
||||
return true;
|
||||
// If we can view current URL there is nothing to do.
|
||||
if ($this->owner->canView()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Switch to a different top-level menu item
|
||||
|
||||
// Admin can access everything, no point in checking.
|
||||
$member = Member::currentUser();
|
||||
if($member && Permission::checkMember($member, 'ADMIN')) return;
|
||||
|
||||
// Check if we have access to current section on the current subsite.
|
||||
$accessibleSites = $this->owner->sectionSites($member);
|
||||
if ($accessibleSites->count() && $accessibleSites->find('ID', Subsite::currentSubsiteID())) {
|
||||
// Current section can be accessed on the current site, all good.
|
||||
return;
|
||||
}
|
||||
|
||||
// If the current section is not accessible, try at least to stick to the same subsite.
|
||||
$menu = CMSMenu::get_menu_items();
|
||||
foreach($menu as $candidate) {
|
||||
if($candidate->controller != $this->owner->class) {
|
||||
$sites = Subsite::accessible_sites("CMS_ACCESS_{$candidate->controller}", true)->map('ID', 'Title');
|
||||
if(is_object($sites)) $sites = $sites->toArray();
|
||||
|
||||
if($sites && !isset($sites[Subsite::currentSubsiteID()])) {
|
||||
$siteIDs = array_keys($sites);
|
||||
Subsite::changeSubsite($siteIDs[0]);
|
||||
$cClass = $candidate->controller;
|
||||
$cObj = new $cClass();
|
||||
$this->owner->redirect($cObj->Link());
|
||||
return null;
|
||||
if($candidate->controller && $candidate->controller!=$this->owner->class) {
|
||||
|
||||
$accessibleSites = singleton($candidate->controller)->sectionSites(true, 'Main site', $member);
|
||||
if ($accessibleSites->count() && $accessibleSites->find('ID', Subsite::currentSubsiteID())) {
|
||||
// Section is accessible, redirect there.
|
||||
$this->owner->redirect(singleton($candidate->controller)->Link());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, if no section is available, move to any other permitted subsite.
|
||||
foreach($menu as $candidate) {
|
||||
if($candidate->controller) {
|
||||
$accessibleSites = singleton($candidate->controller)->sectionSites(true, 'Main site', $member);
|
||||
if ($accessibleSites->count()) {
|
||||
Subsite::changeSubsite($accessibleSites->First()->ID);
|
||||
$this->owner->redirect(singleton($candidate->controller)->Link());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If all of those fail, you really don't have access to the CMS
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
function augmentNewSiteTreeItem(&$item) {
|
||||
$item->SubsiteID = isset($_POST['SubsiteID']) ? $_POST['SubsiteID'] : Subsite::currentSubsiteID();
|
||||
}
|
||||
|
||||
|
||||
function onAfterSave($record) {
|
||||
if($record->hasMethod('NormalRelated') && ($record->NormalRelated() || $record->ReverseRelated())) {
|
||||
$this->owner->response->addHeader('X-Status', rawurlencode(_t('LeftAndMainSubsites.Saved', 'Saved, please update related pages.')));
|
||||
|
@ -310,10 +310,9 @@ JS;
|
||||
|
||||
if(isset($_GET['SubsiteID'])) {
|
||||
$id = (int)$_GET['SubsiteID'];
|
||||
}
|
||||
else if (Subsite::$use_session_subsiteid) {
|
||||
} else if (Subsite::$use_session_subsiteid) {
|
||||
$id = Session::get('SubsiteID');
|
||||
}
|
||||
}
|
||||
|
||||
if($id === NULL) {
|
||||
$id = self::getSubsiteIDForDomain();
|
||||
@ -522,12 +521,64 @@ JS;
|
||||
return $duplicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all subsites, regardless of permissions (augmented with main site).
|
||||
*
|
||||
* @return SS_List List of {@link Subsite} objects (DataList or ArrayList).
|
||||
*/
|
||||
public static function all_sites($includeMainSite = true, $mainSiteTitle = "Main site") {
|
||||
$subsites = Subsite::get();
|
||||
|
||||
if($includeMainSite) {
|
||||
$subsites = $subsites->toArray();
|
||||
|
||||
$mainSite = new Subsite();
|
||||
$mainSite->Title = $mainSiteTitle;
|
||||
array_unshift($subsites, $mainSite);
|
||||
|
||||
$subsites = ArrayList::create($subsites);
|
||||
}
|
||||
|
||||
return $subsites;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns an ArrayList of the subsites accessible to the current user.
|
||||
* It's enough for any section to be accessible for the site to be included.
|
||||
*
|
||||
* @return ArrayList of {@link Subsite} instances.
|
||||
*/
|
||||
public static function all_accessible_sites($includeMainSite = true, $mainSiteTitle = "Main site", $member = null) {
|
||||
// Rationalise member arguments
|
||||
if(!$member) $member = Member::currentUser();
|
||||
if(!$member) return new ArrayList();
|
||||
if(!is_object($member)) $member = DataObject::get_by_id('Member', $member);
|
||||
|
||||
$subsites = new ArrayList();
|
||||
|
||||
// Collect subsites for all sections.
|
||||
$menu = CMSMenu::get_viewable_menu_items();
|
||||
foreach($menu as $candidate) {
|
||||
if ($candidate->controller) {
|
||||
$accessibleSites = singleton($candidate->controller)->sectionSites(
|
||||
$includeMainSite,
|
||||
$mainSiteTitle,
|
||||
$member
|
||||
);
|
||||
|
||||
// Replace existing keys so no one site appears twice.
|
||||
$subsites->merge($accessibleSites);
|
||||
}
|
||||
}
|
||||
|
||||
$subsites->removeDuplicates();
|
||||
|
||||
return $subsites;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the subsites that the current user can access.
|
||||
* Look for one of the given permission codes on the site.
|
||||
*
|
||||
* Sites will only be included if they have a Title
|
||||
* Return the subsites that the current user can access by given permission.
|
||||
* Sites will only be included if they have a Title.
|
||||
*
|
||||
* @param $permCode array|string Either a single permission code or an array of permission codes.
|
||||
* @param $includeMainSite If true, the main site will be included if appropriate.
|
||||
|
@ -58,7 +58,7 @@
|
||||
*/
|
||||
$('.cms-container .cms-menu-list li a').entwine({
|
||||
onclick: function(e) {
|
||||
$('.cms-container').subsiteFetchPjaxFragment('admin/subsites/', 'SubsiteList');
|
||||
$('.cms-container').subsiteFetchPjaxFragment('SubsiteXHRController', 'SubsiteList');
|
||||
this._super(e);
|
||||
}
|
||||
});
|
||||
@ -68,7 +68,7 @@
|
||||
*/
|
||||
$('.cms-container .SubsiteAdmin .cms-edit-form fieldset.ss-gridfield').entwine({
|
||||
onreload: function(e) {
|
||||
$('.cms-container').subsiteFetchPjaxFragment('admin/subsites/', 'SubsiteList');
|
||||
$('.cms-container').subsiteFetchPjaxFragment('SubsiteXHRController', 'SubsiteList');
|
||||
this._super(e);
|
||||
}
|
||||
});
|
||||
@ -81,7 +81,7 @@
|
||||
*/
|
||||
$('.cms-container .cms-content-fields .subsite-model').entwine({
|
||||
onadd: function(e) {
|
||||
$('.cms-container').subsiteFetchPjaxFragment('admin/subsites/', 'SubsiteList');
|
||||
$('.cms-container').subsiteFetchPjaxFragment('SubsiteXHRController', 'SubsiteList');
|
||||
this._super(e);
|
||||
}
|
||||
});
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
<div class="cms-panel-content center">
|
||||
<ul class="cms-menu-list">
|
||||
<% loop $SubsiteMainMenu %>
|
||||
<% loop $MainMenu %>
|
||||
<li class="$LinkingMode $FirstLast <% if $LinkingMode == 'link' %><% else %>opened<% end_if %>" id="Menu-$Code" title="$Title.ATT">
|
||||
<a href="$Link" <% if $Code == 'Help' %>target="_blank"<% end_if %>>
|
||||
<span class="icon icon-16 icon-{$Code.LowerCase}"> </span>
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
<?php
|
||||
|
||||
class LeftAndMainSubsitesTest extends FunctionalTest {
|
||||
|
||||
static $fixture_file = 'subsites/tests/SubsiteTest.yml';
|
||||
@ -9,12 +10,34 @@ class LeftAndMainSubsitesTest extends FunctionalTest {
|
||||
function objFromFixture($class, $id) {
|
||||
Subsite::disable_subsite_filter(true);
|
||||
$obj = parent::objFromFixture($class, $id);
|
||||
Subsite::disable_subsite_filter(false);
|
||||
Subsite::disable_subsite_filter(false);
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
function testAlternateAccessCheck() {
|
||||
|
||||
function testSectionSites() {
|
||||
$member = $this->objFromFixture('Member', 'subsite1member');
|
||||
|
||||
$cmsmain = singleton('CMSMain');
|
||||
$subsites = $cmsmain->sectionSites(true, "Main site", $member);
|
||||
$this->assertDOSEquals(array(
|
||||
array('Title' =>'Subsite1 Template')
|
||||
), $subsites, 'Lists member-accessible sites for the accessible controller.');
|
||||
|
||||
$assetadmin = singleton('AssetAdmin');
|
||||
$subsites = $assetadmin->sectionSites(true, "Main site", $member);
|
||||
$this->assertDOSEquals(array(), $subsites, 'Does not list any sites for forbidden controller.');
|
||||
|
||||
$member = $this->objFromFixture('Member', 'editor');
|
||||
|
||||
$cmsmain = singleton('CMSMain');
|
||||
$subsites = $cmsmain->sectionSites(true, "Main site", $member);
|
||||
$this->assertDOSContains(array(
|
||||
array('Title' =>'Main site')
|
||||
), $subsites, 'Includes the main site for members who can access all sites.');
|
||||
}
|
||||
|
||||
function testAccessChecksDontChangeCurrentSubsite() {
|
||||
$admin = $this->objFromFixture("Member","admin");
|
||||
$this->loginAs($admin);
|
||||
$ids = array();
|
||||
@ -28,11 +51,17 @@ class LeftAndMainSubsitesTest extends FunctionalTest {
|
||||
$ids[] = $subsite3->ID;
|
||||
$ids[] = 0;
|
||||
|
||||
// Enable session-based subsite tracking.
|
||||
Subsite::$use_session_subsiteid = true;
|
||||
|
||||
foreach($ids as $id) {
|
||||
Subsite::changeSubsite($id); //switch to main site (subsite ID zero)
|
||||
Subsite::changeSubsite($id);
|
||||
$this->assertEquals($id, Subsite::currentSubsiteID());
|
||||
|
||||
$left = new LeftAndMain();
|
||||
$this->assertTrue($left->canView(), "Admin user can view subsites LeftAndMain with id = '$id'");
|
||||
$this->assertEquals($id, Subsite::currentSubsiteID(), "The current subsite has not been changed in the process of checking permissions for admin user.");
|
||||
$this->assertEquals($id, Subsite::currentSubsiteID(),
|
||||
"The current subsite has not been changed in the process of checking permissions for admin user.");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ class SiteTreeSubsitesTest extends BaseSubsiteTest {
|
||||
|
||||
function testBasicSanity() {
|
||||
$this->assertTrue(singleton('SiteTree')->getSiteConfig() instanceof SiteConfig);
|
||||
// The following assert is breaking in Translatable.
|
||||
$this->assertTrue(singleton('SiteTree')->getCMSFields() instanceof FieldList);
|
||||
$this->assertTrue(singleton('SubsitesVirtualPage')->getCMSFields() instanceof FieldList);
|
||||
$this->assertTrue(is_array(singleton('SiteTreeSubsites')->extraStatics()));
|
||||
|
@ -6,6 +6,35 @@ class SubsiteAdminFunctionalTest extends FunctionalTest {
|
||||
|
||||
protected $autoFollowRedirection = false;
|
||||
|
||||
/**
|
||||
* Helper: FunctionalTest is only able to follow redirection once, we want to go all the way.
|
||||
*/
|
||||
function getAndFollowAll($url) {
|
||||
$response = $this->get($url);
|
||||
while ($location = $response->getHeader('Location')) {
|
||||
$response = $this->mainSession->followRedirection();
|
||||
}
|
||||
echo $response->getHeader('Location');
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Anonymous user cannot access anything.
|
||||
*/
|
||||
function testAnonymousIsForbiddenAdminAccess() {
|
||||
$response = $this->getAndFollowAll('admin/pages/?SubsiteID=0');
|
||||
$this->assertRegExp('#^Security/login.*#', $this->mainSession->lastUrl(), 'Admin is disallowed');
|
||||
|
||||
$subsite1 = $this->objFromFixture('Subsite', 'subsite1');
|
||||
$response = $this->getAndFollowAll("admin/pages/?SubsiteID={$subsite1->ID}");
|
||||
$this->assertRegExp('#^Security/login.*#', $this->mainSession->lastUrl(), 'Admin is disallowed');
|
||||
|
||||
$response = $this->getAndFollowAll('SubsiteXHRController');
|
||||
$this->assertRegExp('#^Security/login.*#', $this->mainSession->lastUrl(),
|
||||
'SubsiteXHRController is disallowed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Admin should be able to access all subsites and the main site
|
||||
*/
|
||||
@ -13,14 +42,18 @@ class SubsiteAdminFunctionalTest extends FunctionalTest {
|
||||
$member = $this->objFromFixture('Member', 'admin');
|
||||
Session::set("loggedInAs", $member->ID);
|
||||
|
||||
$this->get('admin/pages?SubsiteID=0&ajax=1');
|
||||
$this->get('admin');
|
||||
$this->assertEquals(Subsite::currentSubsiteID(), '0', 'Can access main site');
|
||||
$this->getAndFollowAll('admin/pages/?SubsiteID=0');
|
||||
$this->assertEquals(Subsite::currentSubsiteID(), '0', 'Can access main site.');
|
||||
$this->assertRegExp('#^admin/pages.*#', $this->mainSession->lastUrl(), 'Lands on the correct section');
|
||||
|
||||
$mainSubsite = $this->objFromFixture('Subsite', 'main');
|
||||
$this->get("admin/pages?SubsiteID={$mainSubsite->ID}&ajax=1");
|
||||
$this->get('admin');
|
||||
$this->assertEquals(Subsite::currentSubsiteID(), $mainSubsite->ID, 'Can access the subsite');
|
||||
$subsite1 = $this->objFromFixture('Subsite', 'subsite1');
|
||||
$this->getAndFollowAll("admin/pages/?SubsiteID={$subsite1->ID}");
|
||||
$this->assertEquals(Subsite::currentSubsiteID(), $subsite1->ID, 'Can access other subsite.');
|
||||
$this->assertRegExp('#^admin/pages.*#', $this->mainSession->lastUrl(), 'Lands on the correct section');
|
||||
|
||||
$response = $this->getAndFollowAll('SubsiteXHRController');
|
||||
$this->assertNotRegExp('#^Security/login.*#', $this->mainSession->lastUrl(),
|
||||
'SubsiteXHRController is reachable');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -30,14 +63,48 @@ class SubsiteAdminFunctionalTest extends FunctionalTest {
|
||||
function testEditorCanAccessAllSubsites() {
|
||||
$member = $this->objFromFixture('Member', 'editor');
|
||||
Session::set("loggedInAs", $member->ID);
|
||||
|
||||
$this->get('admin/pages?SubsiteID=0&ajax=1');
|
||||
$this->get('admin');
|
||||
$this->assertEquals(Subsite::currentSubsiteID(), '0', 'Can access main site');
|
||||
|
||||
$mainSubsite = $this->objFromFixture('Subsite', 'main');
|
||||
$this->get("admin/pages?SubsiteID={$mainSubsite->ID}&ajax=1");
|
||||
$this->get('admin');
|
||||
$this->assertEquals(Subsite::currentSubsiteID(), $mainSubsite->ID, 'Can access the subsite');
|
||||
$this->getAndFollowAll('admin/pages/?SubsiteID=0');
|
||||
$this->assertEquals(Subsite::currentSubsiteID(), '0', 'Can access main site.');
|
||||
$this->assertRegExp('#^admin/pages.*#', $this->mainSession->lastUrl(), 'Lands on the correct section');
|
||||
|
||||
$subsite1 = $this->objFromFixture('Subsite', 'subsite1');
|
||||
$this->getAndFollowAll("admin/pages/?SubsiteID={$subsite1->ID}");
|
||||
$this->assertEquals(Subsite::currentSubsiteID(), $subsite1->ID, 'Can access other subsite.');
|
||||
$this->assertRegExp('#^admin/pages.*#', $this->mainSession->lastUrl(), 'Lands on the correct section');
|
||||
|
||||
$response = $this->getAndFollowAll('SubsiteXHRController');
|
||||
$this->assertNotRegExp('#^Security/login.*#', $this->mainSession->lastUrl(),
|
||||
'SubsiteXHRController is reachable');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a member who only has access to one subsite (subsite1) and only some sections (pages and security).
|
||||
*/
|
||||
function testSubsiteAdmin() {
|
||||
$member = $this->objFromFixture('Member', 'subsite1member');
|
||||
Session::set("loggedInAs", $member->ID);
|
||||
|
||||
$subsite1 = $this->objFromFixture('Subsite', 'subsite1');
|
||||
|
||||
// Check allowed URL.
|
||||
$this->getAndFollowAll("admin/pages/?SubsiteID={$subsite1->ID}");
|
||||
$this->assertEquals(Subsite::currentSubsiteID(), $subsite1->ID, 'Can access own subsite.');
|
||||
$this->assertRegExp('#^admin/pages.*#', $this->mainSession->lastUrl(), 'Can access permitted section.');
|
||||
|
||||
// Check forbidden section in allowed subsite.
|
||||
$this->getAndFollowAll("admin/assets/?SubsiteID={$subsite1->ID}");
|
||||
$this->assertEquals(Subsite::currentSubsiteID(), $subsite1->ID, 'Is redirected within subsite.');
|
||||
$this->assertNotRegExp('#^admin/assets/.*#', $this->mainSession->lastUrl(),
|
||||
'Is redirected away from forbidden section');
|
||||
|
||||
// Check forbidden site.
|
||||
$this->getAndFollowAll("admin/pages/?SubsiteID=0");
|
||||
$this->assertEquals(Subsite::currentSubsiteID(), $subsite1->ID, 'Is redirected to permitted subsite.');
|
||||
|
||||
// Check the standalone XHR controller.
|
||||
$response = $this->getAndFollowAll('SubsiteXHRController');
|
||||
$this->assertNotRegExp('#^Security/login.*#', $this->mainSession->lastUrl(),
|
||||
'SubsiteXHRController is reachable');
|
||||
}
|
||||
}
|
||||
|
@ -241,7 +241,29 @@ class SubsiteTest extends BaseSubsiteTest {
|
||||
|
||||
$_SERVER['HTTP_HOST'] = $originalHTTPHost;
|
||||
}
|
||||
|
||||
|
||||
function testAllSites() {
|
||||
$subsites = Subsite::all_sites();
|
||||
$this->assertDOSEquals(array(
|
||||
array('Title' =>'Main site'),
|
||||
array('Title' =>'Template'),
|
||||
array('Title' =>'Subsite1 Template'),
|
||||
array('Title' =>'Subsite2 Template'),
|
||||
array('Title' =>'Test 1'),
|
||||
array('Title' =>'Test 2'),
|
||||
array('Title' =>'Test 3')
|
||||
), $subsites, 'Lists all subsites');
|
||||
}
|
||||
|
||||
function testAllAccessibleSites() {
|
||||
$member = $this->objFromFixture('Member', 'subsite1member');
|
||||
|
||||
$subsites = Subsite::all_accessible_sites(true, 'Main site', $member);
|
||||
$this->assertDOSEquals(array(
|
||||
array('Title' =>'Subsite1 Template')
|
||||
), $subsites, 'Lists member-accessible sites.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Subsite::accessible_sites()
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user