Skip to content

Commit

Permalink
Add RestrictedDispatcherWithVoter
Browse files Browse the repository at this point in the history
  • Loading branch information
olvlvl committed Apr 26, 2022
1 parent f5907cb commit f6c570d
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 0 deletions.
28 changes: 28 additions & 0 deletions lib/PermissionNotGranted.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

/*
* This file is part of the ICanBoogie package.
*
* (c) Olivier Laviale <olivier.laviale@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace ICanBoogie\MessageBus;

use Throwable;

class PermissionNotGranted extends \Exception implements Exception
{
/**
* @param Context $context
*/
public function __construct(
public object $dispatched_message,
public Context $context,
?Throwable $previous = null
) {
parent::__construct("Permission not granted for message: " . $dispatched_message::class, 0, $previous);
}
}
20 changes: 20 additions & 0 deletions lib/RestrictedDispatcher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

/*
* This file is part of the ICanBoogie package.
*
* (c) Olivier Laviale <olivier.laviale@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace ICanBoogie\MessageBus;

interface RestrictedDispatcher
{
/**
* @throws PermissionNotGranted
*/
public function dispatch(object $message, Context $context): mixed;
}
34 changes: 34 additions & 0 deletions lib/RestrictedDispatcherWithVoter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

/*
* This file is part of the ICanBoogie package.
*
* (c) Olivier Laviale <olivier.laviale@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace ICanBoogie\MessageBus;

/**
* A dispatcher with a voter, preferably one such as {@link VoterWithPermissions}.
*/
final class RestrictedDispatcherWithVoter implements RestrictedDispatcher
{
public function __construct(
private Dispatcher $innerDispatcher,
private Voter $voter,
) {
}

/**
* @throws PermissionNotGranted
*/
public function dispatch(object $message, Context $context): mixed
{
$this->voter->isGranted($message, $context) or throw new PermissionNotGranted($message, $context);

return $this->innerDispatcher->dispatch($message);
}
}
84 changes: 84 additions & 0 deletions tests/RestrictedDispatcherWithVoterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

/*
* This file is part of the ICanBoogie package.
*
* (c) Olivier Laviale <olivier.laviale@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace ICanBoogie\MessageBus;

use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;

use function uniqid;

final class RestrictedDispatcherWithVoterTest extends TestCase
{
use ProphecyTrait;

/**
* @var ObjectProphecy<Dispatcher>
*/
private ObjectProphecy $innerDispatcher;

/**
* @var ObjectProphecy<Voter>
*/
private ObjectProphecy $voter;
private Context $context;
private object $message;

protected function setUp(): void
{
parent::setUp();

$this->innerDispatcher = $this->prophesize(Dispatcher::class);
$this->voter = $this->prophesize(Voter::class);
$this->context = new Context();
$this->message = new class () {
};
}

public function testVoterFalse(): void
{
$this->voter->isGranted($this->message, $this->context)
->willReturn(false);
$this->innerDispatcher->dispatch(Argument::any())
->shouldNotBeCalled();

$this->expectException(PermissionNotGranted::class);

$this->makeSTU()->dispatch($this->message, $this->context);
}

public function testVoterTrue(): void
{
$result = uniqid();

$this->voter->isGranted($this->message, $this->context)
->willReturn(false);
$this->innerDispatcher->dispatch($this->message)
->willReturn($result);

$this->expectException(PermissionNotGranted::class);

$this->assertSame(
$result,
$this->makeSTU()->dispatch($this->message, $this->context)
);
}

private function makeSTU(): RestrictedDispatcher
{
return new RestrictedDispatcherWithVoter(
$this->innerDispatcher->reveal(),
$this->voter->reveal(),
);
}
}

0 comments on commit f6c570d

Please sign in to comment.