Add an Account Admin role with permission to administer users and assign managed roles #714
This commit is contained in:
commit
6970f3b568
|
@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- [Add a Group membership assignment quick form #723](https://github.com/farmOS/farmOS/pull/723)
|
- [Add a Group membership assignment quick form #723](https://github.com/farmOS/farmOS/pull/723)
|
||||||
- [farmOS Setup Menu #706](https://github.com/farmOS/farmOS/pull/706)
|
- [farmOS Setup Menu #706](https://github.com/farmOS/farmOS/pull/706)
|
||||||
- [Issue #3354935: Configurable quick forms](https://www.drupal.org/project/farm/issues/3354935)
|
- [Issue #3354935: Configurable quick forms](https://www.drupal.org/project/farm/issues/3354935)
|
||||||
|
- [Add an Account Admin role with permission to administer users and assign managed roles #714](https://github.com/farmOS/farmOS/pull/714)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
"drupal/migrate_source_csv": "^3.5",
|
"drupal/migrate_source_csv": "^3.5",
|
||||||
"drupal/migrate_source_ui": "^1.0",
|
"drupal/migrate_source_ui": "^1.0",
|
||||||
"drupal/migrate_tools": "^6.0.2",
|
"drupal/migrate_tools": "^6.0.2",
|
||||||
|
"drupal/role_delegation": "^1.2",
|
||||||
"drupal/simple_oauth": "5.2.3",
|
"drupal/simple_oauth": "5.2.3",
|
||||||
"drupal/state_machine": "^1.0",
|
"drupal/state_machine": "^1.0",
|
||||||
"drupal/subrequests": "^3.0.3",
|
"drupal/subrequests": "^3.0.3",
|
||||||
|
|
|
@ -60,6 +60,7 @@ function farm_modules() {
|
||||||
'farm_import_kml' => t('KML asset importer'),
|
'farm_import_kml' => t('KML asset importer'),
|
||||||
'farm_fieldkit' => t('Field Kit integration'),
|
'farm_fieldkit' => t('Field Kit integration'),
|
||||||
'farm_l10n' => t('Translation/localization features'),
|
'farm_l10n' => t('Translation/localization features'),
|
||||||
|
'farm_role_account_admin' => t('Account Admin role'),
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
langcode: en
|
||||||
|
status: true
|
||||||
|
dependencies:
|
||||||
|
enforced:
|
||||||
|
module:
|
||||||
|
- farm_role_account_admin
|
||||||
|
module:
|
||||||
|
- farm_role
|
||||||
|
id: farm_account_admin
|
||||||
|
label: 'Account Admin'
|
||||||
|
weight: 1
|
||||||
|
is_admin: false
|
||||||
|
permissions:
|
||||||
|
- 'administer farm settings'
|
||||||
|
- 'administer users'
|
||||||
|
third_party_settings:
|
||||||
|
farm_role:
|
||||||
|
access:
|
||||||
|
config: true
|
||||||
|
entity:
|
||||||
|
view all: false
|
||||||
|
create all: false
|
||||||
|
update all: false
|
||||||
|
delete all: false
|
|
@ -0,0 +1,7 @@
|
||||||
|
farm_role_account_admin.settings:
|
||||||
|
type: config_object
|
||||||
|
label: 'farmOS Account Admin Role settings'
|
||||||
|
mapping:
|
||||||
|
allow_peer_role_assignment:
|
||||||
|
type: boolean
|
||||||
|
label: 'Allow users with the Account Admin role to assign/revoke the Account Admin role.'
|
|
@ -0,0 +1,9 @@
|
||||||
|
name: farmOS Account Admin Role
|
||||||
|
description: Provides an Account Admin role for managing users.
|
||||||
|
type: module
|
||||||
|
package: farmOS
|
||||||
|
core_version_requirement: ^9
|
||||||
|
dependencies:
|
||||||
|
- farm:farm_role
|
||||||
|
- farm:farm_settings
|
||||||
|
- role_delegation:role_delegation
|
|
@ -0,0 +1,5 @@
|
||||||
|
farm_role_account_admin.settings:
|
||||||
|
base_route: farm_settings.settings_page
|
||||||
|
route_name: farm_role_account_admin.settings
|
||||||
|
title: 'Account Admin'
|
||||||
|
weight: 5
|
|
@ -0,0 +1,3 @@
|
||||||
|
farm_role_account_admin:
|
||||||
|
permission_callbacks:
|
||||||
|
- Drupal\farm_role_account_admin\AccountAdminPermissions::permissions
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Hooks implemented by the farmOS Account Admin Role module.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Drupal\Core\Access\AccessResult;
|
||||||
|
use Drupal\Core\Entity\EntityInterface;
|
||||||
|
use Drupal\Core\Session\AccountInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements hook_ENTITY_TYPE_access().
|
||||||
|
*/
|
||||||
|
function farm_role_account_admin_user_access(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||||
|
|
||||||
|
// Only user 1 can access user 1.
|
||||||
|
if ($entity->id() == 1 && $account->id() != 1) {
|
||||||
|
return AccessResult::forbidden();
|
||||||
|
}
|
||||||
|
return AccessResult::neutral();
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
configure account admin role:
|
||||||
|
title: 'Configure Account Admin role'
|
|
@ -0,0 +1,7 @@
|
||||||
|
farm_role_account_admin.settings:
|
||||||
|
path: 'farm/settings/account-admin'
|
||||||
|
defaults:
|
||||||
|
_form: '\Drupal\farm_role_account_admin\Form\AccountAdminSettingsForm'
|
||||||
|
_title: 'Account Admin Role settings'
|
||||||
|
requirements:
|
||||||
|
_permission: 'configure account admin role'
|
|
@ -0,0 +1,89 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Drupal\farm_role_account_admin;
|
||||||
|
|
||||||
|
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||||
|
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||||
|
use Drupal\farm_role\ManagedRolePermissionsManagerInterface;
|
||||||
|
use Drupal\user\RoleInterface;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add permissions to the Account Admin role.
|
||||||
|
*/
|
||||||
|
class AccountAdminPermissions implements ContainerInjectionInterface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The managed role permissions manager.
|
||||||
|
*
|
||||||
|
* @var \Drupal\farm_role\ManagedRolePermissionsManagerInterface
|
||||||
|
*/
|
||||||
|
protected $managedRolePermissionsManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The config factory service.
|
||||||
|
*
|
||||||
|
* @var \Drupal\Core\Config\ConfigFactoryInterface
|
||||||
|
*/
|
||||||
|
protected $configFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an AccountAdminPermissions object.
|
||||||
|
*
|
||||||
|
* @param \Drupal\farm_role\ManagedRolePermissionsManagerInterface $managed_role_permissions_manager
|
||||||
|
* The managed role permissions manager.
|
||||||
|
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||||
|
* The config factory service.
|
||||||
|
*/
|
||||||
|
public function __construct(ManagedRolePermissionsManagerInterface $managed_role_permissions_manager, ConfigFactoryInterface $config_factory) {
|
||||||
|
$this->managedRolePermissionsManager = $managed_role_permissions_manager;
|
||||||
|
$this->configFactory = $config_factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public static function create(ContainerInterface $container) {
|
||||||
|
return new static(
|
||||||
|
$container->get('plugin.manager.managed_role_permissions'),
|
||||||
|
$container->get('config.factory'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add permissions to default farmOS roles.
|
||||||
|
*
|
||||||
|
* @param \Drupal\user\RoleInterface $role
|
||||||
|
* The role to add permissions to.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
* An array of permission strings.
|
||||||
|
*/
|
||||||
|
public function permissions(RoleInterface $role) {
|
||||||
|
$perms = [];
|
||||||
|
|
||||||
|
// Add permissions to the farm_account_admin role.
|
||||||
|
if ($role->id() == 'farm_account_admin') {
|
||||||
|
|
||||||
|
// Load the module settings.
|
||||||
|
$settings = $this->configFactory->get('farm_role_account_admin.settings');
|
||||||
|
|
||||||
|
// Grant the ability to assign managed farmOS roles.
|
||||||
|
$roles = $this->managedRolePermissionsManager->getMangedRoles();
|
||||||
|
foreach ($roles as $role) {
|
||||||
|
|
||||||
|
// Do not allow assigning the "Account Admin" role if
|
||||||
|
// allow_peer_role_assignment is disabled.
|
||||||
|
if ($role->id() == 'farm_account_admin' && !$settings->get('allow_peer_role_assignment', FALSE)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add permission to assign the role.
|
||||||
|
$perms[] = 'assign ' . $role->id() . ' role';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $perms;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Drupal\farm_role_account_admin\Form;
|
||||||
|
|
||||||
|
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
|
||||||
|
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||||
|
use Drupal\Core\Form\ConfigFormBase;
|
||||||
|
use Drupal\Core\Form\FormStateInterface;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a settings form for the Account Admin Role module.
|
||||||
|
*/
|
||||||
|
class AccountAdminSettingsForm extends ConfigFormbase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Config settings.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const SETTINGS = 'farm_role_account_admin.settings';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cache tags invalidator.
|
||||||
|
*
|
||||||
|
* @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface
|
||||||
|
*/
|
||||||
|
protected $cacheTagsInvalidator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a \Drupal\system\ConfigFormBase object.
|
||||||
|
*
|
||||||
|
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||||
|
* The factory for configuration objects.
|
||||||
|
* @param \Drupal\Core\Cache\CacheTagsInvalidatorInterface $cache_tags_invalidator
|
||||||
|
* The cache tags invalidator.
|
||||||
|
*/
|
||||||
|
public function __construct(ConfigFactoryInterface $config_factory, CacheTagsInvalidatorInterface $cache_tags_invalidator) {
|
||||||
|
$this->setConfigFactory($config_factory);
|
||||||
|
$this->cacheTagsInvalidator = $cache_tags_invalidator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public static function create(ContainerInterface $container) {
|
||||||
|
return new static(
|
||||||
|
$container->get('config.factory'),
|
||||||
|
$container->get('cache_tags.invalidator'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getFormId() {
|
||||||
|
return 'farm_role_account_admin_settings';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function getEditableConfigNames() {
|
||||||
|
return [
|
||||||
|
static::SETTINGS,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function buildForm(array $form, FormStateinterface $form_state) {
|
||||||
|
$config = $this->config(static::SETTINGS);
|
||||||
|
|
||||||
|
$form['allow_peer_role_assignment'] = [
|
||||||
|
'#type' => 'checkbox',
|
||||||
|
'#title' => $this->t('Allow peer role assignment'),
|
||||||
|
'#description' => $this->t('Allow users with the Account Admin role to assign/revoke the Account Admin role.'),
|
||||||
|
'#default_value' => $config->get('allow_peer_role_assignment'),
|
||||||
|
];
|
||||||
|
|
||||||
|
return parent::buildForm($form, $form_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||||
|
$this->configFactory->getEditable(static::SETTINGS)
|
||||||
|
->set('allow_peer_role_assignment', $form_state->getValue('allow_peer_role_assignment'))
|
||||||
|
->save();
|
||||||
|
|
||||||
|
// Invalidate the user_role:farm_account_admin cache tag.
|
||||||
|
$this->cacheTagsInvalidator->invalidateTags(['user_role:farm_account_admin']);
|
||||||
|
|
||||||
|
parent::submitForm($form, $form_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Drupal\Tests\farm_role_account_admin\Functional;
|
||||||
|
|
||||||
|
use Drupal\Tests\farm_test\Functional\FarmBrowserTestBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests access to user 1.
|
||||||
|
*
|
||||||
|
* @group farm
|
||||||
|
*/
|
||||||
|
class UserAccessTest extends FarmBrowserTestBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected static $modules = [
|
||||||
|
'farm_role_account_admin',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test user 1 access.
|
||||||
|
*/
|
||||||
|
public function testUser1Access() {
|
||||||
|
|
||||||
|
// Create and login a user with farm_account_admin role.
|
||||||
|
$user = $this->createUser();
|
||||||
|
$user->addRole('farm_account_admin');
|
||||||
|
$user->save();
|
||||||
|
$this->drupalLogin($user);
|
||||||
|
|
||||||
|
// Confirm that the user cannot access user 1.
|
||||||
|
$this->drupalGet('user/1');
|
||||||
|
$this->assertSession()->statusCodeEquals(403);
|
||||||
|
$this->drupalGet('user/1/edit');
|
||||||
|
$this->assertSession()->statusCodeEquals(403);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Drupal\Tests\farm_role_account_admin\Kernel;
|
||||||
|
|
||||||
|
use Drupal\KernelTests\KernelTestBase;
|
||||||
|
use Drupal\Tests\user\Traits\UserCreationTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for Account Admin role permissions.
|
||||||
|
*
|
||||||
|
* @group farm
|
||||||
|
*/
|
||||||
|
class AccountAdminPermissionsTest extends KernelTestBase {
|
||||||
|
|
||||||
|
use UserCreationTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected static $modules = [
|
||||||
|
'farm_role',
|
||||||
|
'farm_role_account_admin',
|
||||||
|
'farm_role_roles',
|
||||||
|
'farm_settings',
|
||||||
|
'role_delegation',
|
||||||
|
'system',
|
||||||
|
'user',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function setUp():void {
|
||||||
|
parent::setUp();
|
||||||
|
$this->installEntitySchema('user');
|
||||||
|
$this->installSchema('system', ['sequences']);
|
||||||
|
$this->installConfig(['farm_role_account_admin', 'farm_role_roles']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that the Account Admin role gets appropriate permissions.
|
||||||
|
*/
|
||||||
|
public function testAccountAdminPermissions() {
|
||||||
|
|
||||||
|
// Create a user.
|
||||||
|
$user = $this->setUpCurrentUser([], [], FALSE);
|
||||||
|
|
||||||
|
// List Account Admin permissions.
|
||||||
|
$account_admin_permissions = [
|
||||||
|
'administer farm settings',
|
||||||
|
'administer users',
|
||||||
|
'assign farm_manager role',
|
||||||
|
'assign farm_worker role',
|
||||||
|
'assign farm_viewer role',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Ensure the user does not have permissions.
|
||||||
|
foreach ($account_admin_permissions as $permission) {
|
||||||
|
$this->assertFalse($user->hasPermission($permission));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add Account Admin role.
|
||||||
|
$user->addRole('farm_account_admin');
|
||||||
|
|
||||||
|
// Ensure the user has permissions.
|
||||||
|
foreach ($account_admin_permissions as $permission) {
|
||||||
|
$this->assertTrue($user->hasPermission($permission));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the user does not have the "assign farm_account_admin role"
|
||||||
|
// permission.
|
||||||
|
$this->assertFalse($user->hasPermission('assign farm_account_admin role'));
|
||||||
|
|
||||||
|
// Enable the allow_peer_role_assignment setting.
|
||||||
|
$settings = \Drupal::configFactory()->getEditable('farm_role_account_admin.settings');
|
||||||
|
$settings->set('allow_peer_role_assignment', TRUE);
|
||||||
|
$settings->save();
|
||||||
|
|
||||||
|
// Rebuild the container so the configuration change takes effect.
|
||||||
|
$kernel = \Drupal::service('kernel');
|
||||||
|
$kernel->invalidateContainer();
|
||||||
|
$kernel->rebuildContainer();
|
||||||
|
|
||||||
|
// Ensure the user has the "assign farm_account_admin role" permission.
|
||||||
|
$this->assertTrue($user->hasPermission('assign farm_account_admin role'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue