Skip to content

Commit

Permalink
NEW: Validate the Title on Group is not empty
Browse files Browse the repository at this point in the history
NEW: Use trim to validate Group title

NEW: Stop duplicate and empty Group titles

NEW: Do not allow group codes to be duplicated
  • Loading branch information
Kirk Mayo committed Oct 11, 2021
1 parent 4163d38 commit 9c30c41
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 6 deletions.
1 change: 1 addition & 0 deletions lang/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ en:
GROUPNAME: 'Group name'
GroupReminder: 'If you choose a parent group, this group will take all it''s roles'
HierarchyPermsError: 'Can''t assign parent group "{group}" with privileged permissions (requires ADMIN access)'
ValidationIdentifierAlreadyExists: 'A Group ({group}) already exists with the same {identifier}'
Locked: 'Locked?'
MEMBERS: Members
NEWGROUP: 'New Group'
Expand Down
9 changes: 6 additions & 3 deletions src/Dev/SapphireTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1112,9 +1112,12 @@ protected function createMemberWithPermission($permCode)
$member = $this->cache_generatedMembers[$permCode];
} else {
// Generate group with these permissions
$group = Group::create();
$group->Title = "$permCode group";
$group->write();
$group = Group::get()->filter('Code', "$permCode-group")->first();
if (!$group || !$group->exists()) {
$group = Group::create();
$group->Title = "$permCode group ";
$group->write();
}

// Create each individual permission
foreach ($permArray as $permArrayItem) {
Expand Down
49 changes: 48 additions & 1 deletion src/Security/Group.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use SilverStripe\Admin\SecurityAdmin;
use SilverStripe\Core\Convert;
use SilverStripe\Forms\CompositeValidator;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
Expand All @@ -21,6 +22,7 @@
use SilverStripe\Forms\HTMLEditor\HTMLEditorConfig;
use SilverStripe\Forms\ListboxField;
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\RequiredFields;
use SilverStripe\Forms\Tab;
use SilverStripe\Forms\TabSet;
use SilverStripe\Forms\TextareaField;
Expand Down Expand Up @@ -480,7 +482,16 @@ public function getTreeTitle()
*/
public function setCode($val)
{
$this->setField("Code", Convert::raw2url($val));
$currentGroups = Group::get()
->map('Code', 'Title')
->toArray();
$code = Convert::raw2url($val);
$count = 2;
while (isset($currentGroups[$code])) {
$code = Convert::raw2url($val . '-' . $count);
$count++;
}
$this->setField("Code", $code);
}

public function validate()
Expand All @@ -506,9 +517,45 @@ public function validate()
}
}

$currentGroups = Group::get()
->filter('ID:not', $this->ID)
->map('Code', 'Title')
->toArray();

if (isset($currentGroups[$this->Code])) {
$result->addError(
_t(
'SilverStripe\\Security\\Group.ValidationIdentifierAlreadyExists',
'A Group ({group}) already exists with the same {identifier}',
['group' => $this->Code, 'identifier' => 'Code']
)
);
}

if (in_array($this->Title, $currentGroups)) {
$result->addError(
_t(
'SilverStripe\\Security\\Group.ValidationIdentifierAlreadyExists',
'A Group ({group}) already exists with the same {identifier}',
['group' => $this->Title, 'identifier' => 'Title']
)
);
}

return $result;
}

public function getCMSCompositeValidator(): CompositeValidator
{
$validator = parent::getCMSCompositeValidator();

$validator->addValidator(RequiredFields::create([
'Title'
]));

return $validator;
}

public function onBeforeWrite()
{
parent::onBeforeWrite();
Expand Down
2 changes: 1 addition & 1 deletion tests/php/Security/GroupCsvBulkLoaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public function testOverwriteExistingImport()

$updated = $results->Updated()->toArray();
$this->assertEquals(count($updated), 1);
$this->assertEquals($updated[0]->Code, 'newgroup1');
$this->assertEquals($updated[0]->Code, 'newgroup1-2');
$this->assertEquals($updated[0]->Title, 'New Group 1');
}

Expand Down
60 changes: 59 additions & 1 deletion tests/php/Security/GroupTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use InvalidArgumentException;
use SilverStripe\Control\Controller;
use SilverStripe\Dev\FunctionalTest;
use SilverStripe\Forms\RequiredFields;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataObject;
use SilverStripe\Security\Group;
Expand Down Expand Up @@ -33,7 +34,7 @@ public function testGroupCodeDefaultsToTitle()
$this->assertEquals('my-title', $g1->Code, 'Custom title gets converted to code if none exists already');

$g2 = new Group();
$g2->Title = "My Title";
$g2->Title = "My Title and Code";
$g2->Code = "my-code";
$g2->write();
$this->assertEquals('my-code', $g2->Code, 'Custom attributes are not overwritten by Title field');
Expand Down Expand Up @@ -101,6 +102,7 @@ public function testUnsavedGroups()
{
$member = $this->objFromFixture(TestMember::class, 'admin');
$group = new Group();
$group->Title = 'Title';

// Can save user to unsaved group
$group->Members()->add($member);
Expand All @@ -121,6 +123,7 @@ public function testCollateAncestorIDs()
/** @var Group $childGroup */
$childGroup = $this->objFromFixture(Group::class, 'childgroup');
$orphanGroup = new Group();
$orphanGroup->Title = 'Title';
$orphanGroup->ParentID = 99999;
$orphanGroup->write();

Expand Down Expand Up @@ -280,4 +283,59 @@ public function testValidatesPrivilegeLevelOfParent()
'Members with only APPLY_ROLES can\'t assign parent groups with inherited ADMIN permission'
);
}

public function testGroupTitleValidation()
{
$group1 = $this->objFromFixture(Group::class, 'group1');

$newGroup = new Group();

$validators = $newGroup->getCMSCompositeValidator()->getValidators();
$this->assertCount(1, $validators);
$this->assertInstanceOf(RequiredFields::class, $validators[0]);
$this->assertTrue(in_array('Title', $validators[0]->getRequired()));

$newGroup->Title = $group1->Title;
$result = $newGroup->validate();
$this->assertFalse(
$result->isValid(),
'Group names cannot be duplicated'
);

$newGroup->Title = 'Title';
$result = $newGroup->validate();
$this->assertTrue($result->isValid());
}

public function testGroupTitleDuplication()
{
$group = $this->objFromFixture(Group::class, 'group1');
$group->Title = 'Group title modified';
$group->write();
$this->assertEquals('group-1', $group->Code);

$group = new Group();
$group->Title = 'Group 1';
$group->write();
$this->assertEquals('group-1-2', $group->Code);

$group = new Group();
$group->Title = 'Duplicate';
$group->write();
$group->Title = 'Duplicate renamed';
$group->write();
$this->assertEquals('duplicate', $group->Code);

$group = new Group();
$group->Title = 'Duplicate';
$group->write();
$group->Title = 'More renaming';
$group->write();
$this->assertEquals('duplicate-2', $group->Code);

$group = new Group();
$group->Title = 'Duplicate';
$group->write();
$this->assertEquals('duplicate-3', $group->Code);
}
}
4 changes: 4 additions & 0 deletions tests/php/Security/GroupTest.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
'SilverStripe\Security\Group':
admingroup:
Title: Admin Group
Code: admingroup
parentgroup:
Title: Parent Group
Code: parentgroup
childgroup:
Title: Child Group
Code: childgroup
Parent: '=>SilverStripe\Security\Group.parentgroup'
grandchildgroup:
Title: Grandchild Group
Code: grandchildgroup
Parent: '=>SilverStripe\Security\Group.childgroup'
group1:
Expand Down

0 comments on commit 9c30c41

Please sign in to comment.