public function processRecord($record, $columnMap, &$results, $preview = false) { $objID = parent::processRecord($record, $columnMap, $results, $preview); $_cache_groupByCode = array(); // Add to predefined groups /** @var Member $member */ $member = DataObject::get_by_id($this->objectClass, $objID); foreach ($this->groups as $group) { // TODO This isnt the most memory effective way to add members to a group $member->Groups()->add($group); } // Add to groups defined in CSV if (isset($record['Groups']) && $record['Groups']) { $groupCodes = explode(',', $record['Groups']); foreach ($groupCodes as $groupCode) { $groupCode = Convert::raw2url($groupCode); if (!isset($_cache_groupByCode[$groupCode])) { $group = Group::get()->filter('Code', $groupCode)->first(); if (!$group) { $group = new Group(); $group->Code = $groupCode; $group->Title = $groupCode; $group->write(); } $member->Groups()->add($group); $_cache_groupByCode[$groupCode] = $group; } } } $member->destroy(); unset($member); return $objID; }
public function testCollateAncestorIDs() { $parentGroup = $this->objFromFixture('SilverStripe\\Security\\Group', 'parentgroup'); $childGroup = $this->objFromFixture('SilverStripe\\Security\\Group', 'childgroup'); $orphanGroup = new Group(); $orphanGroup->ParentID = 99999; $orphanGroup->write(); $this->assertEquals(1, count($parentGroup->collateAncestorIDs()), 'Root node only contains itself'); $this->assertContains($parentGroup->ID, $parentGroup->collateAncestorIDs()); $this->assertEquals(2, count($childGroup->collateAncestorIDs()), 'Contains parent nodes, with child node first'); $this->assertContains($parentGroup->ID, $childGroup->collateAncestorIDs()); $this->assertContains($childGroup->ID, $childGroup->collateAncestorIDs()); $this->assertEquals(1, count($orphanGroup->collateAncestorIDs()), 'Orphaned nodes dont contain invalid parent IDs'); $this->assertContains($orphanGroup->ID, $orphanGroup->collateAncestorIDs()); }
public function getEditForm($id = null, $fields = null) { // TODO Duplicate record fetching (see parent implementation) if (!$id) { $id = $this->currentPageID(); } $form = parent::getEditForm($id); // TODO Duplicate record fetching (see parent implementation) $record = $this->getRecord($id); if ($record && !$record->canView()) { return Security::permissionFailure($this); } $memberList = GridField::create('Members', false, Member::get(), $memberListConfig = GridFieldConfig_RecordEditor::create()->addComponent(new GridFieldButtonRow('after'))->addComponent(new GridFieldExportButton('buttons-after-left')))->addExtraClass("members_grid"); if ($record && method_exists($record, 'getValidator')) { $validator = $record->getValidator(); } else { $validator = Member::singleton()->getValidator(); } $memberListConfig->getComponentByType('GridFieldDetailForm')->setValidator($validator); $groupList = GridField::create('Groups', false, Group::get(), GridFieldConfig_RecordEditor::create()); $columns = $groupList->getConfig()->getComponentByType('GridFieldDataColumns'); $columns->setDisplayFields(array('Breadcrumbs' => singleton('SilverStripe\\Security\\Group')->fieldLabel('Title'))); $columns->setFieldFormatting(array('Breadcrumbs' => function ($val, $item) { return Convert::raw2xml($item->getBreadcrumbs(' > ')); })); $fields = new FieldList($root = new TabSet('Root', $usersTab = new Tab('Users', _t('SecurityAdmin.Users', 'Users'), new LiteralField('MembersCautionText', sprintf('<div class="alert alert-warning" role="alert">%s</div>', _t('SecurityAdmin.MemberListCaution', 'Caution: Removing members from this list will remove them from all groups and the database'))), $memberList), $groupsTab = new Tab('Groups', singleton('SilverStripe\\Security\\Group')->i18n_plural_name(), $groupList)), new HiddenField('ID', false, 0)); // Add import capabilities. Limit to admin since the import logic can affect assigned permissions if (Permission::check('ADMIN')) { $fields->addFieldsToTab('Root.Users', array(new HeaderField(_t('SecurityAdmin.IMPORTUSERS', 'Import users'), 3), new LiteralField('MemberImportFormIframe', sprintf('<iframe src="%s" id="MemberImportFormIframe" width="100%%" height="250px" frameBorder="0">' . '</iframe>', $this->Link('memberimport'))))); $fields->addFieldsToTab('Root.Groups', array(new HeaderField(_t('SecurityAdmin.IMPORTGROUPS', 'Import groups'), 3), new LiteralField('GroupImportFormIframe', sprintf('<iframe src="%s" id="GroupImportFormIframe" width="100%%" height="250px" frameBorder="0">' . '</iframe>', $this->Link('groupimport'))))); } // Tab nav in CMS is rendered through separate template $root->setTemplate('CMSTabSet'); // Add roles editing interface if (Permission::check('APPLY_ROLES')) { $rolesField = GridField::create('Roles', false, PermissionRole::get(), GridFieldConfig_RecordEditor::create()); $rolesTab = $fields->findOrMakeTab('Root.Roles', _t('SecurityAdmin.TABROLES', 'Roles')); $rolesTab->push($rolesField); } $actionParam = $this->getRequest()->param('Action'); if ($actionParam == 'groups') { $groupsTab->addExtraClass('ui-state-active'); } elseif ($actionParam == 'users') { $usersTab->addExtraClass('ui-state-active'); } elseif ($actionParam == 'roles') { $rolesTab->addExtraClass('ui-state-active'); } $actions = new FieldList(); $form = Form::create($this, 'EditForm', $fields, $actions)->setHTMLID('Form_EditForm'); $form->addExtraClass('cms-edit-form'); $form->setTemplate($this->getTemplatesWithSuffix('_EditForm')); // Tab nav in CMS is rendered through separate template if ($form->Fields()->hasTabset()) { $form->Fields()->findOrMakeTab('Root')->setTemplate('CMSTabSet'); } $form->addExtraClass('center ss-tabset cms-tabset ' . $this->BaseCSSClasses()); $form->setAttribute('data-pjax-fragment', 'CurrentForm'); $this->extend('updateEditForm', $form); return $form; }
public function testOverwriteExistingImport() { $existinggroup = new Group(); $existinggroup->Title = 'Old Group Title'; $existinggroup->Code = 'newgroup1'; $existinggroup->write(); $loader = new GroupCsvBulkLoader(); $results = $loader->load($this->getCurrentRelativePath() . '/GroupCsvBulkLoaderTest.csv'); $created = $results->Created()->toArray(); $this->assertEquals(count($created), 1); $this->assertEquals($created[0]->Code, 'newchildgroup1'); $updated = $results->Updated()->toArray(); $this->assertEquals(count($updated), 1); $this->assertEquals($updated[0]->Code, 'newgroup1'); $this->assertEquals($updated[0]->Title, 'New Group 1'); }
/** * Create a member and group with the given permission code, and log in with it. * Returns the member ID. * * @param string|array $permCode Either a permission, or list of permissions * @return int Member ID */ public function logInWithPermission($permCode = "ADMIN") { if (is_array($permCode)) { $permArray = $permCode; $permCode = implode('.', $permCode); } else { $permArray = array($permCode); } // Check cached member if (isset($this->cache_generatedMembers[$permCode])) { $member = $this->cache_generatedMembers[$permCode]; } else { // Generate group with these permissions $group = Group::create(); $group->Title = "{$permCode} group"; $group->write(); // Create each individual permission foreach ($permArray as $permArrayItem) { $permission = Permission::create(); $permission->Code = $permArrayItem; $permission->write(); $group->Permissions()->add($permission); } $member = DataObject::get_one('SilverStripe\\Security\\Member', array('"Member"."Email"' => "{$permCode}@example.org")); if (!$member) { $member = Member::create(); } $member->FirstName = $permCode; $member->Surname = "User"; $member->Email = "{$permCode}@example.org"; $member->write(); $group->Members()->add($member); $this->cache_generatedMembers[$permCode] = $member; } $member->logIn(); return $member->ID; }
/** * Return all of the groups that have one of the given permission codes * @param array|string $codes Either a single permission code, or an array of permission codes * @return SS_List The matching group objects */ public static function get_groups_by_permission($codes) { $codeParams = is_array($codes) ? $codes : array($codes); $codeClause = DB::placeholders($codeParams); // Via Roles are groups that have the permission via a role /** @skipUpgrade */ return Group::get()->where(array("\"PermissionRoleCode\".\"Code\" IN ({$codeClause}) OR \"Permission\".\"Code\" IN ({$codeClause})" => array_merge($codeParams, $codeParams)))->leftJoin('Permission', "\"Permission\".\"GroupID\" = \"Group\".\"ID\"")->leftJoin('Group_Roles', "\"Group_Roles\".\"GroupID\" = \"Group\".\"ID\"")->leftJoin('PermissionRole', "\"Group_Roles\".\"PermissionRoleID\" = \"PermissionRole\".\"ID\"")->leftJoin('PermissionRoleCode', "\"PermissionRoleCode\".\"RoleID\" = \"PermissionRole\".\"ID\""); }
/** * Return an existing member with administrator privileges, or create one of necessary. * * Will create a default 'Administrators' group if no group is found * with an ADMIN permission. Will create a new 'Admin' member with administrative permissions * if no existing Member with these permissions is found. * * Important: Any newly created administrator accounts will NOT have valid * login credentials (Email/Password properties), which means they can't be used for login * purposes outside of any default credentials set through {@link Security::setDefaultAdmin()}. * * @return Member */ public static function findAnAdministrator() { // coupling to subsites module $origSubsite = null; if (is_callable('Subsite::changeSubsite')) { $origSubsite = \Subsite::currentSubsiteID(); \Subsite::changeSubsite(0); } $member = null; // find a group with ADMIN permission $adminGroup = Permission::get_groups_by_permission('ADMIN')->first(); if (is_callable('Subsite::changeSubsite')) { \Subsite::changeSubsite($origSubsite); } if ($adminGroup) { $member = $adminGroup->Members()->First(); } if (!$adminGroup) { Group::singleton()->requireDefaultRecords(); $adminGroup = Permission::get_groups_by_permission('ADMIN')->first(); } if (!$member) { Member::singleton()->requireDefaultRecords(); $member = Permission::get_members_by_permission('ADMIN')->first(); } if (!$member) { $member = Member::default_admin(); } if (!$member) { // Failover to a blank admin $member = Member::create(); $member->FirstName = _t('Member.DefaultAdminFirstname', 'Default Admin'); $member->write(); // Add member to group instead of adding group to member // This bypasses the privilege escallation code in Member_GroupSet $adminGroup->DirectMembers()->add($member); } return $member; }
/** * Return a {@link FieldList} of fields that would appropriate for editing * this member. * * @return FieldList Return a FieldList of fields that would appropriate for * editing this member. */ public function getCMSFields() { require_once 'Zend/Date.php'; $self = $this; $this->beforeUpdateCMSFields(function (FieldList $fields) use($self) { /** @var FieldList $mainFields */ $mainFields = $fields->fieldByName("Root")->fieldByName("Main")->getChildren(); // Build change password field $mainFields->replaceField('Password', $self->getMemberPasswordField()); $mainFields->replaceField('Locale', new DropdownField("Locale", _t('Member.INTERFACELANG', "Interface Language", 'Language of the CMS'), i18n::get_existing_translations())); $mainFields->removeByName($self->config()->hidden_fields); if (!$self->config()->lock_out_after_incorrect_logins) { $mainFields->removeByName('FailedLoginCount'); } // Groups relation will get us into logical conflicts because // Members are displayed within group edit form in SecurityAdmin $fields->removeByName('Groups'); // Members shouldn't be able to directly view/edit logged passwords $fields->removeByName('LoggedPasswords'); $fields->removeByName('RememberLoginHashes'); if (Permission::check('EDIT_PERMISSIONS')) { $groupsMap = array(); foreach (Group::get() as $group) { // Listboxfield values are escaped, use ASCII char instead of » $groupsMap[$group->ID] = $group->getBreadcrumbs(' > '); } asort($groupsMap); $fields->addFieldToTab('Root.Main', ListboxField::create('DirectGroups', singleton('SilverStripe\\Security\\Group')->i18n_plural_name())->setSource($groupsMap)->setAttribute('data-placeholder', _t('Member.ADDGROUP', 'Add group', 'Placeholder text for a dropdown'))); // Add permission field (readonly to avoid complicated group assignment logic). // This should only be available for existing records, as new records start // with no permissions until they have a group assignment anyway. if ($self->ID) { $permissionsField = new PermissionCheckboxSetField_Readonly('Permissions', false, 'SilverStripe\\Security\\Permission', 'GroupID', $self->getManyManyComponents('Groups')); $fields->findOrMakeTab('Root.Permissions', singleton('SilverStripe\\Security\\Permission')->i18n_plural_name()); $fields->addFieldToTab('Root.Permissions', $permissionsField); } } $permissionsTab = $fields->fieldByName("Root")->fieldByName('Permissions'); if ($permissionsTab) { $permissionsTab->addExtraClass('readonly'); } $defaultDateFormat = Zend_Locale_Format::getDateFormat(new Zend_Locale($self->Locale)); $dateFormatMap = array('MMM d, yyyy' => Zend_Date::now()->toString('MMM d, yyyy'), 'yyyy/MM/dd' => Zend_Date::now()->toString('yyyy/MM/dd'), 'MM/dd/yyyy' => Zend_Date::now()->toString('MM/dd/yyyy'), 'dd/MM/yyyy' => Zend_Date::now()->toString('dd/MM/yyyy')); $dateFormatMap[$defaultDateFormat] = Zend_Date::now()->toString($defaultDateFormat) . sprintf(' (%s)', _t('Member.DefaultDateTime', 'default')); $mainFields->push($dateFormatField = new MemberDatetimeOptionsetField('DateFormat', $self->fieldLabel('DateFormat'), $dateFormatMap)); $dateFormatField->setValue($self->DateFormat); $dateFormatField->setDescriptionTemplate('forms/MemberDatetimeOptionsetField_description_date'); $defaultTimeFormat = Zend_Locale_Format::getTimeFormat(new Zend_Locale($self->Locale)); $timeFormatMap = array('h:mm a' => Zend_Date::now()->toString('h:mm a'), 'H:mm' => Zend_Date::now()->toString('H:mm')); $timeFormatMap[$defaultTimeFormat] = Zend_Date::now()->toString($defaultTimeFormat) . sprintf(' (%s)', _t('Member.DefaultDateTime', 'default')); $mainFields->push($timeFormatField = new MemberDatetimeOptionsetField('TimeFormat', $self->fieldLabel('TimeFormat'), $timeFormatMap)); $timeFormatField->setValue($self->TimeFormat); $timeFormatField->setDescriptionTemplate('forms/MemberDatetimeOptionsetField_description_time'); }); return parent::getCMSFields(); }
public function Breadcrumbs($unlinked = false) { $crumbs = parent::Breadcrumbs($unlinked); // Name root breadcrumb based on which record is edited, // which can only be determined by looking for the fieldname of the GridField. // Note: Titles should be same titles as tabs in RootForm(). $params = $this->getRequest()->allParams(); if (isset($params['FieldName'])) { // TODO FieldName param gets overwritten by nested GridFields, // so shows "Members" rather than "Groups" for the following URL: // admin/security/EditForm/field/Groups/item/2/ItemEditForm/field/Members/item/1/edit $firstCrumb = $crumbs->shift(); if ($params['FieldName'] == 'Groups') { $crumbs->unshift(new ArrayData(array('Title' => Group::singleton()->i18n_plural_name(), 'Link' => $this->Link('groups')))); } elseif ($params['FieldName'] == 'Users') { $crumbs->unshift(new ArrayData(array('Title' => _t('SecurityAdmin.Users', 'Users'), 'Link' => $this->Link('users')))); } elseif ($params['FieldName'] == 'Roles') { $crumbs->unshift(new ArrayData(array('Title' => _t('SecurityAdmin.TABROLES', 'Roles'), 'Link' => $this->Link('roles')))); } $crumbs->unshift($firstCrumb); } return $crumbs; }
/** * Test Member_GroupSet::add */ public function testOnChangeGroupsBySetIDList() { $staffMember = $this->objFromFixture('SilverStripe\\Security\\Member', 'staffmember'); // Setup new admin group $newAdminGroup = new Group(array('Title' => 'newadmin')); $newAdminGroup->write(); Permission::grant($newAdminGroup->ID, 'ADMIN'); // Test staff member can't be added to admin groups $this->assertFalse($staffMember->inGroup($newAdminGroup)); $staffMember->Groups()->setByIDList(array($newAdminGroup->ID)); $this->assertFalse($staffMember->inGroup($newAdminGroup), 'Adding new admin group relation is not allowed for non-admin members'); }
/** * Add default records to database. * * This function is called whenever the database is built, after the * database tables have all been created. */ public function requireDefaultRecords() { parent::requireDefaultRecords(); // Add default author group if no other group exists $allGroups = DataObject::get('SilverStripe\\Security\\Group'); if (!$allGroups->count()) { $authorGroup = new Group(); $authorGroup->Code = 'content-authors'; $authorGroup->Title = _t('Group.DefaultGroupTitleContentAuthors', 'Content Authors'); $authorGroup->Sort = 1; $authorGroup->write(); Permission::grant($authorGroup->ID, 'CMS_ACCESS_CMSMain'); Permission::grant($authorGroup->ID, 'CMS_ACCESS_AssetAdmin'); Permission::grant($authorGroup->ID, 'CMS_ACCESS_ReportAdmin'); Permission::grant($authorGroup->ID, 'SITETREE_REORGANISE'); } // Add default admin group if none with permission code ADMIN exists $adminGroups = Permission::get_groups_by_permission('ADMIN'); if (!$adminGroups->count()) { $adminGroup = new Group(); $adminGroup->Code = 'administrators'; $adminGroup->Title = _t('Group.DefaultGroupTitleAdministrators', 'Administrators'); $adminGroup->Sort = 0; $adminGroup->write(); Permission::grant($adminGroup->ID, 'ADMIN'); } // Members are populated through Member->requireDefaultRecords() }