mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-09-30 05:09:06 +02:00
Merge pull request #7518 from open-sausages/pulls/4.0/its-time-to-cut-the-cord
Feature disable current user from modifying their own groups
This commit is contained in:
commit
d47bddb376
@ -1,3 +1,10 @@
|
|||||||
|
# Run framework behat tests with this command (installed with silverstripe/installer)
|
||||||
|
# Note that framework behat tests require CMS module
|
||||||
|
# ========================================================================= #
|
||||||
|
# vendor/bin/selenium-server-standalone -Dwebdriver.firefox.bin="/Applications/Firefox31.app/Contents/MacOS/firefox-bin"
|
||||||
|
# vendor/bin/serve --bootstrap-file vendor/silverstripe/framework/tests/behat/serve-bootstrap.php
|
||||||
|
# vendor/bin/behat @framework
|
||||||
|
# ========================================================================= #
|
||||||
default:
|
default:
|
||||||
suites:
|
suites:
|
||||||
framework:
|
framework:
|
||||||
|
@ -85,6 +85,8 @@ en:
|
|||||||
Print: Print
|
Print: Print
|
||||||
RelationSearch: 'Relation search'
|
RelationSearch: 'Relation search'
|
||||||
ResetFilter: Reset
|
ResetFilter: Reset
|
||||||
|
SilverStripe\Forms\GridField\GridFieldGroupDeleteAction:
|
||||||
|
UnlinkSelfFailure: 'Cannot remove yourself from this group, you will lose admin rights'
|
||||||
SilverStripe\Forms\GridField\GridFieldDeleteAction:
|
SilverStripe\Forms\GridField\GridFieldDeleteAction:
|
||||||
DELETE_DESCRIPTION: Delete
|
DELETE_DESCRIPTION: Delete
|
||||||
Delete: Delete
|
Delete: Delete
|
||||||
@ -247,6 +249,7 @@ en:
|
|||||||
other: '{count} Members'
|
other: '{count} Members'
|
||||||
REMEMBERME: 'Remember me next time? (for {count} days on this device)'
|
REMEMBERME: 'Remember me next time? (for {count} days on this device)'
|
||||||
SINGULARNAME: Member
|
SINGULARNAME: Member
|
||||||
|
VALIDATIONADMINLOSTACCESS: 'Cannot remove all admin groups from your profile'
|
||||||
SUBJECTPASSWORDCHANGED: 'Your password has been changed'
|
SUBJECTPASSWORDCHANGED: 'Your password has been changed'
|
||||||
SUBJECTPASSWORDRESET: 'Your password reset link'
|
SUBJECTPASSWORDRESET: 'Your password reset link'
|
||||||
SURNAME: Surname
|
SURNAME: Surname
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace SilverStripe\Dev;
|
namespace SilverStripe\Dev;
|
||||||
|
|
||||||
use SilverStripe\Control\Director;
|
use SilverStripe\Control\Director;
|
||||||
|
use SilverStripe\Core\Environment;
|
||||||
use SilverStripe\Core\Manifest\ClassLoader;
|
use SilverStripe\Core\Manifest\ClassLoader;
|
||||||
use SilverStripe\Core\Manifest\Module;
|
use SilverStripe\Core\Manifest\Module;
|
||||||
use SilverStripe\Core\Manifest\ModuleLoader;
|
use SilverStripe\Core\Manifest\ModuleLoader;
|
||||||
@ -148,7 +149,7 @@ class Deprecation
|
|||||||
if (isset(self::$enabled)) {
|
if (isset(self::$enabled)) {
|
||||||
return self::$enabled;
|
return self::$enabled;
|
||||||
}
|
}
|
||||||
return getenv('SS_DEPRECATION_ENABLED') ?: true;
|
return Environment::getEnv('SS_DEPRECATION_ENABLED') ?: true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -119,6 +119,7 @@ class GridFieldDeleteAction implements GridField_ColumnProvider, GridField_Actio
|
|||||||
if (!$record->canEdit()) {
|
if (!$record->canEdit()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
$title = _t(__CLASS__.'.UnlinkRelation', "Unlink");
|
||||||
|
|
||||||
$field = GridField_FormAction::create(
|
$field = GridField_FormAction::create(
|
||||||
$gridField,
|
$gridField,
|
||||||
@ -128,7 +129,8 @@ class GridFieldDeleteAction implements GridField_ColumnProvider, GridField_Actio
|
|||||||
array('RecordID' => $record->ID)
|
array('RecordID' => $record->ID)
|
||||||
)
|
)
|
||||||
->addExtraClass('btn btn--no-text btn--icon-md font-icon-link-broken grid-field__icon-action gridfield-button-unlink')
|
->addExtraClass('btn btn--no-text btn--icon-md font-icon-link-broken grid-field__icon-action gridfield-button-unlink')
|
||||||
->setAttribute('title', _t('SilverStripe\\Forms\\GridField\\GridFieldDeleteAction.UnlinkRelation', "Unlink"));
|
->setAttribute('title', $title)
|
||||||
|
->setAttribute('aria-label', $title);
|
||||||
} else {
|
} else {
|
||||||
if (!$record->canDelete()) {
|
if (!$record->canDelete()) {
|
||||||
return null;
|
return null;
|
||||||
@ -142,8 +144,8 @@ class GridFieldDeleteAction implements GridField_ColumnProvider, GridField_Actio
|
|||||||
array('RecordID' => $record->ID)
|
array('RecordID' => $record->ID)
|
||||||
)
|
)
|
||||||
->addExtraClass('gridfield-button-delete btn--icon-md font-icon-trash-bin btn--no-text grid-field__icon-action')
|
->addExtraClass('gridfield-button-delete btn--icon-md font-icon-trash-bin btn--no-text grid-field__icon-action')
|
||||||
->setAttribute('title', _t('SilverStripe\\Forms\\GridField\\GridFieldDeleteAction.Delete', "Delete"))
|
->setAttribute('title', _t(__CLASS__.'.Delete', "Delete"))
|
||||||
->setDescription(_t('SilverStripe\\Forms\\GridField\\GridFieldDeleteAction.DELETE_DESCRIPTION', 'Delete'));
|
->setDescription(_t(__CLASS__.'.DELETE_DESCRIPTION', 'Delete'));
|
||||||
}
|
}
|
||||||
return $field->Field();
|
return $field->Field();
|
||||||
}
|
}
|
||||||
@ -153,8 +155,8 @@ class GridFieldDeleteAction implements GridField_ColumnProvider, GridField_Actio
|
|||||||
*
|
*
|
||||||
* @param GridField $gridField
|
* @param GridField $gridField
|
||||||
* @param string $actionName
|
* @param string $actionName
|
||||||
* @param mixed $arguments
|
* @param array $arguments
|
||||||
* @param array $data - form data
|
* @param array $data Form data
|
||||||
* @throws ValidationException
|
* @throws ValidationException
|
||||||
*/
|
*/
|
||||||
public function handleAction(GridField $gridField, $actionName, $arguments, $data)
|
public function handleAction(GridField $gridField, $actionName, $arguments, $data)
|
||||||
@ -169,7 +171,7 @@ class GridFieldDeleteAction implements GridField_ColumnProvider, GridField_Actio
|
|||||||
if ($actionName == 'deleterecord') {
|
if ($actionName == 'deleterecord') {
|
||||||
if (!$item->canDelete()) {
|
if (!$item->canDelete()) {
|
||||||
throw new ValidationException(
|
throw new ValidationException(
|
||||||
_t('SilverStripe\\Forms\\GridField\\GridFieldDeleteAction.DeletePermissionsFailure', "No delete permissions")
|
_t(__CLASS__.'.DeletePermissionsFailure', "No delete permissions")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +179,7 @@ class GridFieldDeleteAction implements GridField_ColumnProvider, GridField_Actio
|
|||||||
} else {
|
} else {
|
||||||
if (!$item->canEdit()) {
|
if (!$item->canEdit()) {
|
||||||
throw new ValidationException(
|
throw new ValidationException(
|
||||||
_t('SilverStripe\\Forms\\GridField\\GridFieldDeleteAction.EditPermissionsFailure', "No permission to unlink record")
|
_t(__CLASS__.'.EditPermissionsFailure', "No permission to unlink record")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
90
src/Forms/GridField/GridFieldGroupDeleteAction.php
Normal file
90
src/Forms/GridField/GridFieldGroupDeleteAction.php
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\Forms\GridField;
|
||||||
|
|
||||||
|
use SilverStripe\ORM\DataObject;
|
||||||
|
use SilverStripe\ORM\ValidationException;
|
||||||
|
use SilverStripe\Security\Member;
|
||||||
|
use SilverStripe\Security\Permission;
|
||||||
|
use SilverStripe\Security\Security;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a delete action for the gridfield to remove a relationship from group.
|
||||||
|
* This is a special case where it captures whether the current user is the record being removed and
|
||||||
|
* prevents removal from happening.
|
||||||
|
*/
|
||||||
|
class GridFieldGroupDeleteAction extends GridFieldDeleteAction
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $groupID;
|
||||||
|
|
||||||
|
public function __construct($groupID)
|
||||||
|
{
|
||||||
|
$this->groupID = $groupID;
|
||||||
|
parent::__construct(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param GridField $gridField
|
||||||
|
* @param DataObject $record
|
||||||
|
* @param string $columnName
|
||||||
|
* @return string the HTML for the column
|
||||||
|
*/
|
||||||
|
public function getColumnContent($gridField, $record, $columnName)
|
||||||
|
{
|
||||||
|
if ($this->canUnlink($record)) {
|
||||||
|
return parent::getColumnContent($gridField, $record, $columnName);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the actions and apply any changes to the GridField
|
||||||
|
*
|
||||||
|
* @param GridField $gridField
|
||||||
|
* @param string $actionName
|
||||||
|
* @param array $arguments
|
||||||
|
* @param array $data Form data
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
public function handleAction(GridField $gridField, $actionName, $arguments, $data)
|
||||||
|
{
|
||||||
|
$record = $gridField->getList()->find('ID', $arguments['RecordID']);
|
||||||
|
|
||||||
|
if (!$record || !$actionName == 'unlinkrelation' || $this->canUnlink($record)) {
|
||||||
|
parent::handleAction($gridField, $actionName, $arguments, $data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ValidationException(
|
||||||
|
_t(__CLASS__ . '.UnlinkSelfFailure', 'Cannot remove yourself from this group, you will lose admin rights')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $record - the record of the User to unlink with
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function canUnlink($record)
|
||||||
|
{
|
||||||
|
$currentUser = Security::getCurrentUser();
|
||||||
|
if ($currentUser
|
||||||
|
&& $record instanceof Member
|
||||||
|
&& (int)$record->ID === (int)$currentUser->ID
|
||||||
|
&& Permission::checkMember($record, 'ADMIN')
|
||||||
|
) {
|
||||||
|
$adminGroups = array_intersect(
|
||||||
|
$record->Groups()->column(),
|
||||||
|
Permission::get_groups_by_permission('ADMIN')->column()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (count($adminGroups) === 1 && array_search($this->groupID, $adminGroups) !== false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -11,8 +11,11 @@ use SilverStripe\Forms\GridField\GridField;
|
|||||||
use SilverStripe\Forms\GridField\GridFieldAddExistingAutocompleter;
|
use SilverStripe\Forms\GridField\GridFieldAddExistingAutocompleter;
|
||||||
use SilverStripe\Forms\GridField\GridFieldButtonRow;
|
use SilverStripe\Forms\GridField\GridFieldButtonRow;
|
||||||
use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor;
|
use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor;
|
||||||
|
use SilverStripe\Forms\GridField\GridFieldDeleteAction;
|
||||||
use SilverStripe\Forms\GridField\GridFieldDetailForm;
|
use SilverStripe\Forms\GridField\GridFieldDetailForm;
|
||||||
use SilverStripe\Forms\GridField\GridFieldExportButton;
|
use SilverStripe\Forms\GridField\GridFieldExportButton;
|
||||||
|
use SilverStripe\Forms\GridField\GridFieldGroupDeleteAction;
|
||||||
|
use SilverStripe\Forms\GridField\GridFieldPageCount;
|
||||||
use SilverStripe\Forms\GridField\GridFieldPrintButton;
|
use SilverStripe\Forms\GridField\GridFieldPrintButton;
|
||||||
use SilverStripe\Forms\HiddenField;
|
use SilverStripe\Forms\HiddenField;
|
||||||
use SilverStripe\Forms\HTMLEditor\HTMLEditorConfig;
|
use SilverStripe\Forms\HTMLEditor\HTMLEditorConfig;
|
||||||
@ -150,6 +153,9 @@ class Group extends DataObject
|
|||||||
$config->addComponent(new GridFieldButtonRow('after'));
|
$config->addComponent(new GridFieldButtonRow('after'));
|
||||||
$config->addComponents(new GridFieldExportButton('buttons-after-left'));
|
$config->addComponents(new GridFieldExportButton('buttons-after-left'));
|
||||||
$config->addComponents(new GridFieldPrintButton('buttons-after-left'));
|
$config->addComponents(new GridFieldPrintButton('buttons-after-left'));
|
||||||
|
$config->removeComponentsByType(GridFieldDeleteAction::class);
|
||||||
|
$config->addComponent(new GridFieldGroupDeleteAction($this->ID), GridFieldPageCount::class);
|
||||||
|
|
||||||
/** @var GridFieldAddExistingAutocompleter $autocompleter */
|
/** @var GridFieldAddExistingAutocompleter $autocompleter */
|
||||||
$autocompleter = $config->getComponentByType(GridFieldAddExistingAutocompleter::class);
|
$autocompleter = $config->getComponentByType(GridFieldAddExistingAutocompleter::class);
|
||||||
/** @skipUpgrade */
|
/** @skipUpgrade */
|
||||||
|
@ -101,8 +101,8 @@ class Member_Validator extends RequiredFields
|
|||||||
|
|
||||||
// Only validate identifier field if it's actually set. This could be the case if
|
// Only validate identifier field if it's actually set. This could be the case if
|
||||||
// somebody removes `Email` from the list of required fields.
|
// somebody removes `Email` from the list of required fields.
|
||||||
|
$id = isset($data['ID']) ? (int)$data['ID'] : 0;
|
||||||
if (isset($data[$identifierField])) {
|
if (isset($data[$identifierField])) {
|
||||||
$id = isset($data['ID']) ? (int)$data['ID'] : 0;
|
|
||||||
if (!$id && ($ctrl = $this->form->getController())) {
|
if (!$id && ($ctrl = $this->form->getController())) {
|
||||||
// get the record when within GridField (Member editing page in CMS)
|
// get the record when within GridField (Member editing page in CMS)
|
||||||
if ($ctrl instanceof GridFieldDetailForm_ItemRequest && $record = $ctrl->getRecord()) {
|
if ($ctrl instanceof GridFieldDetailForm_ItemRequest && $record = $ctrl->getRecord()) {
|
||||||
@ -137,6 +137,38 @@ class Member_Validator extends RequiredFields
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$currentUser = Security::getCurrentUser();
|
||||||
|
if ($currentUser
|
||||||
|
&& $id
|
||||||
|
&& $id === (int)$currentUser->ID
|
||||||
|
&& Permission::checkMember($currentUser, 'ADMIN')
|
||||||
|
) {
|
||||||
|
$stillAdmin = true;
|
||||||
|
|
||||||
|
if (!isset($data['DirectGroups'])) {
|
||||||
|
$stillAdmin = false;
|
||||||
|
} else {
|
||||||
|
$adminGroups = array_intersect(
|
||||||
|
$data['DirectGroups'],
|
||||||
|
Permission::get_groups_by_permission('ADMIN')->column()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (count($adminGroups) === 0) {
|
||||||
|
$stillAdmin = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$stillAdmin) {
|
||||||
|
$this->validationError(
|
||||||
|
'DirectGroups',
|
||||||
|
_t(
|
||||||
|
'SilverStripe\\Security\\Member.VALIDATIONADMINLOSTACCESS',
|
||||||
|
'Cannot remove all admin groups from your profile'
|
||||||
|
),
|
||||||
|
'required'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Execute the validators on the extensions
|
// Execute the validators on the extensions
|
||||||
$results = $this->extend('updatePHP', $data, $this->form);
|
$results = $this->extend('updatePHP', $data, $this->form);
|
||||||
|
@ -5,18 +5,18 @@ Feature: Lost Password
|
|||||||
Using my email
|
Using my email
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given a "member" "Admin" with "Email"="admin@test.com"
|
Given a "member" "Admin" with "Email"="admin@example.org"
|
||||||
|
|
||||||
Scenario: I can request a password reset by email
|
Scenario: I can request a password reset by email
|
||||||
Given I go to "Security/login"
|
Given I go to "Security/login"
|
||||||
When I follow "I've lost my password"
|
When I follow "I've lost my password"
|
||||||
And I fill in "admin@test.com" for "Email"
|
And I fill in "admin@example.org" for "Email"
|
||||||
And I press the "Send me the password reset link" button
|
And I press the "Send me the password reset link" button
|
||||||
Then I should see "A reset link has been sent to 'admin@test.com'"
|
Then I should see "A reset link has been sent to 'admin@example.org'"
|
||||||
And there should be an email to "admin@test.com" titled "Your password reset link"
|
And there should be an email to "admin@example.org" titled "Your password reset link"
|
||||||
When I click on the "password reset link" link in the email to "admin@test.com"
|
When I click on the "password reset link" link in the email to "admin@example.org"
|
||||||
Then I should see "Please enter a new password"
|
Then I should see "Please enter a new password"
|
||||||
When I fill in "newpassword" for "New Password"
|
When I fill in "newpassword" for "New Password"
|
||||||
And I fill in "newpassword" for "Confirm New Password"
|
And I fill in "newpassword" for "Confirm New Password"
|
||||||
And I press the "Change Password" button
|
And I press the "Change Password" button
|
||||||
Then the password for "admin@test.com" should be "newpassword"
|
Then the password for "admin@example.org" should be "newpassword"
|
||||||
|
@ -5,23 +5,41 @@ Feature: Manage users
|
|||||||
So that I can control access to the CMS
|
So that I can control access to the CMS
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given a "member" "ADMIN" belonging to "ADMIN Group" with "Email"="admin@test.com"
|
Given a "member" "ADMIN" belonging to "ADMIN group" with "Email"="admin@example.org"
|
||||||
And a "member" "Staff" belonging to "Staff Group" with "Email"="staffmember@test.com"
|
And the "member" "ADMIN" belonging to "ADMIN group2"
|
||||||
|
And a "member" "Staff" belonging to "Staff group" with "Email"="staffmember@example.org"
|
||||||
And the "group" "ADMIN group" has permissions "Full administrative rights"
|
And the "group" "ADMIN group" has permissions "Full administrative rights"
|
||||||
|
And the "group" "ADMIN group2" has permissions "Full administrative rights"
|
||||||
And I am logged in with "ADMIN" permissions
|
And I am logged in with "ADMIN" permissions
|
||||||
And I go to "/admin/security"
|
And I go to "/admin/security"
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: I cannot remove my admin access, but can remove myself from an admin group
|
||||||
|
When I click the "Groups" CMS tab
|
||||||
|
And I click "ADMIN group" in the "#Root_Groups" element
|
||||||
|
And I should see the "Unlink" button in the "Members" gridfield for the "ADMIN" row
|
||||||
|
Then I click "Groups" in the ".breadcrumbs-wrapper" element
|
||||||
|
And I click the "Groups" CMS tab
|
||||||
|
And I click "ADMIN group2" in the "#Root_Groups" element
|
||||||
|
And I should see the "Unlink" button in the "Members" gridfield for the "ADMIN" row
|
||||||
|
Then I click the "Unlink" button in the "Members" gridfield for the "ADMIN" row
|
||||||
|
And I should not see the "Unlink" button in the "Members" gridfield for the "ADMIN" row
|
||||||
|
Then I click "Groups" in the ".breadcrumbs-wrapper" element
|
||||||
|
And I click the "Groups" CMS tab
|
||||||
|
And I click "ADMIN group" in the "#Root_Groups" element
|
||||||
|
And I should not see the "Unlink" button in the "Members" gridfield for the "ADMIN" row
|
||||||
|
|
||||||
Scenario: I can list all users regardless of group
|
Scenario: I can list all users regardless of group
|
||||||
When I click the "Users" CMS tab
|
When I click the "Users" CMS tab
|
||||||
Then I should see "admin@test.com" in the "#Root_Users" element
|
Then I should see "admin@example.org" in the "#Root_Users" element
|
||||||
And I should see "staffmember@test.com" in the "#Root_Users" element
|
And I should see "staffmember@example.org" in the "#Root_Users" element
|
||||||
|
|
||||||
Scenario: I can list all users in a specific group
|
Scenario: I can list all users in a specific group
|
||||||
When I click the "Groups" CMS tab
|
When I click the "Groups" CMS tab
|
||||||
# TODO Please check how performant this is
|
# TODO Please check how performant this is
|
||||||
And I click "ADMIN group" in the "#Root_Groups" element
|
And I click "ADMIN group" in the "#Root_Groups" element
|
||||||
Then I should see "admin@test.com" in the "#Root_Members" element
|
Then I should see "admin@example.org" in the "#Root_Members" element
|
||||||
And I should not see "staffmember@test.com" in the "#Root_Members" element
|
And I should not see "staffmember@example.org" in the "#Root_Members" element
|
||||||
|
|
||||||
Scenario: I can add a user to the system
|
Scenario: I can add a user to the system
|
||||||
When I click the "Users" CMS tab
|
When I click the "Users" CMS tab
|
||||||
@ -29,16 +47,16 @@ Feature: Manage users
|
|||||||
And I fill in the following:
|
And I fill in the following:
|
||||||
| First Name | John |
|
| First Name | John |
|
||||||
| Surname | Doe |
|
| Surname | Doe |
|
||||||
| Email | john.doe@test.com |
|
| Email | john.doe@example.org |
|
||||||
And I press the "Create" button
|
And I press the "Create" button
|
||||||
Then I should see a "Saved member" message
|
Then I should see a "Saved member" message
|
||||||
|
|
||||||
When I go to "admin/security/"
|
When I go to "admin/security/"
|
||||||
Then I should see "john.doe@test.com" in the "#Root_Users" element
|
Then I should see "john.doe@example.org" in the "#Root_Users" element
|
||||||
|
|
||||||
Scenario: I can edit an existing user and add him to an existing group
|
Scenario: I can edit an existing user and add him to an existing group
|
||||||
When I click the "Users" CMS tab
|
When I click the "Users" CMS tab
|
||||||
And I click "staffmember@test.com" in the "#Root_Users" element
|
And I click "staffmember@example.org" in the "#Root_Users" element
|
||||||
And I select "ADMIN group" from "Groups"
|
And I select "ADMIN group" from "Groups"
|
||||||
And I press the "Save" button
|
And I press the "Save" button
|
||||||
Then I should see a "Saved Member" message
|
Then I should see a "Saved Member" message
|
||||||
@ -46,11 +64,11 @@ Feature: Manage users
|
|||||||
When I go to "admin/security"
|
When I go to "admin/security"
|
||||||
And I click the "Groups" CMS tab
|
And I click the "Groups" CMS tab
|
||||||
And I click "ADMIN group" in the "#Root_Groups" element
|
And I click "ADMIN group" in the "#Root_Groups" element
|
||||||
Then I should see "staffmember@test.com"
|
Then I should see "staffmember@example.org"
|
||||||
|
|
||||||
Scenario: I can delete an existing user
|
Scenario: I can delete an existing user
|
||||||
When I click the "Users" CMS tab
|
When I click the "Users" CMS tab
|
||||||
And I click "staffmember@test.com" in the "#Root_Users" element
|
And I click "staffmember@example.org" in the "#Root_Users" element
|
||||||
And I press the "Delete" button, confirming the dialog
|
And I press the "Delete" button, confirming the dialog
|
||||||
Then I should see "admin@test.com"
|
Then I should see "admin@example.org"
|
||||||
And I should not see "staffmember@test.com"
|
And I should not see "staffmember@example.org"
|
||||||
|
@ -1,48 +1,62 @@
|
|||||||
@retry
|
@retry
|
||||||
Feature: Manage my own settings
|
Feature: Manage my own settings
|
||||||
As a CMS user
|
As a CMS user
|
||||||
I want to be able to change personal settings
|
I want to be able to change personal settings
|
||||||
In order to streamline my CMS experience
|
In order to streamline my CMS experience
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given a "member" "Joe" belonging to "Admin Group" with "Email"="joe@test.com" and "Password"="secret"
|
Given a "member" "Joe" belonging to "Admin group" with "Email"="joe@example.org" and "Password"="secret"
|
||||||
And the "group" "Admin Group" has permissions "Full administrative rights"
|
And the "group" "Admin group" has permissions "Full administrative rights"
|
||||||
And I log in with "joe@test.com" and "secret"
|
And the "member" "Joe" belonging to "Admin group2"
|
||||||
And I go to "admin/myprofile"
|
And the "group" "Admin group2" has permissions "Full administrative rights"
|
||||||
|
And I log in with "joe@example.org" and "secret"
|
||||||
|
And I go to "admin/myprofile"
|
||||||
|
|
||||||
Scenario: I can edit my personal details
|
Scenario: I cannot remove all my admin groups
|
||||||
Given I fill in "First Name" with "Jack"
|
When I click the "Admin group" option in the "DirectGroups" listbox
|
||||||
And I fill in "Surname" with "Johnson"
|
And I click the "Admin group2" option in the "DirectGroups" listbox
|
||||||
And I fill in "Email" with "jack@test.com"
|
And I press the "Save" button
|
||||||
When I press the "Save" button
|
Then I should see "Cannot remove all admin groups from your profile" in the "#Form_EditForm" element
|
||||||
Given I go to "admin/myprofile"
|
|
||||||
Then I should not see "Joe"
|
|
||||||
Then I should see "Jack"
|
|
||||||
And I should see "Johnson"
|
|
||||||
|
|
||||||
Scenario: I can't reset the password without the original
|
Scenario: I can remove one of my admin groups
|
||||||
Given I follow "Change Password"
|
When I click the "Admin group" option in the "DirectGroups" listbox
|
||||||
And I fill in "Current Password" with "idontknow"
|
And I press the "Save" button
|
||||||
And I fill in "New Password" with "newsecret"
|
Then I should see a "Saved" notice
|
||||||
And I fill in "Confirm Password" with "newsecret"
|
And I should not see "Cannot remove all admin groups from your profile" in the "#Form_EditForm" element
|
||||||
And I press the "Save" button
|
|
||||||
Then I should see "The current password you have entered is not correct."
|
|
||||||
|
|
||||||
Scenario: I can change my password
|
Scenario: I can edit my personal details
|
||||||
Given I follow "Change Password"
|
Given I fill in "First Name" with "Jack"
|
||||||
And I fill in "Current Password" with "secret"
|
And I fill in "Surname" with "Johnson"
|
||||||
And I fill in "New Password" with "newsecret"
|
And I fill in "Email" with "jack@example.org"
|
||||||
And I fill in "Confirm Password" with "newsecret"
|
When I press the "Save" button
|
||||||
And I press the "Save" button
|
Given I go to "admin/myprofile"
|
||||||
And I am not logged in
|
Then I should not see "Joe"
|
||||||
When I log in with "joe@test.com" and "newsecret"
|
Then I should see "Jack"
|
||||||
And I go to "admin/myprofile"
|
And I should see "Johnson"
|
||||||
Then I should see the CMS
|
|
||||||
|
|
||||||
Scenario: I can change the interface language
|
Scenario: I can't reset the password without the original
|
||||||
And I select "German (Germany)" from "Interface Language"
|
Given I follow "Change Password"
|
||||||
And I press the "Save" button
|
And I fill in "Current Password" with "idontknow"
|
||||||
Then I should see "Sprache"
|
And I fill in "New Password" with "newsecret"
|
||||||
|
And I fill in "Confirm Password" with "newsecret"
|
||||||
|
And I press the "Save" button
|
||||||
|
Then I should see "The current password you have entered is not correct."
|
||||||
|
|
||||||
|
Scenario: I can change my password
|
||||||
|
Given I follow "Change Password"
|
||||||
|
And I fill in "Current Password" with "secret"
|
||||||
|
And I fill in "New Password" with "newsecret"
|
||||||
|
And I fill in "Confirm Password" with "newsecret"
|
||||||
|
And I press the "Save" button
|
||||||
|
And I am not logged in
|
||||||
|
When I log in with "joe@example.org" and "newsecret"
|
||||||
|
And I go to "admin/myprofile"
|
||||||
|
Then I should see the CMS
|
||||||
|
|
||||||
|
Scenario: I can change the interface language
|
||||||
|
And I select "German (Germany)" from "Interface Language"
|
||||||
|
And I press the "Save" button
|
||||||
|
Then I should see "Sprache"
|
||||||
|
|
||||||
# TODO Date/time format - Difficult because its not exposed anywhere in the CMS?
|
# TODO Date/time format - Difficult because its not exposed anywhere in the CMS?
|
||||||
# TODO Group modification as ADMIN user
|
# TODO Group modification as ADMIN user
|
||||||
|
@ -6,7 +6,7 @@ Feature: Manage Security Permissions for Groups
|
|||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given a "group" "test group"
|
Given a "group" "test group"
|
||||||
And a "member" "ADMIN" belonging to "ADMIN Group" with "Email"="admin@test.com"
|
And a "member" "ADMIN" belonging to "ADMIN group" with "Email"="admin@example.org"
|
||||||
And the "group" "ADMIN group" has permissions "Full administrative rights"
|
And the "group" "ADMIN group" has permissions "Full administrative rights"
|
||||||
And I am logged in with "ADMIN" permissions
|
And I am logged in with "ADMIN" permissions
|
||||||
And I go to "/admin/security"
|
And I go to "/admin/security"
|
||||||
|
@ -95,7 +95,7 @@ class CmsFormsContext implements Context
|
|||||||
{
|
{
|
||||||
$element = $this->getHtmlField($locator);
|
$element = $this->getHtmlField($locator);
|
||||||
$actual = $element->getValue();
|
$actual = $element->getValue();
|
||||||
$regex = '/'.preg_quote($html, '/').'/ui';
|
$regex = '/' . preg_quote($html, '/') . '/ui';
|
||||||
$failed = false;
|
$failed = false;
|
||||||
|
|
||||||
if (trim($negative)) {
|
if (trim($negative)) {
|
||||||
@ -230,7 +230,7 @@ JS;
|
|||||||
*/
|
*/
|
||||||
public function iClickOnTheHtmlFieldButton($button)
|
public function iClickOnTheHtmlFieldButton($button)
|
||||||
{
|
{
|
||||||
$xpath = "//*[@aria-label='".$button."']";
|
$xpath = "//*[@aria-label='" . $button . "']";
|
||||||
$session = $this->getSession();
|
$session = $this->getSession();
|
||||||
$element = $session->getPage()->find('xpath', $xpath);
|
$element = $session->getPage()->find('xpath', $xpath);
|
||||||
if (null === $element) {
|
if (null === $element) {
|
||||||
@ -352,4 +352,87 @@ JS;
|
|||||||
// Destroy cookie to detach session
|
// Destroy cookie to detach session
|
||||||
$this->getMainContext()->getSession()->setCookie('PHPSESSID', null);
|
$this->getMainContext()->getSession()->setCookie('PHPSESSID', null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @When /^I should see the "([^"]*)" button in the "([^"]*)" gridfield for the "([^"]*)" row$/
|
||||||
|
* @param string $buttonLabel
|
||||||
|
* @param string $gridFieldName
|
||||||
|
* @param string $rowName
|
||||||
|
*/
|
||||||
|
public function assertIShouldSeeTheGridFieldButtonForRow($buttonLabel, $gridFieldName, $rowName)
|
||||||
|
{
|
||||||
|
$button = $this->getGridFieldButton($gridFieldName, $rowName, $buttonLabel);
|
||||||
|
assertNotNull($button, sprintf('Button "%s" not found', $buttonLabel));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @When /^I should not see the "([^"]*)" button in the "([^"]*)" gridfield for the "([^"]*)" row$/
|
||||||
|
* @param string $buttonLabel
|
||||||
|
* @param string $gridFieldName
|
||||||
|
* @param string $rowName
|
||||||
|
*/
|
||||||
|
public function assertIShouldNotSeeTheGridFieldButtonForRow($buttonLabel, $gridFieldName, $rowName)
|
||||||
|
{
|
||||||
|
$button = $this->getGridFieldButton($gridFieldName, $rowName, $buttonLabel);
|
||||||
|
assertNull($button, sprintf('Button "%s" found', $buttonLabel));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @When /^I click the "([^"]*)" button in the "([^"]*)" gridfield for the "([^"]*)" row$/
|
||||||
|
* @param string $buttonLabel
|
||||||
|
* @param string $gridFieldName
|
||||||
|
* @param string $rowName
|
||||||
|
*/
|
||||||
|
public function stepIClickTheGridFieldButtonForRow($buttonLabel, $gridFieldName, $rowName)
|
||||||
|
{
|
||||||
|
$button = $this->getGridFieldButton($gridFieldName, $rowName, $buttonLabel);
|
||||||
|
assertNotNull($button, sprintf('Button "%s" not found', $buttonLabel));
|
||||||
|
|
||||||
|
$button->click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a button in the gridfield row
|
||||||
|
*
|
||||||
|
* @param $gridFieldName
|
||||||
|
* @param $rowName
|
||||||
|
* @param $buttonLabel
|
||||||
|
* @return $button
|
||||||
|
*/
|
||||||
|
protected function getGridFieldButton($gridFieldName, $rowName, $buttonLabel)
|
||||||
|
{
|
||||||
|
$page = $this->getSession()->getPage();
|
||||||
|
$gridField = $page->find('xpath', sprintf('//*[@data-name="%s"]', $gridFieldName));
|
||||||
|
assertNotNull($gridField, sprintf('Gridfield "%s" not found', $gridFieldName));
|
||||||
|
|
||||||
|
$name = $gridField->find('xpath', sprintf('//*[count(*)=0 and contains(.,"%s")]', $rowName));
|
||||||
|
if (!$name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$button = $name->getParent()->find('xpath', sprintf('//*[@aria-label="%s"]', $buttonLabel));
|
||||||
|
|
||||||
|
return $button;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @When /^I click the "([^"]*)" option in the "([^"]*)" listbox$/
|
||||||
|
* @param $optionLabel
|
||||||
|
* @param $fieldName
|
||||||
|
*/
|
||||||
|
public function stepIClickTheListBoxOption($optionLabel, $fieldName)
|
||||||
|
{
|
||||||
|
$page = $this->getSession()->getPage();
|
||||||
|
$listBox = $page->find('xpath', sprintf('//*[@name="%s[]"]', $fieldName));
|
||||||
|
assertNotNull($listBox, sprintf('The listbox %s is not found', $fieldName));
|
||||||
|
|
||||||
|
$option = $listBox->getParent()
|
||||||
|
->find('css', '.chosen-choices')
|
||||||
|
->find('xpath', sprintf('//*[count(*)=0 and contains(.,"%s")]', $optionLabel));
|
||||||
|
assertNotNull($option, sprintf('Option %s is not found', $optionLabel));
|
||||||
|
|
||||||
|
$button = $option->getParent()->find('css', 'a');
|
||||||
|
|
||||||
|
$button->click();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user