diff --git a/core/model/SiteConfig.php b/core/model/SiteConfig.php index c5ed09a09..1ca87fcd9 100644 --- a/core/model/SiteConfig.php +++ b/core/model/SiteConfig.php @@ -4,18 +4,21 @@ * Sitewide configuration * * @author Tom Rix + * @package cms */ -class SiteConfig extends DataObject implements PermissionProvider { +class SiteConfig extends DataObject { static $db = array( "Title" => "Varchar(255)", "Tagline" => "Varchar(255)", "CanViewType" => "Enum('Anyone, LoggedInUsers, OnlyTheseUsers', 'Anyone')", - "CanEditType" => "Enum('LoggedInUsers, OnlyTheseUsers', 'LoggedInUsers')" + "CanEditType" => "Enum('LoggedInUsers, OnlyTheseUsers', 'LoggedInUsers')", + "CanCreateTopLevelType" => "Enum('LoggedInUsers, OnlyTheseUsers', 'LoggedInUsers')", ); static $many_many = array( "ViewerGroups" => "Group", - "EditorGroups" => "Group" + "EditorGroups" => "Group", + "CreateTopLevelGroups" => "Group" ); /** @@ -28,16 +31,19 @@ class SiteConfig extends DataObject implements PermissionProvider { $fields = new FieldSet( new TabSet("Root", new Tab('Main', - $titleField = new TextField("Title", "Title"), - $taglineField = new TextField("Tagline", "Tagline") + $titleField = new TextField("Title", _t('SiteConfig.SITETITLE', "Site title")), + $taglineField = new TextField("Tagline", _t('SiteConfig.SITETAGLINE', "Site Tagline/Slogan")) ), new Tab('Access', - new HeaderField('WhoCanViewHeader', "Who can view pages on this site?", 2), + new HeaderField('WhoCanViewHeader', _t('SiteConfig.VIEWHEADER', "Who can view pages on this site?"), 2), $viewersOptionsField = new OptionsetField("CanViewType"), $viewerGroupsField = new TreeMultiselectField("ViewerGroups", _t('SiteTree.VIEWERGROUPS', "Viewer Groups")), - new HeaderField('WhoCanEditHeader', "Who can edit pages on this site?", 2), + new HeaderField('WhoCanEditHeader', _t('SiteConfig.EDITHEADER', "Who can edit pages on this site?"), 2), $editorsOptionsField = new OptionsetField("CanEditType"), - $editorGroupsField = new TreeMultiselectField("EditorGroups", _t('SiteTree.EDITORGROUPS', "Editor Groups")) + $editorGroupsField = new TreeMultiselectField("EditorGroups", _t('SiteTree.EDITORGROUPS', "Editor Groups")), + new HeaderField('WhoCanCreateTopLevelHeader', _t('SiteConfig.TOPLEVELCREATE', "Who can create pages in the root of the site?"), 2), + $topLevelCreatorsOptionsField = new OptionsetField("CanCreateTopLevelType"), + $topLevelCreatorsGroupsField = new TreeMultiselectField("CreateTopLevelGroups", _t('SiteTree.TOPLEVELCREATORGROUPS', "Top level creators")) ) ) ); @@ -52,12 +58,16 @@ class SiteConfig extends DataObject implements PermissionProvider { $editorsOptionsSource["LoggedInUsers"] = _t('SiteTree.EDITANYONE', "Anyone who can log-in to the CMS"); $editorsOptionsSource["OnlyTheseUsers"] = _t('SiteTree.EDITONLYTHESE', "Only these people (choose from list)"); $editorsOptionsField->setSource($editorsOptionsSource); + + $topLevelCreatorsOptionsField->setSource($editorsOptionsSource); if (!Permission::check('EDIT_SITECONFIG')) { $fields->makeFieldReadonly($viewersOptionsField); $fields->makeFieldReadonly($viewerGroupsField); $fields->makeFieldReadonly($editorsOptionsField); $fields->makeFieldReadonly($editorGroupsField); + $fields->makeFieldReadonly($topLevelCreatorsOptionsField); + $fields->makeFieldReadonly($topLevelCreatorsGroupsField); $fields->makeFieldReadonly($taglineField); $fields->makeFieldReadonly($titleField); } @@ -111,6 +121,11 @@ class SiteConfig extends DataObject implements PermissionProvider { } } + /** + * Make a default site config if there isn't on already + * + * @return void + */ static function make_site_config() { if(!DataObject::get_one('SiteConfig')){ $siteConfig = new SiteConfig(); @@ -120,6 +135,14 @@ class SiteConfig extends DataObject implements PermissionProvider { } } + /** + * Can a user view pages on this site? This method is only + * called if a page is set to Inherit, but there is nothing + * to inherit from. + * + * @param mixed $member + * @return boolean + */ public function canView($member = null) { if ($this->CanViewType == 'Anyone') return true; @@ -137,11 +160,19 @@ class SiteConfig extends DataObject implements PermissionProvider { return false; } + /** + * Can a user edit pages on this site? This method is only + * called if a page is set to Inherit, but there is nothing + * to inherit from. + * + * @param mixed $member + * @return boolean + */ public function canEdit($member = null) { if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) { $member = Member::currentUserID(); } - + // check for any logged-in users if($this->CanEditType == 'LoggedInUsers' && $member) return true; @@ -149,6 +180,7 @@ class SiteConfig extends DataObject implements PermissionProvider { if($member && is_numeric($member)) $member = DataObject::get_by_id('Member', $member); if($this->CanEditType == 'OnlyTheseUsers' && $member && $member->inGroups($this->EditorGroups())) return true; + return false; } @@ -162,4 +194,26 @@ class SiteConfig extends DataObject implements PermissionProvider { ) ); } -} \ No newline at end of file + + /** + * Can a user create pages in the root of this site? + * + * @param mixed $member + * @return boolean + */ + public function canCreateTopLevel($member = null) { + if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) { + $member = Member::currentUserID(); + } + + // check for any logged-in users + if($this->CanCreateTopLevelType == 'LoggedInUsers' && $member) return true; + + // check for specific groups + if($member && is_numeric($member)) $member = DataObject::get_by_id('Member', $member); + if($this->CanCreateTopLevelType == 'OnlyTheseUsers' && $member && $member->inGroups($this->CreateTopLevelGroups())) return true; + + + return false; + } +} diff --git a/core/model/SiteTree.php b/core/model/SiteTree.php index f7a42f8cd..32dff5a2f 100755 --- a/core/model/SiteTree.php +++ b/core/model/SiteTree.php @@ -637,6 +637,9 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid * * @uses DataObjectDecorator->can() * + * If a page is set to inherit, but has no parent, it inherits from + * {@link SiteConfig} + * * @param string $perm The permission to be checked, such as 'View'. * @param Member $member The member whose permissions need checking. * Defaults to the currently logged in user. diff --git a/css/TreeDropdownField.css b/css/TreeDropdownField.css index 5ebeaf164..026d1e4c3 100644 --- a/css/TreeDropdownField.css +++ b/css/TreeDropdownField.css @@ -16,6 +16,7 @@ div.TreeDropdownField span.items { background-color: #fff; margin:0; font-size: 12px; + overflow:hidden; } div.TreeDropdownField div.tree_holder { diff --git a/security/Permission.php b/security/Permission.php index d53c87fbb..a09ece1c4 100755 --- a/security/Permission.php +++ b/security/Permission.php @@ -413,22 +413,10 @@ class Permission extends DataObject { * permission. */ public static function get_members_by_permission($code) { + $toplevelGroups = self::get_groups_by_permission($code); + if (!$toplevelGroups) return false; + $groupIDs = array(); - - $SQL_codeList = (is_array($code)) ? implode("','", Convert::raw2sql($code)) : Convert::raw2sql($code); - - $SQL_filter = "\"Permission\".\"Code\" IN ('" . $SQL_codeList . "') " . - "AND \"Permission\".\"Type\" = " . self::GRANT_PERMISSION; - - $toplevelGroups = DataObject::get( - 'Group', - $SQL_filter, // filter - null, // limit - "LEFT JOIN \"Permission\" ON \"Group\".\"ID\" = \"Permission\".\"GroupID\"" - ); - if(!$toplevelGroups) - return false; - foreach($toplevelGroups as $group) { $familyIDs = $group->collateFamilyIDs(); if(is_array($familyIDs)) { @@ -438,7 +426,7 @@ class Permission extends DataObject { if(!count($groupIDs)) return false; - + $members = DataObject::get( Object::getCustomClass('Member'), $_filter = "\"Group\".\"ID\" IN (" . implode(",",$groupIDs) . ")", @@ -446,6 +434,7 @@ class Permission extends DataObject { $_join = "LEFT JOIN \"Group_Members\" ON \"Member\".\"ID\" = \"Group_Members\".\"MemberID\" " . "LEFT JOIN \"Group\" ON \"Group_Members\".\"GroupID\" = \"Group\".\"ID\" " ); + return $members; } @@ -460,12 +449,14 @@ class Permission extends DataObject { $SQLa_codes = Convert::raw2sql($codes); $SQL_codes = join("','", $SQLa_codes); - return DataObject::get( - 'Group', - "\"Permission\".\"Code\" IN ('$SQL_codes')", + // Via Roles are groups that have the permission via a role + return DataObject::get('Group', + "PermissionRoleCode.`Code` IN ('$SQL_codes') OR Permission.`Code` IN ('$SQL_codes')", "", - "LEFT JOIN \"Permission\" ON \"Group\".\"ID\" = \"Permission\".\"GroupID\"" - ); + "LEFT JOIN Permission ON Permission.GroupID = `Group`.ID + LEFT JOIN Group_Roles ON Group_Roles.GroupID = `Group`.ID + LEFT JOIN PermissionRole ON Group_Roles.PermissionRoleID = PermissionRole.ID + LEFT JOIN PermissionRoleCode ON PermissionRoleCode.RoleID = PermissionRole.ID"); } diff --git a/security/Security.php b/security/Security.php index e1a94a52e..87ad5b0e6 100644 --- a/security/Security.php +++ b/security/Security.php @@ -150,7 +150,7 @@ class Security extends Controller { if(Director::is_ajax()) { $response = ($controller) ? $controller->getResponse() : new SS_HTTPResponse(); $response->setStatusCode(403); - $response->setBody('NOTLOGGEDIN:'); + if(!Member::currentUser()) $response->setBody('NOTLOGGEDIN:'); return $response; } else { // Prepare the messageSet provided diff --git a/tests/SiteTreePermissionsTest.php b/tests/SiteTreePermissionsTest.php index 713a26f1c..5fee6a154 100755 --- a/tests/SiteTreePermissionsTest.php +++ b/tests/SiteTreePermissionsTest.php @@ -273,6 +273,57 @@ class SiteTreePermissionsTest extends FunctionalTest { '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' ); } + + function testInheritCanViewFromSiteConfig() { + $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->ViewerGroups()->write(); + $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'); + } + + function testInheritCanEditFromSiteConfig() { + $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->EditorGroups()->write(); + $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'); + } function testInheritCanViewFromSiteConfig() { $page = $this->objFromFixture('Page', 'inheritWithNoParent');