diff --git a/code/extensions/LeftAndMainSubsites.php b/code/extensions/LeftAndMainSubsites.php index 7b93205..081ac85 100644 --- a/code/extensions/LeftAndMainSubsites.php +++ b/code/extensions/LeftAndMainSubsites.php @@ -127,11 +127,9 @@ class LeftAndMainSubsites extends Extension { // Switch to a subsite that this user can actually access. $member = Member::currentUser(); - if ($member && Permission::check('ADMIN')) { - return true; //admin can access all subsites - } + if($member && Permission::checkMember($member, 'ADMIN')) return true; // admin can access all subsites - $sites = Subsite::accessible_sites("CMS_ACCESS_{$this->owner->class}")->map('ID', 'Title'); + $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()])) { @@ -144,7 +142,7 @@ class LeftAndMainSubsites extends Extension { $menu = CMSMenu::get_menu_items(); foreach($menu as $candidate) { if($candidate->controller != $this->owner->class) { - $sites = Subsite::accessible_sites("CMS_ACCESS_{$candidate->controller}")->map('ID', 'Title'); + $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()])) { diff --git a/code/model/Subsite.php b/code/model/Subsite.php index db9c8b7..3fb25b5 100644 --- a/code/model/Subsite.php +++ b/code/model/Subsite.php @@ -308,8 +308,7 @@ JS; } } - // Only bother flushing caches if we've actually changed - if($subsiteID != self::currentSubsiteID()) Permission::flush_permission_cache(); + Permission::flush_permission_cache(); } /** @@ -413,6 +412,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\" @@ -422,8 +422,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); } /** @@ -514,14 +527,14 @@ JS; if(!$subsites && $rolesSubsites) return $rolesSubsites; + $subsites = new ArrayList($subsites->toArray()); + if($rolesSubsites) foreach($rolesSubsites as $subsite) { - if(!$subsites->containsIDs(array($subsite->ID))) { + if(!$subsites->find('ID', $subsite->ID)) { $subsites->push($subsite); } } - // Include the main site - if(!$subsites) $subsites = new ArrayList(); if($includeMainSite) { if(!is_array($permCode)) $permCode = array($permCode); if(self::hasMainSitePermission($member, $permCode)) { @@ -535,7 +548,6 @@ JS; } self::$_cache_accessible_sites[$cacheKey] = $subsites; - return $subsites; } diff --git a/tests/SubsiteAdminFunctionalTest.php b/tests/SubsiteAdminFunctionalTest.php new file mode 100644 index 0000000..a1e9f8b --- /dev/null +++ b/tests/SubsiteAdminFunctionalTest.php @@ -0,0 +1,43 @@ +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'); + + $mainSubsite = $this->objFromFixture('Subsite_Template', 'main'); + $this->get("admin/pages?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/pages?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/pages?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 a5e7903..fc39f3a 100644 --- a/tests/SubsiteAdminTest.php +++ b/tests/SubsiteAdminTest.php @@ -110,3 +110,4 @@ class SubsiteAdminTest extends SapphireTest { } + diff --git a/tests/SubsiteTest.php b/tests/SubsiteTest.php index c8ced5f..875a852 100644 --- a/tests/SubsiteTest.php +++ b/tests/SubsiteTest.php @@ -261,7 +261,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')); @@ -275,8 +275,14 @@ 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() { $admin = $this->objFromFixture('Member', 'admin'); $subsite1member = $this->objFromFixture('Member', 'subsite1member'); diff --git a/tests/SubsiteTest.yml b/tests/SubsiteTest.yml index ceb825c..363ccb8 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 @@ -75,11 +78,22 @@ SiteTree: Title: Contact Us SubsiteID: =>Subsite_Template.subsite2 +PermissionRoleCode: + roleCode1: + Code: CMS_ACCESS_CMSMain +PermissionRole: + role1: + Title: role1 + Codes: =>PermissionRoleCode.roleCode1 Group: admin: Title: Admin Code: admin AccessAllSubsites: 1 + editor: + Title: Editor + Code: editor + AccessAllSubsites: 1 subsite1_group: Title: subsite1_group Code: subsite1_group @@ -99,10 +113,24 @@ Group: Title: allsubsitesauthors Code: allsubsitesauthors AccessAllSubsites: 1 + subsite1_group_via_role: + Title: subsite1_group_via_role + Code: subsite1_group_via_role + AccessAllSubsites: 1 + Roles: =>PermissionRole.role1 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 @@ -132,6 +160,12 @@ 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 @@ -143,4 +177,7 @@ Member: Groups: =>Group.subsite1admins allsubsitesauthor: Email: allsubsitesauthor@test.com - Groups: =>Group.allsubsitesauthors \ No newline at end of file + Groups: =>Group.allsubsitesauthors + subsite1member2: + Email: subsite1member2@test.com + Groups: =>Group.subsite1_group_via_role