From f0e93b1b3cb7d642bcd4d324aeada5b4ed446e0c Mon Sep 17 00:00:00 2001 From: Mateusz Uzdowski Date: Mon, 11 Apr 2011 10:32:51 +1200 Subject: [PATCH 1/3] BUGFIX: flush cache always after changing the subsite - otherwise a user who has access only to one of the subsites will not be able to get to the CMS at all. --- code/Subsite.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/Subsite.php b/code/Subsite.php index c8a4f2a..c42cc6f 100644 --- a/code/Subsite.php +++ b/code/Subsite.php @@ -265,8 +265,7 @@ JS; } } - // Only bother flushing caches if we've actually changed - if($subsiteID != self::currentSubsiteID()) Permission::flush_permission_cache(); + Permission::flush_permission_cache(); } /** From fb998aec870b6ebe56268d0bc370f4df3ad8dbda Mon Sep 17 00:00:00 2001 From: Mateusz Uzdowski Date: Mon, 11 Apr 2011 12:59:42 +1200 Subject: [PATCH 2/3] BUGFIX: Change the default setting to include the main site. Users able to AccessAllSites should be able to access the main site as well. --- code/Subsite.php | 2 +- tests/SubsiteAdminFunctionalTest.php | 43 ++++++++++++++++++++++++++++ tests/SubsiteAdminTest.php | 2 +- tests/SubsiteTest.yml | 24 +++++++++++++++- 4 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 tests/SubsiteAdminFunctionalTest.php diff --git a/code/Subsite.php b/code/Subsite.php index c42cc6f..88bed05 100644 --- a/code/Subsite.php +++ b/code/Subsite.php @@ -408,7 +408,7 @@ JS; * @param $includeMainSite If true, the main site will be included if appropriate. * @param $mainSiteTitle The label to give to the main site */ - function accessible_sites($permCode, $includeMainSite = false, $mainSiteTitle = "Main site", $member = null) { + function accessible_sites($permCode, $includeMainSite = true, $mainSiteTitle = "Main site", $member = null) { // Rationalise member arguments if(!$member) $member = Member::currentUser(); if(!$member) return new DataObjectSet(); diff --git a/tests/SubsiteAdminFunctionalTest.php b/tests/SubsiteAdminFunctionalTest.php new file mode 100644 index 0000000..1568f51 --- /dev/null +++ b/tests/SubsiteAdminFunctionalTest.php @@ -0,0 +1,43 @@ +objFromFixture('Member', 'admin'); + Session::set("loggedInAs", $member->ID); + + $this->get('admin/changesubsite?SubsiteID=0&ajax=1'); + $this->get('admin'); + $this->assertEquals(Subsite::currentSubsiteID(), '0', 'Can access main site'); + + $mainSubsite = $this->objFromFixture('Subsite_Template', 'main'); + $this->get("admin/changesubsite?SubsiteID={$mainSubsite->ID}&ajax=1"); + $this->get('admin'); + $this->assertEquals(Subsite::currentSubsiteID(), $mainSubsite->ID, 'Can access the subsite'); + } + + /** + * User which has AccessAllSubsites set to 1 should be able to access all subsites and main site, + * even though he does not have the ADMIN permission. + */ + function testEditorCanAccessAllSubsites() { + $member = $this->objFromFixture('Member', 'editor'); + Session::set("loggedInAs", $member->ID); + + $this->get('admin/changesubsite?SubsiteID=0&ajax=1'); + $this->get('admin'); + $this->assertEquals(Subsite::currentSubsiteID(), '0', 'Can access main site'); + + $mainSubsite = $this->objFromFixture('Subsite_Template', 'main'); + $this->get("admin/changesubsite?SubsiteID={$mainSubsite->ID}&ajax=1"); + $this->get('admin'); + $this->assertEquals(Subsite::currentSubsiteID(), $mainSubsite->ID, 'Can access the subsite'); + } +} diff --git a/tests/SubsiteAdminTest.php b/tests/SubsiteAdminTest.php index 2988540..b2f344e 100644 --- a/tests/SubsiteAdminTest.php +++ b/tests/SubsiteAdminTest.php @@ -112,4 +112,4 @@ class SubsiteAdminTest extends SapphireTest { } -?> \ No newline at end of file +?> diff --git a/tests/SubsiteTest.yml b/tests/SubsiteTest.yml index a82ef75..6caed8c 100644 --- a/tests/SubsiteTest.yml +++ b/tests/SubsiteTest.yml @@ -39,6 +39,9 @@ SubsiteDomain: IsPrimary: 1 SiteTree: + mainSubsitePage: + Title: MainSubsitePage + SubsiteID: 0 home: Title: Home SubsiteID: =>Subsite_Template.main @@ -77,6 +80,10 @@ Group: Title: Admin Code: admin AccessAllSubsites: 1 + editor: + Title: Editor + Code: editor + AccessAllSubsites: 1 subsite1_group: Title: subsite1_group Code: subsite1_group @@ -91,6 +98,15 @@ Permission: admin: Code: ADMIN GroupID: =>Group.admin + editor1: + Code: CMS_ACCESS_CMSMain + GroupID: =>Group.editor + editor2: + Code: SITETREE_VIEW_ALL + GroupID: =>Group.editor + editor3: + Code: VIEW_DRAFT_CONTENT + GroupID: =>Group.editor accesscmsmain1: Code: CMS_ACCESS_CMSMain GroupID: =>Group.subsite1_group @@ -111,9 +127,15 @@ Member: Email: admin@test.com Password: rangi Groups: =>Group.admin + editor: + FirstName: Editor + Surname: User + Email: editor@test.com + Password: rangi + Groups: =>Group.editor subsite1member: Email: subsite1member@test.com Groups: =>Group.subsite1_group subsite2member: Email: subsite2member@test.com - Groups: =>Group.subsite2_group \ No newline at end of file + Groups: =>Group.subsite2_group From 5f337db5534e30da0977fba16b72d95d232b5f92 Mon Sep 17 00:00:00 2001 From: Mateusz Uzdowski Date: Wed, 5 Oct 2011 15:02:57 +1300 Subject: [PATCH 3/3] BUGFIX: make sure non-admins can access the main site via group role --- code/LeftAndMainSubsites.php | 5 +++-- code/Subsite.php | 37 ++++++++++++++++++++++++++---------- tests/SubsiteTest.php | 18 ++++++++++++++++-- tests/SubsiteTest.yml | 17 ++++++++++++++++- 4 files changed, 62 insertions(+), 15 deletions(-) diff --git a/code/LeftAndMainSubsites.php b/code/LeftAndMainSubsites.php index 9d467f2..24740b5 100644 --- a/code/LeftAndMainSubsites.php +++ b/code/LeftAndMainSubsites.php @@ -127,7 +127,8 @@ class LeftAndMainSubsites extends Extension { $member = Member::currentUser(); if ($member && $member->isAdmin()) return true; //admin can access all subsites - $sites = Subsite::accessible_sites("CMS_ACCESS_{$this->owner->class}")->toDropdownMap(); + $sites = Subsite::accessible_sites("CMS_ACCESS_{$this->owner->class}", true)->toDropdownMap(); + if($sites && !isset($sites[Subsite::currentSubsiteID()])) { $siteIDs = array_keys($sites); Subsite::changeSubsite($siteIDs[0]); @@ -139,7 +140,7 @@ class LeftAndMainSubsites extends Extension { foreach($menu as $candidate) { if($candidate->controller != $this->owner->class) { - $sites = Subsite::accessible_sites("CMS_ACCESS_{$candidate->controller}")->toDropdownMap(); + $sites = Subsite::accessible_sites("CMS_ACCESS_{$candidate->controller}", true)->toDropdownMap(); if($sites && !isset($sites[Subsite::currentSubsiteID()])) { $siteIDs = array_keys($sites); Subsite::changeSubsite($siteIDs[0]); diff --git a/code/Subsite.php b/code/Subsite.php index 88bed05..49b32f0 100644 --- a/code/Subsite.php +++ b/code/Subsite.php @@ -347,6 +347,7 @@ JS; $SQL_perms = join("','", $SQLa_perm); $memberID = (int)$member->ID; + // Count this user's groups which can access the main site $groupCount = DB::query(" SELECT COUNT(\"Permission\".\"ID\") FROM \"Permission\" @@ -356,8 +357,21 @@ JS; AND \"MemberID\" = {$memberID} ")->value(); - return ($groupCount > 0); - + // Count this user's groups which have a role that can access the main site + $roleCount = DB::query(" + SELECT COUNT(\"PermissionRoleCode\".\"ID\") + FROM \"Group\" + INNER JOIN \"Group_Members\" ON \"Group_Members\".\"GroupID\" = \"Group\".\"ID\" + INNER JOIN \"Group_Roles\" ON \"Group_Roles\".\"GroupID\"=\"Group\".\"ID\" + INNER JOIN \"PermissionRole\" ON \"Group_Roles\".\"PermissionRoleID\"=\"PermissionRole\".\"ID\" + INNER JOIN \"PermissionRoleCode\" ON \"PermissionRole\".\"ID\"=\"PermissionRoleCode\".\"RoleID\" + WHERE \"PermissionRoleCode\".\"Code\" IN ('$SQL_perms') + AND \"Group\".\"AccessAllSubsites\" = 1 + AND \"MemberID\" = {$memberID} + ")->value(); + + // There has to be at least one that allows access. + return ($groupCount + $roleCount > 0); } /** @@ -419,6 +433,7 @@ JS; $templateClassList = "'" . implode("', '", ClassInfo::subclassesFor("Subsite_Template")) . "'"; + // Get all subsites accessible via a group $subsites = DataObject::get( 'Subsite', "\"Subsite\".\"Title\" != ''", @@ -434,7 +449,9 @@ JS; ON \"Group\".\"ID\"=\"Permission\".\"GroupID\" AND \"Permission\".\"Code\" IN ($SQL_codes, 'ADMIN')" ); + if (!$subsites) $subsites = new DataObjectSet(); + // Get all subsites accessible via a role $rolesSubsites = DataObject::get( 'Subsite', "\"Subsite\".\"Title\" != ''", @@ -454,17 +471,17 @@ JS; ON \"PermissionRole\".\"ID\"=\"PermissionRoleCode\".\"RoleID\" AND \"PermissionRoleCode\".\"Code\" IN ($SQL_codes, 'ADMIN')" ); - - if(!$subsites && $rolesSubsites) return $rolesSubsites; - - if($rolesSubsites) foreach($rolesSubsites as $subsite) { - if(!$subsites->containsIDs(array($subsite->ID))) { - $subsites->push($subsite); + + // Merge subsites + if($rolesSubsites) { + if($rolesSubsites) foreach($rolesSubsites as $subsite) { + if(!$subsites->containsIDs(array($subsite->ID))) { + $subsites->push($subsite); + } } } - // Include the main site - if(!$subsites) $subsites = new DataObjectSet(); + // Include the main site, if requested if($includeMainSite) { if(!is_array($permCode)) $permCode = array($permCode); if(self::hasMainSitePermission($member, $permCode)) { diff --git a/tests/SubsiteTest.php b/tests/SubsiteTest.php index 9faa80e..92314f8 100644 --- a/tests/SubsiteTest.php +++ b/tests/SubsiteTest.php @@ -109,7 +109,7 @@ class SubsiteTest extends SapphireTest { $this->objFromFixture('Member', 'subsite1member')); $member1SiteTitles = $member1Sites->column("Title"); sort($member1SiteTitles); - $this->assertEquals(array('Subsite1 Template'), $member1SiteTitles); + $this->assertEquals('Subsite1 Template', $member1SiteTitles[0], 'Member can get to a subsite via a group'); $adminSites = Subsite::accessible_sites("CMS_ACCESS_CMSMain", false, null, $this->objFromFixture('Member', 'admin')); @@ -123,6 +123,20 @@ class SubsiteTest extends SapphireTest { 'Test 2', 'Test 3', ), $adminSiteTitles); + + $member2Sites = Subsite::accessible_sites("CMS_ACCESS_CMSMain", false, null, + $this->objFromFixture('Member', 'subsite1member2')); + $member2SiteTitles = $member2Sites->column("Title"); + sort($member2SiteTitles); + $this->assertEquals('Subsite1 Template', $member2SiteTitles[0], 'Member can get to subsite via a group role'); + } + + function testHasMainSitePermission() { + $canAccess = Subsite::hasMainSitePermission($this->objFromFixture('Member', 'subsite1member'), array("CMS_ACCESS_CMSMain")); + $this->assertTrue($canAccess, 'Member has access to Main site via a group'); + + $canAccess = Subsite::hasMainSitePermission($this->objFromFixture('Member', 'subsite1member2'), array("CMS_ACCESS_CMSMain")); + $this->assertTrue($canAccess, 'Member has access to Main site via a group role'); } function testDuplicateSubsite() { @@ -150,4 +164,4 @@ class SubsiteTest extends SapphireTest { $subsite2->activate(); $this->assertEquals('MyNewAwesomePage', DataObject::get_by_id('Page', $page2->ID)->Title); } -} \ No newline at end of file +} diff --git a/tests/SubsiteTest.yml b/tests/SubsiteTest.yml index 6caed8c..33bb00c 100644 --- a/tests/SubsiteTest.yml +++ b/tests/SubsiteTest.yml @@ -75,6 +75,13 @@ SiteTree: Title: Contact Us (Subsite 2) SubsiteID: =>Subsite_Template.subsite2 +PermissionRoleCode: + roleCode1: + Code: CMS_ACCESS_CMSMain +PermissionRole: + role1: + Title: role1 + Codes: =>PermissionRoleCode.roleCode1 Group: admin: Title: Admin @@ -87,13 +94,18 @@ Group: subsite1_group: Title: subsite1_group Code: subsite1_group - AccessAllSubsites: 0 + AccessAllSubsites: 1 Subsites: =>Subsite_Template.subsite1 subsite2_group: Title: subsite2_group Code: subsite2_group AccessAllSubsites: 0 Subsites: =>Subsite_Template.subsite2 + subsite1_group_via_role: + Title: subsite1_group_via_role + Code: subsite1_group_via_role + AccessAllSubsites: 1 + Roles: =>PermissionRole.role1 Permission: admin: Code: ADMIN @@ -139,3 +151,6 @@ Member: subsite2member: Email: subsite2member@test.com Groups: =>Group.subsite2_group + subsite1member2: + Email: subsite1member2@test.com + Groups: =>Group.subsite1_group_via_role