Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH Add "only these users" option to siteconfig access settings #146

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 93 additions & 11 deletions code/SiteConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use SilverStripe\Security\Security;
use SilverStripe\View\TemplateGlobalProvider;
use SilverStripe\CMS\Controllers\CMSMain;
use SilverStripe\Security\InheritedPermissions;

/**
* SiteConfig
Expand All @@ -40,15 +41,18 @@ class SiteConfig extends DataObject implements PermissionProvider, TemplateGloba
private static $db = [
"Title" => "Varchar(255)",
"Tagline" => "Varchar(255)",
"CanViewType" => "Enum('Anyone, LoggedInUsers, OnlyTheseUsers', 'Anyone')",
"CanEditType" => "Enum('LoggedInUsers, OnlyTheseUsers', 'LoggedInUsers')",
"CanCreateTopLevelType" => "Enum('LoggedInUsers, OnlyTheseUsers', 'LoggedInUsers')",
"CanViewType" => "Enum('Anyone, LoggedInUsers, OnlyTheseUsers, OnlyTheseMembers', 'Anyone')",
"CanEditType" => "Enum('LoggedInUsers, OnlyTheseUsers, OnlyTheseMembers', 'LoggedInUsers')",
"CanCreateTopLevelType" => "Enum('LoggedInUsers, OnlyTheseUsers, OnlyTheseMembers', 'LoggedInUsers')",
];

private static $many_many = [
"ViewerGroups" => Group::class,
"EditorGroups" => Group::class,
"CreateTopLevelGroups" => Group::class,
"ViewerMembers" => Member::class,
"EditorMembers" => Member::class,
"CreateTopLevelMembers" => Member::class,
];

private static $defaults = [
Expand Down Expand Up @@ -100,6 +104,7 @@ public function getCMSFields()
$groupsMap = $mapFn(Group::get());
$viewAllGroupsMap = $mapFn(Permission::get_groups_by_permission(['SITETREE_VIEW_ALL', 'ADMIN']));
$editAllGroupsMap = $mapFn(Permission::get_groups_by_permission(['SITETREE_EDIT_ALL', 'ADMIN']));
$membersMap = Member::get()->map('ID', 'Name');

$fields = FieldList::create(
TabSet::create(
Expand Down Expand Up @@ -127,6 +132,11 @@ public function getCMSFields()
'data-placeholder',
_t('SilverStripe\\CMS\\Model\\SiteTree.GroupPlaceholder', 'Click to select group')
),
$viewerMembersField = ListboxField::create(
"ViewerMembers",
_t(self::class . '.VIEWERMEMBERS', "Viewer Users"),
$membersMap,
),
$editorsOptionsField = OptionsetField::create(
"CanEditType",
_t(self::class . '.EDITHEADER', "Who can edit pages on this site?")
Expand All @@ -140,19 +150,29 @@ public function getCMSFields()
'data-placeholder',
_t('SilverStripe\\CMS\\Model\\SiteTree.GroupPlaceholder', 'Click to select group')
),
$editorMembersField = ListboxField::create(
"EditorMembers",
_t(self::class . '.EDITORMEMBERS', "Editor Users"),
$membersMap,
),
$topLevelCreatorsOptionsField = OptionsetField::create(
"CanCreateTopLevelType",
_t(self::class . '.TOPLEVELCREATE', "Who can create pages in the root of the site?")
),
$topLevelCreatorsGroupsField = ListboxField::create(
"CreateTopLevelGroups",
_t(self::class . '.TOPLEVELCREATORGROUPS', "Top level creators")
_t(self::class . '.TOPLEVELCREATORGROUPS2', "Top level creator groups")
sabina-talipova marked this conversation as resolved.
Show resolved Hide resolved
)
->setSource($groupsMap)
->setAttribute(
'data-placeholder',
_t('SilverStripe\\CMS\\Model\\SiteTree.GroupPlaceholder', 'Click to select group')
)
),
$topLevelCreatorsMembersField = ListboxField::create(
"CreateTopLevelMembers",
_t(self::class . '.TOPLEVELCREATORUSERS', "Top level creator users"),
$membersMap,
)
)
),
HiddenField::create('ID')
Expand All @@ -168,6 +188,10 @@ public function getCMSFields()
'SilverStripe\\CMS\\Model\\SiteTree.ACCESSONLYTHESE',
"Only these groups (choose from list)"
);
$viewersOptionsSource[InheritedPermissions::ONLY_THESE_MEMBERS] = _t(
self::class . '.ACCESSONLYTHESEMEMBERS',
"Only these users (choose from list)"
);
sabina-talipova marked this conversation as resolved.
Show resolved Hide resolved
$viewersOptionsField->setSource($viewersOptionsSource);

if ($viewAllGroupsMap) {
Expand Down Expand Up @@ -195,19 +219,53 @@ public function getCMSFields()
'SilverStripe\\CMS\\Model\\SiteTree.EDITONLYTHESE',
"Only these groups (choose from list)"
);
$editorsOptionsSource[InheritedPermissions::ONLY_THESE_MEMBERS] = _t(
self::class . '.EDITONLYTHESEMEMBERS',
"Only these users (choose from list)"
);
$editorsOptionsField->setSource($editorsOptionsSource);

$topLevelCreatorsOptionsField->setSource($editorsOptionsSource);

if (!Permission::check('EDIT_SITECONFIG')) {
$fields->makeFieldReadonly($taglineField);
$fields->makeFieldReadonly($titleField);
// Hide and remove appropriate viewer fields
$fields->makeFieldReadonly($viewersOptionsField);
$fields->makeFieldReadonly($viewerGroupsField);
if ($this->CanViewType === InheritedPermissions::ONLY_THESE_USERS) {
$fields->makeFieldReadonly($viewerGroupsField);
$fields->removeByName('ViewerMembers');
} elseif ($this->CanViewType === InheritedPermissions::ONLY_THESE_MEMBERS) {
$fields->makeFieldReadonly($viewerMembersField);
$fields->removeByName('ViewerGroups');
} else {
$fields->removeByName('ViewerGroups');
$fields->removeByName('ViewerMembers');
}
// Hide and remove appropriate editor fields
$fields->makeFieldReadonly($editorsOptionsField);
$fields->makeFieldReadonly($editorGroupsField);
if ($this->CanEditType === InheritedPermissions::ONLY_THESE_USERS) {
$fields->makeFieldReadonly($editorGroupsField);
$fields->removeByName('EditorMembers');
} elseif ($this->CanEditType === InheritedPermissions::ONLY_THESE_MEMBERS) {
$fields->makeFieldReadonly($editorMembersField);
$fields->removeByName('EditorGroups');
} else {
$fields->removeByName('EditorGroups');
$fields->removeByName('EditorMembers');
}
// Hide and remove appropriate top-level creator fields
$fields->makeFieldReadonly($topLevelCreatorsOptionsField);
$fields->makeFieldReadonly($topLevelCreatorsGroupsField);
$fields->makeFieldReadonly($taglineField);
$fields->makeFieldReadonly($titleField);
if ($this->CanCreateTopLevelType === InheritedPermissions::ONLY_THESE_USERS) {
$fields->makeFieldReadonly($topLevelCreatorsGroupsField);
$fields->removeByName('CreateTopLevelMembers');
} elseif ($this->CanCreateTopLevelType === InheritedPermissions::ONLY_THESE_MEMBERS) {
$fields->makeFieldReadonly($topLevelCreatorsMembersField);
$fields->removeByName('CreateTopLevelGroups');
} else {
$fields->removeByName('CreateTopLevelGroups');
$fields->removeByName('CreateTopLevelMembers');
}
}

if (file_exists(BASE_PATH . '/install.php')) {
Expand Down Expand Up @@ -370,6 +428,14 @@ public function canViewPages($member = null)
return true;
}

// check for specific users
if ($this->CanViewType === InheritedPermissions::ONLY_THESE_MEMBERS
&& $member
&& $this->ViewerMembers()->filter('ID', $member->ID)->count() > 0
) {
return true;
}

return false;
}

Expand Down Expand Up @@ -403,11 +469,19 @@ public function canEditPages($member = null)
return true;
}

// check for specific groups
// check for specific groups
if ($this->CanEditType === 'OnlyTheseUsers' && $member && $member->inGroups($this->EditorGroups())) {
return true;
}

// check for specific users
if ($this->CanEditType === InheritedPermissions::ONLY_THESE_MEMBERS
&& $member
&& $this->EditorMembers()->filter('ID', $member->ID)->count() > 0
) {
return true;
}

return false;
}

Expand Down Expand Up @@ -482,6 +556,14 @@ public function canCreateTopLevel($member = null)
return true;
}

// check for specific users
if ($this->CanCreateTopLevelType === InheritedPermissions::ONLY_THESE_MEMBERS
&& $member
&& $this->CreateTopLevelMembers()->filter('ID', $member->ID)->count() > 0
) {
return true;
}

return false;
}

Expand Down
111 changes: 110 additions & 1 deletion tests/behat/features/manage-page-permissions.feature
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ Feature: Manage global page permissions
Given a "page" "Home" with "Content"="<p>Welcome</p>"
And a "group" "AUTHOR" has permissions "Access to 'Pages' section"
And a "group" "SECURITY" has permissions "Access to 'Security' section"
# Have to supply an email address like this for "I am logged in as a member of <name> group" to find this user
And a "member" "AUTHOR" belonging to "AUTHOR" with "Email"="[email protected]"
And a "member" "SECURITY" belonging to "SECURITY" with "Email"="[email protected]"
And I am logged in with "ADMIN" permissions
And I go to "admin/settings"
And I click the "Access" CMS tab
Expand Down Expand Up @@ -43,6 +46,28 @@ Feature: Manage global page permissions
And I go to the homepage
Then I should see "Welcome"

Scenario: I can limit global view permissions to certain members
Given I select "Only these users (choose from list)" from "Who can view pages on this site?" input group
And I select "AUTHOR" from "Viewer Users" with javascript
And I press the "Save" button
When I am not logged in
And I go to the homepage
Then I should see a log-in form
When I am logged in as a member of "SECURITY" group
And I go to the homepage
Then I will see a "warning" log-in message
When I am not logged in
And I am logged in as a member of "AUTHOR" group
And I go to the homepage
Then I should see "Welcome"

Scenario: I can open global edit permissions to everyone
Given I select "Anyone who can log-in to the CMS" from "Who can edit pages on this site?" input group
And I press the "Save" button
Then pages should be editable by "AUTHOR"
# "anyone" doesn't override actual permissions
And pages should not be editable by "SECURITY"

Scenario: I can limit global edit permissions to logged-in users
Given I am not logged in
And I am logged in as a member of "AUTHOR" group
Expand All @@ -55,11 +80,95 @@ Feature: Manage global page permissions
And I press the "Save" button
Then pages should be editable by "AUTHOR"
And pages should be editable by "ADMIN"
And pages should not be editable by "SECURITY"

Scenario: I can limit global edit permissions to certain groups
Given I select "Only these groups (choose from list)" from "Who can edit pages on this site?" input group
When I select "Only these groups (choose from list)" from "Who can edit pages on this site?" input group
And I select "ADMIN group" from "Editor Groups" with javascript
And I press the "Save" button
Then pages should not be editable by "AUTHOR"
And pages should not be editable by "SECURITY"
But pages should be editable by "ADMIN"

Scenario: I can limit global edit permissions to certain members
Given I select "Only these users (choose from list)" from "Who can edit pages on this site?" input group
And I select "ADMIN" from "Editor Users" with javascript
And I press the "Save" button
Then pages should not be editable by "AUTHOR"
And pages should not be editable by "SECURITY"
But pages should be editable by "ADMIN"

Scenario: I should only see member/group fields when I am limiting access to members/groups (View)
Given I select "Anyone" from "Who can view pages on this site?" input group
# Need to wait a beat after each selection so the animation has time to finish
And I wait for 1 second
Then I should not see "Viewer Groups"
And I should not see "Viewer Users"
When I select "Logged-in users" from "Who can view pages on this site?" input group
And I wait for 1 second
Then I should not see "Viewer Groups"
And I should not see "Viewer Users"
When I select "Only these groups (choose from list)" from "Who can view pages on this site?" input group
And I wait for 1 second
Then I should see "Viewer Groups"
And I should not see "Viewer Users"
When I select "Only these users (choose from list)" from "Who can view pages on this site?" input group
And I wait for 1 second
Then I should not see "Viewer Groups"
And I should see "Viewer Users"
When I select "Logged-in users" from "Who can view pages on this site?" input group
And I wait for 1 second
Then I should not see "Viewer Groups"
And I should not see "Viewer Users"
# Avoids having a toast which crashes the test
When I press the "Save" button

Scenario: I should only see member/group fields when I am limiting access to members/groups (Edit)
Given I select "Anyone who can log-in to the CMS" from "Who can edit pages on this site?" input group
# Need to wait a beat after each selection so the animation has time to finish
And I wait for 1 second
Then I should not see "Editor Groups"
And I should not see "Editor Users"
When I select "Logged-in users" from "Who can edit pages on this site?" input group
And I wait for 1 second
Then I should not see "Editor Groups"
And I should not see "Editor Users"
When I select "Only these groups (choose from list)" from "Who can edit pages on this site?" input group
And I wait for 1 second
Then I should see "Editor Groups"
And I should not see "Editor Users"
When I select "Only these users (choose from list)" from "Who can edit pages on this site?" input group
And I wait for 1 second
Then I should not see "Editor Groups"
And I should see "Editor Users"
When I select "Anyone who can log-in to the CMS" from "Who can edit pages on this site?" input group
And I wait for 1 second
Then I should not see "Editor Groups"
And I should not see "Editor Users"
# Avoids having a toast which crashes the test
When I press the "Save" button

Scenario: I should only see member/group fields when I am limiting access to members/groups (Create)
Given I select "Anyone who can log-in to the CMS" from "Who can create pages in the root of the site?" input group
# Need to wait a beat after each selection so the animation has time to finish
And I wait for 1 second
Then I should not see "Top level creator groups"
And I should not see "Top level creator users"
When I select "Logged-in users" from "Who can create pages in the root of the site?" input group
And I wait for 1 second
Then I should not see "Top level creator groups"
And I should not see "Top level creator users"
When I select "Only these groups (choose from list)" from "Who can create pages in the root of the site?" input group
And I wait for 1 second
Then I should see "Top level creator groups"
And I should not see "Top level creator users"
When I select "Only these users (choose from list)" from "Who can create pages in the root of the site?" input group
And I wait for 1 second
Then I should not see "Top level creator groups"
And I should see "Top level creator users"
When I select "Anyone who can log-in to the CMS" from "Who can create pages in the root of the site?" input group
And I wait for 1 second
Then I should not see "Top level creator groups"
And I should not see "Top level creator users"
# Avoids having a toast which crashes the test
When I press the "Save" button