check customer permissions on invoice api access (#5849)
This commit is contained in:
@@ -18,6 +18,7 @@ use FOS\RestBundle\Request\ParamFetcherInterface;
|
|||||||
use FOS\RestBundle\View\View;
|
use FOS\RestBundle\View\View;
|
||||||
use FOS\RestBundle\View\ViewHandlerInterface;
|
use FOS\RestBundle\View\ViewHandlerInterface;
|
||||||
use OpenApi\Attributes as OA;
|
use OpenApi\Attributes as OA;
|
||||||
|
use Symfony\Component\ExpressionLanguage\Expression;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||||
@@ -76,6 +77,9 @@ final class InvoiceController extends BaseApiController
|
|||||||
/** @var array<int> $customers */
|
/** @var array<int> $customers */
|
||||||
$customers = $paramFetcher->get('customers');
|
$customers = $paramFetcher->get('customers');
|
||||||
foreach ($customerRepository->findByIds(array_unique($customers)) as $customer) {
|
foreach ($customerRepository->findByIds(array_unique($customers)) as $customer) {
|
||||||
|
if (!$this->isGranted('access', $customer)) {
|
||||||
|
throw $this->createAccessDeniedException('Cannot access Customer: ' . $customer->getId());
|
||||||
|
}
|
||||||
$query->addCustomer($customer);
|
$query->addCustomer($customer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,6 +94,7 @@ final class InvoiceController extends BaseApiController
|
|||||||
* Fetch invoice
|
* Fetch invoice
|
||||||
*/
|
*/
|
||||||
#[IsGranted('view_invoice')]
|
#[IsGranted('view_invoice')]
|
||||||
|
#[IsGranted(new Expression("is_granted('access', subject.getCustomer())"), 'invoice')]
|
||||||
#[OA\Response(response: 200, description: 'Returns one invoice', content: new OA\JsonContent(ref: '#/components/schemas/Invoice'))]
|
#[OA\Response(response: 200, description: 'Returns one invoice', content: new OA\JsonContent(ref: '#/components/schemas/Invoice'))]
|
||||||
#[Route(methods: ['GET'], path: '/{id}', name: 'get_invoice', requirements: ['id' => '\d+'])]
|
#[Route(methods: ['GET'], path: '/{id}', name: 'get_invoice', requirements: ['id' => '\d+'])]
|
||||||
public function getAction(Invoice $invoice): Response
|
public function getAction(Invoice $invoice): Response
|
||||||
|
|||||||
@@ -9,8 +9,11 @@
|
|||||||
|
|
||||||
namespace App\Tests\API;
|
namespace App\Tests\API;
|
||||||
|
|
||||||
|
use App\Entity\Customer;
|
||||||
use App\Entity\Invoice;
|
use App\Entity\Invoice;
|
||||||
|
use App\Entity\Team;
|
||||||
use App\Entity\User;
|
use App\Entity\User;
|
||||||
|
use App\Repository\TeamRepository;
|
||||||
use App\Tests\DataFixtures\InvoiceFixtures;
|
use App\Tests\DataFixtures\InvoiceFixtures;
|
||||||
use PHPUnit\Framework\Attributes\Group;
|
use PHPUnit\Framework\Attributes\Group;
|
||||||
|
|
||||||
@@ -123,4 +126,59 @@ class InvoiceControllerTest extends APIControllerBaseTestCase
|
|||||||
{
|
{
|
||||||
$this->assertEntityNotFound(User::ROLE_USER, '/api/invoices/' . PHP_INT_MAX);
|
$this->assertEntityNotFound(User::ROLE_USER, '/api/invoices/' . PHP_INT_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testDownloadRespectsCustomerPermission(): void
|
||||||
|
{
|
||||||
|
$client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD);
|
||||||
|
|
||||||
|
$invoices = $this->importInvoiceFixtures(1, [Invoice::STATUS_NEW]);
|
||||||
|
$invoice = $invoices[0];
|
||||||
|
$customer = $invoice->getCustomer();
|
||||||
|
self::assertInstanceOf(Customer::class, $customer);
|
||||||
|
|
||||||
|
$this->assertAccessIsGranted($client, '/api/invoices/' . $invoice->getId());
|
||||||
|
|
||||||
|
$content = $client->getResponse()->getContent();
|
||||||
|
self::assertIsString($content);
|
||||||
|
$result = json_decode($content, true);
|
||||||
|
|
||||||
|
self::assertIsArray($result);
|
||||||
|
self::assertApiResponseTypeStructure('Invoice', $result);
|
||||||
|
|
||||||
|
$team = new Team('foo');
|
||||||
|
$team->addTeamlead($this->getUserByRole(User::ROLE_ADMIN));
|
||||||
|
$team->addCustomer($customer);
|
||||||
|
|
||||||
|
$em = $this->getEntityManager();
|
||||||
|
/** @var TeamRepository $repository */
|
||||||
|
$repository = $em->getRepository(Team::class);
|
||||||
|
$repository->saveTeam($team);
|
||||||
|
|
||||||
|
$this->assertApiAccessDenied($client, '/api/invoices/' . $invoice->getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCollectionRespectsCustomerPermission(): void
|
||||||
|
{
|
||||||
|
$client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD);
|
||||||
|
|
||||||
|
$invoices = $this->importInvoiceFixtures(1, [Invoice::STATUS_NEW]);
|
||||||
|
$invoice = $invoices[0];
|
||||||
|
$customer = $invoice->getCustomer();
|
||||||
|
self::assertInstanceOf(Customer::class, $customer);
|
||||||
|
|
||||||
|
$query = ['customers' => [$customer->getId()]];
|
||||||
|
$this->assertAccessIsGranted($client, '/api/invoices', 'GET', $query);
|
||||||
|
|
||||||
|
$team = new Team('foo');
|
||||||
|
$team->addTeamlead($this->getUserByRole(User::ROLE_ADMIN));
|
||||||
|
$team->addCustomer($customer);
|
||||||
|
|
||||||
|
$em = $this->getEntityManager();
|
||||||
|
/** @var TeamRepository $repository */
|
||||||
|
$repository = $em->getRepository(Team::class);
|
||||||
|
$repository->saveTeam($team);
|
||||||
|
|
||||||
|
$this->request($client, '/api/invoices', 'GET', $query);
|
||||||
|
$this->assertApiResponseAccessDenied($client->getResponse());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user