From 65797b61a06769892b9bda7cd660acebc86aab6f Mon Sep 17 00:00:00 2001
From: Alejandro Celaya <alejandro@alejandrocelaya.com>
Date: Sun, 3 Jan 2021 14:03:10 +0100
Subject: [PATCH] Applied API role specs to single short URL deletion

---
 .../src/Service/ShortUrl/DeleteShortUrlService.php   | 10 +++++++---
 .../ShortUrl/DeleteShortUrlServiceInterface.php      |  7 ++++++-
 .../src/Action/ShortUrl/DeleteShortUrlAction.php     |  6 +++++-
 .../Action/ShortUrl/DeleteShortUrlActionTest.php     | 12 ++++++++----
 4 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/module/Core/src/Service/ShortUrl/DeleteShortUrlService.php b/module/Core/src/Service/ShortUrl/DeleteShortUrlService.php
index 35a540da..07af448d 100644
--- a/module/Core/src/Service/ShortUrl/DeleteShortUrlService.php
+++ b/module/Core/src/Service/ShortUrl/DeleteShortUrlService.php
@@ -9,6 +9,7 @@ use Shlinkio\Shlink\Core\Entity\ShortUrl;
 use Shlinkio\Shlink\Core\Exception;
 use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier;
 use Shlinkio\Shlink\Core\Options\DeleteShortUrlsOptions;
+use Shlinkio\Shlink\Rest\Entity\ApiKey;
 
 class DeleteShortUrlService implements DeleteShortUrlServiceInterface
 {
@@ -30,9 +31,12 @@ class DeleteShortUrlService implements DeleteShortUrlServiceInterface
      * @throws Exception\ShortUrlNotFoundException
      * @throws Exception\DeleteShortUrlException
      */
-    public function deleteByShortCode(ShortUrlIdentifier $identifier, bool $ignoreThreshold = false): void
-    {
-        $shortUrl = $this->urlResolver->resolveShortUrl($identifier);
+    public function deleteByShortCode(
+        ShortUrlIdentifier $identifier,
+        bool $ignoreThreshold = false,
+        ?ApiKey $apiKey = null
+    ): void {
+        $shortUrl = $this->urlResolver->resolveShortUrl($identifier, $apiKey);
         if (! $ignoreThreshold && $this->isThresholdReached($shortUrl)) {
             throw Exception\DeleteShortUrlException::fromVisitsThreshold(
                 $this->deleteShortUrlsOptions->getVisitsThreshold(),
diff --git a/module/Core/src/Service/ShortUrl/DeleteShortUrlServiceInterface.php b/module/Core/src/Service/ShortUrl/DeleteShortUrlServiceInterface.php
index 4759bf24..b1f01839 100644
--- a/module/Core/src/Service/ShortUrl/DeleteShortUrlServiceInterface.php
+++ b/module/Core/src/Service/ShortUrl/DeleteShortUrlServiceInterface.php
@@ -6,6 +6,7 @@ namespace Shlinkio\Shlink\Core\Service\ShortUrl;
 
 use Shlinkio\Shlink\Core\Exception;
 use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier;
+use Shlinkio\Shlink\Rest\Entity\ApiKey;
 
 interface DeleteShortUrlServiceInterface
 {
@@ -13,5 +14,9 @@ interface DeleteShortUrlServiceInterface
      * @throws Exception\ShortUrlNotFoundException
      * @throws Exception\DeleteShortUrlException
      */
-    public function deleteByShortCode(ShortUrlIdentifier $identifier, bool $ignoreThreshold = false): void;
+    public function deleteByShortCode(
+        ShortUrlIdentifier $identifier,
+        bool $ignoreThreshold = false,
+        ?ApiKey $apiKey = null
+    ): void;
 }
diff --git a/module/Rest/src/Action/ShortUrl/DeleteShortUrlAction.php b/module/Rest/src/Action/ShortUrl/DeleteShortUrlAction.php
index bd5b487e..73eaa6ee 100644
--- a/module/Rest/src/Action/ShortUrl/DeleteShortUrlAction.php
+++ b/module/Rest/src/Action/ShortUrl/DeleteShortUrlAction.php
@@ -10,6 +10,7 @@ use Psr\Http\Message\ServerRequestInterface;
 use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier;
 use Shlinkio\Shlink\Core\Service\ShortUrl\DeleteShortUrlServiceInterface;
 use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
+use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
 
 class DeleteShortUrlAction extends AbstractRestAction
 {
@@ -26,7 +27,10 @@ class DeleteShortUrlAction extends AbstractRestAction
     public function handle(ServerRequestInterface $request): ResponseInterface
     {
         $identifier = ShortUrlIdentifier::fromApiRequest($request);
-        $this->deleteShortUrlService->deleteByShortCode($identifier);
+        $apiKey = AuthenticationMiddleware::apiKeyFromRequest($request);
+
+        $this->deleteShortUrlService->deleteByShortCode($identifier, false, $apiKey);
+
         return new EmptyResponse();
     }
 }
diff --git a/module/Rest/test/Action/ShortUrl/DeleteShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/DeleteShortUrlActionTest.php
index 6f724c4e..9be06756 100644
--- a/module/Rest/test/Action/ShortUrl/DeleteShortUrlActionTest.php
+++ b/module/Rest/test/Action/ShortUrl/DeleteShortUrlActionTest.php
@@ -4,13 +4,14 @@ declare(strict_types=1);
 
 namespace ShlinkioTest\Shlink\Rest\Action\ShortUrl;
 
-use Laminas\Diactoros\ServerRequest;
+use Laminas\Diactoros\ServerRequestFactory;
 use PHPUnit\Framework\TestCase;
 use Prophecy\Argument;
 use Prophecy\PhpUnit\ProphecyTrait;
 use Prophecy\Prophecy\ObjectProphecy;
 use Shlinkio\Shlink\Core\Service\ShortUrl\DeleteShortUrlServiceInterface;
 use Shlinkio\Shlink\Rest\Action\ShortUrl\DeleteShortUrlAction;
+use Shlinkio\Shlink\Rest\Entity\ApiKey;
 
 class DeleteShortUrlActionTest extends TestCase
 {
@@ -28,10 +29,13 @@ class DeleteShortUrlActionTest extends TestCase
     /** @test */
     public function emptyResponseIsReturnedIfProperlyDeleted(): void
     {
-        $deleteByShortCode = $this->service->deleteByShortCode(Argument::any())->will(function (): void {
-        });
+        $apiKey = new ApiKey();
+        $deleteByShortCode = $this->service->deleteByShortCode(Argument::any(), false, $apiKey)->will(
+            function (): void {
+            },
+        );
 
-        $resp = $this->action->handle(new ServerRequest());
+        $resp = $this->action->handle(ServerRequestFactory::fromGlobals()->withAttribute(ApiKey::class, $apiKey));
 
         self::assertEquals(204, $resp->getStatusCode());
         $deleteByShortCode->shouldHaveBeenCalledOnce();