-
Notifications
You must be signed in to change notification settings - Fork 127
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Issue #2593139: Add configure_permission annotation key for plugins.
- Loading branch information
Showing
14 changed files
with
377 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<?php | ||
/** | ||
* @file | ||
* Contains Drupal\rules\Core\Annotation\Condition. | ||
*/ | ||
|
||
namespace Drupal\rules\Core\Annotation; | ||
|
||
use Drupal\Core\Condition\Annotation\Condition as CoreConditionAnnotation; | ||
|
||
/** | ||
* Extension of the Condition annotation class. | ||
* | ||
* @Annotation | ||
* | ||
* This class adds a configuration access parameter to the Condition | ||
* annotation. | ||
*/ | ||
class Condition extends CoreConditionAnnotation { | ||
|
||
/** | ||
* The permissions allowed to access the configuration UI for this plugin. | ||
* | ||
* @var string[] | ||
* Array of permission strings as declared in a *.permissions.yml file. If | ||
* any one of these permissions apply for the relevant user, we allow access. | ||
* | ||
* The key should be used as follows. Note that we add a space between "@" | ||
* and "Condition", since we do not want to trigger the annotation parser | ||
* here; you should remove that space in your actual annotation: | ||
* | ||
* @ Condition( | ||
* id = "my_module_user_is_blocked", | ||
* label = @Translation("My User is blocked"), | ||
* category = @Translation("User"), | ||
* context = { | ||
* "user" = @ContextDefinition("entity:user", | ||
* label = @Translation("User") | ||
* ), | ||
* configure_permissions = { | ||
* "administer users", | ||
* "block users" | ||
* } | ||
* } | ||
* ) | ||
*/ | ||
public $configure_permissions; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<?php | ||
/** | ||
* @file | ||
* Contains \Drupal\rules\Core\ConfigurationAccessControlInterface. | ||
*/ | ||
|
||
namespace Drupal\rules\Core; | ||
|
||
use Drupal\Core\Session\AccountInterface; | ||
|
||
/** | ||
* Defines a configuration permission control interface. | ||
* | ||
* @see \Drupal\rules\Core\ConfigurationAccessControlTrait. | ||
*/ | ||
interface ConfigurationAccessControlInterface { | ||
|
||
/** | ||
* Check configuration access. | ||
* | ||
* @param AccountInterface $account | ||
* (optional) The user for which to check access, or NULL to check access | ||
* for the current user. Defaults to NULL. | ||
* @param bool $return_as_object | ||
* (optional) Defaults to FALSE. | ||
* | ||
* @return bool|\Drupal\Core\Access\AccessResultInterface | ||
* The access result. Returns a boolean if $return_as_object is FALSE (this | ||
* is the default) and otherwise an AccessResultInterface object. | ||
* When a boolean is returned, the result of AccessInterface::isAllowed() is | ||
* returned, i.e. TRUE means access is explicitly allowed, FALSE means | ||
* access is either explicitly forbidden or "no opinion". | ||
*/ | ||
public function checkConfigurationAccess(AccountInterface $account = NULL, $return_as_object = FALSE); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
<?php | ||
|
||
/** | ||
* @file | ||
* Contains \Drupal\rules\Core\ConfigurationAccessControlTrait. | ||
*/ | ||
|
||
namespace Drupal\rules\Core; | ||
|
||
use Drupal\Core\Access\AccessResult; | ||
use Drupal\Core\Session\AccountInterface; | ||
|
||
/** | ||
* Implements access related functions for plugins. | ||
*/ | ||
trait ConfigurationAccessControlTrait { | ||
|
||
/** | ||
* Checks configuration permission. | ||
* | ||
* @param AccountInterface $account | ||
* (optional) The user for which to check access, or NULL to check access | ||
* for the current user. Defaults to NULL. | ||
* @param bool $return_as_object | ||
* (optional) Defaults to FALSE. | ||
* | ||
* @return bool|\Drupal\Core\Access\AccessResultInterface | ||
* The access result. Returns a boolean if $return_as_object is FALSE (this | ||
* is the default) and otherwise an AccessResultInterface object. | ||
* When a boolean is returned, the result of AccessInterface::isAllowed() is | ||
* returned, i.e. TRUE means access is explicitly allowed, FALSE means | ||
* access is either explicitly forbidden or "no opinion". | ||
*/ | ||
public function checkConfigurationAccess(AccountInterface $account = NULL, $return_as_object = FALSE) { | ||
if (!$account) { | ||
$account = \Drupal::currentUser(); | ||
} | ||
// We treat these as our "super-user" accesses. We let the reaction | ||
// rule and component permissions control the main admin UI. | ||
$admin_perms = [ | ||
'administer rules', | ||
'bypass rules access', | ||
]; | ||
|
||
$access = FALSE; | ||
foreach ($admin_perms as $perm) { | ||
if ($account->hasPermission($perm)) { | ||
$access = TRUE; | ||
break; | ||
} | ||
} | ||
|
||
if (!$access) { | ||
// See if the plugin has a configuration_access annotation. | ||
$definition = $this->getPluginDefinition(); | ||
if (!empty($definition['configure_permissions']) && is_array($definition['configure_permissions'])) { | ||
foreach ($definition['configure_permissions'] as $perm) { | ||
if ($account->hasPermission($perm)) { | ||
$access = TRUE; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
if ($return_as_object) { | ||
return $access ? AccessResult::allowed() : AccessResult::neutral(); | ||
} | ||
return $access; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
<?php | ||
/** | ||
* @file | ||
* Contains Drupal\Tests\rules\Integration\Action\RulesActionAccessTest. | ||
*/ | ||
|
||
namespace Drupal\Tests\rules\Integration\Action; | ||
|
||
use Drupal\Tests\rules\Integration\RulesIntegrationTestBase; | ||
use Drupal\Core\Session\AccountInterface; | ||
use Prophecy\Argument; | ||
|
||
/** | ||
* Tests configuration access control for Rules Actions. | ||
* | ||
* @group rules_actions | ||
*/ | ||
class RulesActionAccessTest extends RulesIntegrationTestBase { | ||
|
||
/** | ||
* Confirm that a condition plugin respects configure permission. | ||
*/ | ||
public function testHasConfigurationAccessInfo() { | ||
$plugin = $this->actionManager->createInstance('rules_test_string'); | ||
$definition = $plugin->getPluginDefinition(); | ||
$this->assertNotEmpty($definition['configure_permissions'], "Plugin has configuration permission info."); | ||
$perms = $definition['configure_permissions']; | ||
$this->assertTrue(is_array($perms), "configure_permissions is an array"); | ||
$this->assertContains("access test configuration", $perms, "Expected permission found in configure_permissions."); | ||
|
||
// Now see if the permission is actually used. | ||
$user_with_perm = $this->prophesize(AccountInterface::class); | ||
$user_with_perm | ||
->hasPermission("access test configuration") | ||
->willReturn(TRUE) | ||
->shouldBeCalledTimes(2); | ||
$user_with_perm | ||
->hasPermission(Argument::type('string')) | ||
->willReturn(FALSE); | ||
|
||
$this->container->set('current_user', $user_with_perm->reveal()); | ||
$this->assertTrue($plugin->checkConfigurationAccess(), "User with permission has configuration access."); | ||
|
||
$object_result = $plugin->checkConfigurationAccess($user_with_perm->reveal(), TRUE); | ||
$this->assertTrue($object_result->isAllowed(), "AccessResult in allowed state if an object is requested."); | ||
|
||
$user_without_perm = $this->prophesize(AccountInterface::class); | ||
$user_without_perm | ||
->hasPermission("access test configuration") | ||
->willReturn(FALSE) | ||
->shouldBeCalledTimes(2); | ||
$user_without_perm | ||
->hasPermission(Argument::type('string')) | ||
->willReturn(FALSE); | ||
|
||
$this->assertFalse($plugin->checkConfigurationAccess($user_without_perm->reveal()), | ||
"User without permission does not have configuration access."); | ||
$object_result = $plugin->checkConfigurationAccess($user_without_perm->reveal(), TRUE); | ||
$this->assertTrue($object_result->isNeutral(), "an AccessResultNeutral object is returned on not allowed if an object is requested."); | ||
|
||
} | ||
|
||
} |
Oops, something went wrong.