Skip to content
Snippets Groups Projects
Commit 5a5e5002 authored by Kristiaan Van den Eynde's avatar Kristiaan Van den Eynde
Browse files

Issue #3450293 by kristiaanvandeneynde: Set up GitLab CI

parent 8d3fbc0b
No related branches found
No related tags found
1 merge request!7Resolve #3450293 "Set up gitlab"
Pipeline #183961 passed with warnings
......@@ -27,24 +27,3 @@ and against individual memberships (group_individual).
The Domain module would be able to define permissions specifically for certain
domains and Commerce would be able to do the same on a per-store basis.
Core integration
Sadly, core still has permission checks littered all over the place rather than
in a central service. The silver lining being that most permission checks use
AccountInterface::hasPermission(). If we are somehow able to swap out these
classes, then we could polyfill this system in core and make full PBAC easy to
achieve.
There is currently no budget to investigate this avenue, but any sponsorships
can be directed at hello@factorial.io and we can look into making the
permission layer in core as awesome as this module makes it for contrib.
To give you an example of how powerful this module can be: Because of the
centralized permission calculator and checker, we have a cache context in Group
that varies pages by your group permissions, just like the user.permissions
cache context in core. However, in Group, you can alter someone's permissions
without breaking said cache context. In core this is simply not possible
because the permission layer is not centralized. Altering someone's core
permissions would currently break the user.permissions cache context and lead
to security issues.
......@@ -24,5 +24,8 @@
"require": {
"drupal/core": "^9.5 || ^10",
"drupal/variationcache": "^1.0"
},
"require-dev": {
"jangregor/phpstan-prophecy": "^1.0"
}
}
......@@ -7,6 +7,7 @@ use Drupal\Core\Session\AccountInterface;
/**
* Defines an interface to alter the final calculated permissions.
*/
// phpcs:ignore
interface PermissionCalculatorAlterInterfaceV2 {
/**
......
......@@ -28,6 +28,7 @@ class CalculatedPermissionsTest extends UnitTestCase {
$item_a = new CalculatedPermissionsItem('scope_a', 'foo', ['baz']);
$item_b = new CalculatedPermissionsItem('scope_b', 1, ['bob', 'charlie']);
/** @var \Prophecy\Prophecy\ObjectProphecy<\Drupal\flexible_permissions\CalculatedPermissionsInterface> $calculated_permissions */
$calculated_permissions = $this->prophesize(CalculatedPermissionsInterface::class);
$calculated_permissions->getItems()->willReturn([$item_a, $item_b]);
$calculated_permissions->getCacheTags()->willReturn(['24']);
......
......@@ -32,9 +32,11 @@ class ChainPermissionCalculatorTest extends UnitTestCase {
public function setUp(): void {
parent::setUp();
/** @var \Prophecy\Prophecy\ObjectProphecy<\Drupal\Core\Cache\Context\CacheContextsManager> $cache_context_manager */
$cache_context_manager = $this->prophesize(CacheContextsManager::class);
$cache_context_manager->assertValidTokens(Argument::any())->willReturn(TRUE);
/** @var \Prophecy\Prophecy\ObjectProphecy<\Symfony\Component\DependencyInjection\ContainerInterface> $container */
$container = $this->prophesize(ContainerInterface::class);
$container->get('cache_contexts_manager')->willReturn($cache_context_manager->reveal());
\Drupal::setContainer($container->reveal());
......@@ -88,6 +90,7 @@ class ChainPermissionCalculatorTest extends UnitTestCase {
$chain_calculator = $this->setUpChainCalculator();
$chain_calculator->addCalculator($calculator);
/** @var \Drupal\flexible_permissions\RefinableCalculatedPermissionsInterface $calculator_permissions */
$calculator_permissions = $calculator->calculatePermissions($account, 'bar');
$calculator_permissions->addCacheTags(['flexible_permissions']);
$this->assertEquals(new CalculatedPermissions($calculator_permissions), $chain_calculator->calculatePermissions($account, 'bar'));
......@@ -125,6 +128,7 @@ class ChainPermissionCalculatorTest extends UnitTestCase {
$chain_calculator = $this->setUpChainCalculator();
$chain_calculator->addCalculator($calculator);
/** @var \Drupal\flexible_permissions\RefinableCalculatedPermissionsInterface $calculator_permissions */
$calculator_permissions = $calculator->calculatePermissions($account, 'anything');
$calculator_permissions->addCacheTags(['flexible_permissions']);
$calculated_permissions = $chain_calculator->calculatePermissions($account, 'anything');
......@@ -176,7 +180,7 @@ class ChainPermissionCalculatorTest extends UnitTestCase {
}
/**
* Tests if the account switcher switches properly when user cache context is present.
* Tests if the account switcher switches when user cache context is present.
*
* @covers ::calculatePermissions
* @dataProvider accountSwitcherProvider
......@@ -184,6 +188,7 @@ class ChainPermissionCalculatorTest extends UnitTestCase {
public function testAccountSwitcher($has_user_context) {
$account = $this->prophesize(AccountInterface::class)->reveal();
/** @var \Prophecy\Prophecy\ObjectProphecy<\Drupal\Core\Session\AccountSwitcherInterface> $account_switcher */
$account_switcher = $this->prophesize(AccountSwitcherInterface::class);
if ($has_user_context) {
$account_switcher->switchTo($account)->shouldBeCalledTimes(1);
......@@ -215,7 +220,7 @@ class ChainPermissionCalculatorTest extends UnitTestCase {
}
/**
* Tests if the account switcher switches properly when user cache context is present.
* Tests the caching of the calculated permissions.
*
* @covers ::calculatePermissions
* @dataProvider cachingProvider
......@@ -229,12 +234,15 @@ class ChainPermissionCalculatorTest extends UnitTestCase {
$scope = 'bar';
$bar_calculator = new BarScopeCalculator();
/** @var \Drupal\flexible_permissions\RefinableCalculatedPermissionsInterface $bar_permissions */
$bar_permissions = $bar_calculator->calculatePermissions($account, $scope);
$bar_permissions->addCacheTags(['flexible_permissions']);
$bar_permissions->disableBuildMode();
$none_refinable_bar_permissions = new CalculatedPermissions($bar_permissions);
/** @var \Prophecy\Prophecy\ObjectProphecy<\Drupal\variationcache\Cache\VariationCacheInterface> $cache_static */
$cache_static = $this->prophesize(VariationCacheInterface::class);
/** @var \Prophecy\Prophecy\ObjectProphecy<\Drupal\variationcache\Cache\VariationCacheInterface> $cache_db */
$cache_db = $this->prophesize(VariationCacheInterface::class);
if (!$static_cache_hit) {
if (!$db_cache_hit) {
......@@ -288,9 +296,10 @@ class ChainPermissionCalculatorTest extends UnitTestCase {
VariationCacheInterface $variation_cache = NULL,
VariationCacheInterface $variation_cache_static = NULL,
CacheBackendInterface $cache_static = NULL,
AccountSwitcherInterface $account_switcher = NULL
AccountSwitcherInterface $account_switcher = NULL,
) {
if (!isset($variation_cache)) {
/** @var \Prophecy\Prophecy\ObjectProphecy<\Drupal\variationcache\Cache\VariationCacheInterface> $variation_cache */
$variation_cache = $this->prophesize(VariationCacheInterface::class);
$variation_cache->get(Argument::cetera())->willReturn(FALSE);
$variation_cache->set(Argument::cetera())->willReturn(NULL);
......@@ -298,6 +307,7 @@ class ChainPermissionCalculatorTest extends UnitTestCase {
}
if (!isset($variation_cache_static)) {
/** @var \Prophecy\Prophecy\ObjectProphecy<\Drupal\variationcache\Cache\VariationCacheInterface> $variation_cache_static */
$variation_cache_static = $this->prophesize(VariationCacheInterface::class);
$variation_cache_static->get(Argument::cetera())->willReturn(FALSE);
$variation_cache_static->set(Argument::cetera())->willReturn(NULL);
......@@ -305,6 +315,7 @@ class ChainPermissionCalculatorTest extends UnitTestCase {
}
if (!isset($cache_static)) {
/** @var \Prophecy\Prophecy\ObjectProphecy<\Drupal\Core\Cache\CacheBackendInterface> $cache_static */
$cache_static = $this->prophesize(CacheBackendInterface::class);
$cache_static->get(Argument::cetera())->willReturn(FALSE);
$cache_static->set(Argument::cetera())->willReturn(NULL);
......@@ -334,6 +345,7 @@ class FooScopeCalculator extends PermissionCalculatorBase {
* {@inheritdoc}
*/
public function calculatePermissions(AccountInterface $account, $scope) {
/** @var \Drupal\flexible_permissions\RefinableCalculatedPermissionsInterface $calculated_permissions */
$calculated_permissions = parent::calculatePermissions($account, $scope);
return $calculated_permissions->addItem(new CalculatedPermissionsItem('foo', 1, ['foo', 'bar'], TRUE));
}
......@@ -356,6 +368,7 @@ class BarScopeCalculator extends PermissionCalculatorBase {
* {@inheritdoc}
*/
public function calculatePermissions(AccountInterface $account, $scope) {
/** @var \Drupal\flexible_permissions\RefinableCalculatedPermissionsInterface $calculated_permissions */
$calculated_permissions = parent::calculatePermissions($account, $scope);
return $calculated_permissions->addItem(new CalculatedPermissionsItem('bar', 1, ['foo', 'bar']));
}
......
......@@ -41,7 +41,6 @@ class RefinableCalculatedPermissionsTest extends UnitTestCase {
$this->assertTrue($calculated_permissions->getItem($scope, 'foo')->isAdmin(), 'Merging in a calculated permissions item with admin rights flags the result as having admin rights.');
}
/**
* Tests the overwriting of a calculated permissions item.
*
......@@ -142,8 +141,11 @@ class RefinableCalculatedPermissionsTest extends UnitTestCase {
public function testMerge() {
$scope = 'some_scope';
/** @var \Prophecy\Prophecy\ObjectProphecy<\Drupal\Core\Cache\Context\CacheContextsManager> $cache_context_manager */
$cache_context_manager = $this->prophesize(CacheContextsManager::class);
$cache_context_manager->assertValidTokens(Argument::any())->willReturn(TRUE);
/** @var \Prophecy\Prophecy\ObjectProphecy<\Symfony\Component\DependencyInjection\ContainerInterface> $container */
$container = $this->prophesize(ContainerInterface::class);
$container->get('cache_contexts_manager')->willReturn($cache_context_manager->reveal());
\Drupal::setContainer($container->reveal());
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment