Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

ENHANCEMENT Allowing PermissionCheckboxSetField to inspect multiple g…

…roup records for existing permissions

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@99584 467b73ca-7a2a-4603-9d3b-597d59a354a9
  • Loading branch information...
commit 19336e2fcbc1aed81af45eb43a83be1efdd4b45a 1 parent 246e866
Ingo Schommer chillu authored
Showing with 93 additions and 63 deletions.
  1. +2 −16 security/Group.php
  2. +91 −47 security/PermissionCheckboxSetField.php
18 security/Group.php
View
@@ -35,20 +35,6 @@ class Group extends DataObject {
"Hierarchy",
);
- function getAllParents() {
- $doSet = new DataObjectSet();
-
- $parentID = $this->ParentID;
-
- while($parentID) {
- $parent = DataObject::get_by_id('Group', $parentID);
- $doSet->push($parent);
- $parentID = $parent->ParentID;
- }
-
- return $doSet;
- }
-
/**
* Caution: Only call on instances, not through a singleton.
*
@@ -110,7 +96,7 @@ public function getCMSFields() {
$fields->removeFieldFromTab('Root', 'Permissions');
$fields->removeFieldFromTab('Root', 'IP Addresses');
} else {
- // $parentGroups = $this->getAllParents();
+ // $parentGroups = $this->getAncestors();
// if ($parentGroups) {
// foreach ($parentGroups as $parent) {
// if ($parent->Permissions()->Count()) {
@@ -135,7 +121,7 @@ public function getCMSFields() {
$roleData = Permission::check('ADMIN') ? DataObject::get('PermissionRole') : DataObject::get('PermissionRole', 'OnlyAdminCanApply = 0');
$fields->addFieldToTab('Root.' . _t('SecurityAdmin.ROLES', 'Roles'), new CheckboxSetField('Roles', 'Roles', $roleData));
- // $parentGroups = $this->getAllParents();
+ // $parentGroups = $this->getAncestors();
// if ($parentGroups) {
// foreach ($parentGroups as $parent) {
// if ($parent->Roles()->Count()) {
138 security/PermissionCheckboxSetField.php
View
@@ -1,6 +1,14 @@
<?php
-
-class PermissionCheckboxSetField extends CheckboxSetField {
+/**
+ * Shows a categorized list of available permissions (through {@link Permission::get_codes()}).
+ * Permissions which are assigned to a given {@link Group} record
+ * (either directly, inherited from parent groups, or through a {@link PermissionRole})
+ * will be checked automatically. All checkboxes for "inherited" permissions will be readonly.
+ *
+ * @package sapphire
+ * @subpackage security
+ */
+class PermissionCheckboxSetField extends FormField {
/**
* @var Array Filter certain permission codes from the output.
@@ -8,11 +16,41 @@ class PermissionCheckboxSetField extends CheckboxSetField {
*/
protected $hiddenPermissions = array();
- function __construct($name, $title, $managedClass, $filterField, $record = null) {
+ /**
+ * @var DataObjectSet
+ */
+ protected $groups = null;
+
+ /**
+ * @var array Array Nested array in same notation as {@link CheckboxSetField}.
+ */
+ protected $source = null;
+
+ /**
+ * @param String $name
+ * @param String $title
+ * @param String $managedClass
+ * @param String $filterField
+ * @param Group|DataObjectSet $groups One or more {@link Group} records used to determine permission checkboxes.
+ * Caution: saveInto() can only be used with a single group, all inherited permissions will be marked readonly.
+ * Setting multiple groups only makes sense in a readonly context. (Optional)
+ */
+ function __construct($name, $title, $managedClass, $filterField, $groups = null) {
$this->filterField = $filterField;
$this->managedClass = $managedClass;
- $this->record = $record;
- parent::__construct($name, $title, Permission::get_codes(true));
+
+ if(is_a($groups, 'DataObjectSet')) {
+ $this->groups = $groups;
+ } elseif(is_a($groups, 'Group')) {
+ $this->groups = new DataObjectSet($groups);
+ } elseif($groups) {
+ throw new InvalidArgumentException('$group should be either a Group record, or a DataObjectSet of Group records');
+ }
+
+ // Get all available codes in the system as a categorized nested array
+ $this->source = Permission::get_codes(true);
+
+ parent::__construct($name, $title);
}
/**
@@ -31,86 +69,92 @@ function getHiddenPermissions() {
function Field() {
Requirements::css(SAPPHIRE_DIR . '/css/CheckboxSetField.css');
-
- $source = $this->source;
- $values = array();
- // Get values from the join, if available
+ // Get existing values from the form record (assuming the formfield name is a join field on the record)
+ $uninheritedCodes = array();
if(is_object($this->form)) {
$record = $this->form->getRecord();
if ($record && $record->hasMethod($this->name)) {
$funcName = $this->name;
$join = $record->$funcName();
-
- if($join) {
- foreach($join as $joinItem) {
- $values[] = $joinItem->Code;
- }
+ if($join) foreach($join as $joinItem) {
+ $uninheritedCodes[$joinItem->Code] = $joinItem->Code;
}
}
}
- $odd = 0;
- $options = '';
-
- $inheritedItems = array();
- if ($this->record) {
- if ($this->record->Roles()->Count()) {
- foreach($this->record->Roles() as $role) {
+ // Get all 'inherited' codes not directly assigned to the group (which is stored in $values)
+ $inheritedCodes = array();
+ if($this->groups) foreach($this->groups as $group) {
+ // Get all uninherited permissions
+ foreach($group->Permissions() as $permission) {
+ $uninheritedCodes[$permission->Code] = $permission->Code;
+ }
+
+ // Get all permissions from roles
+ if ($group->Roles()->Count()) {
+ foreach($group->Roles() as $role) {
foreach($role->Codes() as $code) {
- if (!isset($inheritedItems[$code->Code])) $inheritedItems[$code->Code] = array();
- $inheritedItems[$code->Code][] = 'from role '.$role->Title;
+ if (!isset($inheritedCodes[$code->Code])) $inheritedCodes[$code->Code] = array();
+ // TODO i18n
+ $inheritedCodes[$code->Code][] = 'from role '.$role->Title;
}
}
}
-
- $parentGroups = $this->record->getAllParents();
+
+ // Get from parent groups
+ $parentGroups = $group->getAncestors();
if ($parentGroups) {
foreach ($parentGroups as $parent) {
- if ($parent->Roles()->Count()) {
- foreach($parent->Roles() as $role) {
- if ($role->Codes()) {
- foreach($role->Codes() as $code) {
- if (!isset($inheritedItems[$code->Code])) $inheritedItems[$code->Code] = array();
- $inheritedItems[$code->Code][] = 'role '.$role->Title.' on group '.$parent->Title;
- }
+ if (!$parent->Roles()->Count()) continue;
+ foreach($parent->Roles() as $role) {
+ if ($role->Codes()) {
+ foreach($role->Codes() as $code) {
+ if (!isset($inheritedCodes[$code->Code])) $inheritedCodes[$code->Code] = array();
+ // TODO i18n
+ $inheritedCodes[$code->Code][] = 'role '.$role->Title.' on group '.$parent->Title;
}
}
}
if ($parent->Permissions()->Count()) {
foreach($parent->Permissions() as $permission) {
- if (!isset($inheritedItems[$permission->Code])) $inheritedItems[$permission->Code] = array();
- $inheritedItems[$permission->Code][] = 'group '.$parent->Title;
+ if (!isset($inheritedCodes[$permission->Code])) $inheritedCodes[$permission->Code] = array();
+ // TODO i18n
+ $inheritedCodes[$permission->Code][] = 'group '.$parent->Title;
}
}
}
}
}
-
- if($source) {
- foreach($source as $categoryName => $permissions) {
+
+ $odd = 0;
+ $options = '';
+ if($this->source) {
+ // loop through all available categorized permissions and see if they're assigned for the given groups
+ foreach($this->source as $categoryName => $permissions) {
$options .= "<li><h5>$categoryName</h5></li>";
foreach($permissions as $code => $permission) {
if(in_array($code, $this->hiddenPermissions)) continue;
- $key = $code;
+
$value = $permission['name'];
$odd = ($odd + 1) % 2;
$extraClass = $odd ? 'odd' : 'even';
- $extraClass .= ' val' . str_replace(' ', '', $key);
- $itemID = $this->id() . '_' . ereg_replace('[^a-zA-Z0-9]+', '', $key);
+ $extraClass .= ' val' . str_replace(' ', '', $code);
+ $itemID = $this->id() . '_' . ereg_replace('[^a-zA-Z0-9]+', '', $code);
$checked = $disabled = $inheritMessage = '';
-
- $checked = in_array($key, $values) ? ' checked="checked"' : '';
-
- $title = $permission['help'] ? 'title="'.htmlentities($permission['help']).'" ' : '';
+ $checked = in_array($code, $uninheritedCodes) ? ' checked="checked"' : '';
+ $title = $permission['help'] ? 'title="' . htmlentities($permission['help']) . '" ' : '';
- if (isset($inheritedItems[$code])) {
+ if (isset($inheritedCodes[$code])) {
+ // disable inherited codes, as any saving logic would be too complicate to express in this interface
$disabled = ' disabled="true"';
- $inheritMessage = ' inherited from '.join(', ', $inheritedItems[$code]).'';
+ // TODO i18n
+ $inheritMessage = ' inherited from ' . join(', ', $inheritedCodes[$code]) . '';
$options .= "<li class=\"$extraClass\"><label {$title}for=\"$itemID\">$value is $inheritMessage</label></li>\n";
} else {
- $options .= "<li class=\"$extraClass\"><input id=\"$itemID\"$disabled name=\"$this->name[$key]\" type=\"checkbox\" value=\"$key\"$checked class=\"checkbox\" /> <label {$title}for=\"$itemID\">$value$inheritMessage</label></li>\n";
+ // uninherited (and hence editable) code checkbox
+ $options .= "<li class=\"$extraClass\"><input id=\"$itemID\"$disabled name=\"$this->name[$code]\" type=\"checkbox\" value=\"$code\"$checked class=\"checkbox\" /> <label {$title}for=\"$itemID\">$value$inheritMessage</label></li>\n";
}
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.