Ensured delete/rename tags cannot be done with non-admin API keys

This commit is contained in:
Alejandro Celaya
2021-01-06 17:31:49 +01:00
parent b5710f87e2
commit a8b68f07b5
9 changed files with 177 additions and 29 deletions

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Core\Exception;
use Fig\Http\Message\StatusCodeInterface;
use Mezzio\ProblemDetails\Exception\CommonProblemDetailsExceptionTrait;
use Mezzio\ProblemDetails\Exception\ProblemDetailsExceptionInterface;
class ForbiddenTagOperationException extends DomainException implements ProblemDetailsExceptionInterface
{
use CommonProblemDetailsExceptionTrait;
private const TITLE = 'Forbidden tag operation';
private const TYPE = 'FORBIDDEN_OPERATION';
public static function forDeletion(): self
{
return self::createWithMessage('You are not allowed to delete tags');
}
public static function forRenaming(): self
{
return self::createWithMessage('You are not allowed to rename tags');
}
private static function createWithMessage(string $message): self
{
$e = new self($message);
$e->detail = $message;
$e->title = self::TITLE;
$e->type = self::TYPE;
$e->status = StatusCodeInterface::STATUS_FORBIDDEN;
return $e;
}
}

View File

@@ -8,6 +8,7 @@ use Doctrine\Common\Collections\Collection;
use Doctrine\ORM;
use Happyr\DoctrineSpecification\Spec;
use Shlinkio\Shlink\Core\Entity\Tag;
use Shlinkio\Shlink\Core\Exception\ForbiddenTagOperationException;
use Shlinkio\Shlink\Core\Exception\TagConflictException;
use Shlinkio\Shlink\Core\Exception\TagNotFoundException;
use Shlinkio\Shlink\Core\Repository\TagRepository;
@@ -56,9 +57,14 @@ class TagService implements TagServiceInterface
/**
* @param string[] $tagNames
* @throws ForbiddenTagOperationException
*/
public function deleteTags(array $tagNames): void
public function deleteTags(array $tagNames, ?ApiKey $apiKey = null): void
{
if ($apiKey !== null && ! $apiKey->isAdmin()) {
throw ForbiddenTagOperationException::forDeletion();
}
/** @var TagRepository $repo */
$repo = $this->em->getRepository(Tag::class);
$repo->deleteByName($tagNames);
@@ -82,9 +88,14 @@ class TagService implements TagServiceInterface
/**
* @throws TagNotFoundException
* @throws TagConflictException
* @throws ForbiddenTagOperationException
*/
public function renameTag(TagRenaming $renaming): Tag
public function renameTag(TagRenaming $renaming, ?ApiKey $apiKey = null): Tag
{
if ($apiKey !== null && ! $apiKey->isAdmin()) {
throw ForbiddenTagOperationException::forRenaming();
}
/** @var TagRepository $repo */
$repo = $this->em->getRepository(Tag::class);

View File

@@ -6,6 +6,7 @@ namespace Shlinkio\Shlink\Core\Tag;
use Doctrine\Common\Collections\Collection;
use Shlinkio\Shlink\Core\Entity\Tag;
use Shlinkio\Shlink\Core\Exception\ForbiddenTagOperationException;
use Shlinkio\Shlink\Core\Exception\TagConflictException;
use Shlinkio\Shlink\Core\Exception\TagNotFoundException;
use Shlinkio\Shlink\Core\Tag\Model\TagInfo;
@@ -26,8 +27,9 @@ interface TagServiceInterface
/**
* @param string[] $tagNames
* @throws ForbiddenTagOperationException
*/
public function deleteTags(array $tagNames): void;
public function deleteTags(array $tagNames, ?ApiKey $apiKey = null): void;
/**
* @deprecated
@@ -39,6 +41,7 @@ interface TagServiceInterface
/**
* @throws TagNotFoundException
* @throws TagConflictException
* @throws ForbiddenTagOperationException
*/
public function renameTag(TagRenaming $renaming): Tag;
public function renameTag(TagRenaming $renaming, ?ApiKey $apiKey = null): Tag;
}