Applied API role specs to single short URL edition

This commit is contained in:
Alejandro Celaya 2021-01-03 16:41:44 +01:00
parent 65797b61a0
commit fff10ebee4
8 changed files with 59 additions and 25 deletions

View file

@ -134,17 +134,12 @@
"test:db:ms": "DB_DRIVER=mssql composer test:db:sqlite", "test:db:ms": "DB_DRIVER=mssql composer test:db:sqlite",
"test:api": "bin/test/run-api-tests.sh", "test:api": "bin/test/run-api-tests.sh",
"test:unit:pretty": "@php vendor/bin/phpunit --order-by=random --colors=always --coverage-html build/coverage-unit-html", "test:unit:pretty": "@php vendor/bin/phpunit --order-by=random --colors=always --coverage-html build/coverage-unit-html",
"infect": "infection --threads=4 --min-msi=80 --log-verbosity=default --only-covered", "infect:ci:base": "infection --threads=4 --log-verbosity=default --only-covered --skip-initial-tests",
"infect:ci:base": "@infect --skip-initial-tests", "infect:ci:unit": "@infect:ci:base --coverage=build/coverage-unit --min-msi=80",
"infect:ci:unit": "@infect:ci:base --coverage=build/coverage-unit", "infect:ci:db": "@infect:ci:base --coverage=build/coverage-db --min-msi=95 --configuration=infection-db.json",
"infect:ci:db": "@infect:ci:base --coverage=build/coverage-db --min-msi=95 --test-framework-options=--configuration=phpunit-db.xml", "infect:ci": "@parallel infect:ci:unit infect:ci:db",
"infect:ci": [
"@infect:ci:unit",
"@infect:ci:db"
],
"infect:test": [ "infect:test": [
"@test:unit:ci", "@parallel test:unit:ci test:db:sqlite:ci",
"@test:db:sqlite:ci",
"@infect:ci" "@infect:ci"
], ],
"clean:dev": "rm -f data/database.sqlite && rm -f config/params/generated_config.php" "clean:dev": "rm -f data/database.sqlite && rm -f config/params/generated_config.php"

23
infection-db.json Normal file
View file

@ -0,0 +1,23 @@
{
"source": {
"directories": [
"module/*/src"
]
},
"timeout": 5,
"logs": {
"text": "build/infection-db/infection-log.txt",
"summary": "build/infection-db/summary-log.txt",
"debug": "build/infection-db/debug-log.txt"
},
"tmpDir": "build/infection-db/temp",
"phpUnit": {
"configDir": "."
},
"testFrameworkOptions": "--configuration=phpunit-db.xml",
"mutators": {
"@default": true,
"IdenticalEqual": false,
"NotIdenticalNotEqual": false
}
}

View file

@ -6,11 +6,11 @@
}, },
"timeout": 5, "timeout": 5,
"logs": { "logs": {
"text": "build/infection/infection-log.txt", "text": "build/infection-unit/infection-log.txt",
"summary": "build/infection/summary-log.txt", "summary": "build/infection-unit/summary-log.txt",
"debug": "build/infection/debug-log.txt" "debug": "build/infection-unit/debug-log.txt"
}, },
"tmpDir": "build/infection/temp", "tmpDir": "build/infection-unit/temp",
"phpUnit": { "phpUnit": {
"configDir": "." "configDir": "."
}, },

View file

@ -69,13 +69,16 @@ class ShortUrlService implements ShortUrlServiceInterface
* @throws ShortUrlNotFoundException * @throws ShortUrlNotFoundException
* @throws InvalidUrlException * @throws InvalidUrlException
*/ */
public function updateMetadataByShortCode(ShortUrlIdentifier $identifier, ShortUrlEdit $shortUrlEdit): ShortUrl public function updateMetadataByShortCode(
{ ShortUrlIdentifier $identifier,
ShortUrlEdit $shortUrlEdit,
?ApiKey $apiKey = null
): ShortUrl {
if ($shortUrlEdit->hasLongUrl()) { if ($shortUrlEdit->hasLongUrl()) {
$this->urlValidator->validateUrl($shortUrlEdit->longUrl(), $shortUrlEdit->doValidateUrl()); $this->urlValidator->validateUrl($shortUrlEdit->longUrl(), $shortUrlEdit->doValidateUrl());
} }
$shortUrl = $this->urlResolver->resolveShortUrl($identifier); $shortUrl = $this->urlResolver->resolveShortUrl($identifier, $apiKey);
$shortUrl->update($shortUrlEdit); $shortUrl->update($shortUrlEdit);
$this->em->flush(); $this->em->flush();

View file

@ -30,5 +30,9 @@ interface ShortUrlServiceInterface
* @throws ShortUrlNotFoundException * @throws ShortUrlNotFoundException
* @throws InvalidUrlException * @throws InvalidUrlException
*/ */
public function updateMetadataByShortCode(ShortUrlIdentifier $identifier, ShortUrlEdit $shortUrlEdit): ShortUrl; public function updateMetadataByShortCode(
ShortUrlIdentifier $identifier,
ShortUrlEdit $shortUrlEdit,
?ApiKey $apiKey = null
): ShortUrl;
} }

View file

@ -20,6 +20,7 @@ use Shlinkio\Shlink\Core\Repository\ShortUrlRepository;
use Shlinkio\Shlink\Core\Service\ShortUrl\ShortUrlResolverInterface; use Shlinkio\Shlink\Core\Service\ShortUrl\ShortUrlResolverInterface;
use Shlinkio\Shlink\Core\Service\ShortUrlService; use Shlinkio\Shlink\Core\Service\ShortUrlService;
use Shlinkio\Shlink\Core\Util\UrlValidatorInterface; use Shlinkio\Shlink\Core\Util\UrlValidatorInterface;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
use function count; use function count;
@ -90,15 +91,19 @@ class ShortUrlServiceTest extends TestCase
*/ */
public function updateMetadataByShortCodeUpdatesProvidedData( public function updateMetadataByShortCodeUpdatesProvidedData(
int $expectedValidateCalls, int $expectedValidateCalls,
ShortUrlEdit $shortUrlEdit ShortUrlEdit $shortUrlEdit,
?ApiKey $apiKey
): void { ): void {
$originalLongUrl = 'originalLongUrl'; $originalLongUrl = 'originalLongUrl';
$shortUrl = new ShortUrl($originalLongUrl); $shortUrl = new ShortUrl($originalLongUrl);
$findShortUrl = $this->urlResolver->resolveShortUrl(new ShortUrlIdentifier('abc123'))->willReturn($shortUrl); $findShortUrl = $this->urlResolver->resolveShortUrl(
new ShortUrlIdentifier('abc123'),
$apiKey,
)->willReturn($shortUrl);
$flush = $this->em->flush()->willReturn(null); $flush = $this->em->flush()->willReturn(null);
$result = $this->service->updateMetadataByShortCode(new ShortUrlIdentifier('abc123'), $shortUrlEdit); $result = $this->service->updateMetadataByShortCode(new ShortUrlIdentifier('abc123'), $shortUrlEdit, $apiKey);
self::assertSame($shortUrl, $result); self::assertSame($shortUrl, $result);
self::assertEquals($shortUrlEdit->validSince(), $shortUrl->getValidSince()); self::assertEquals($shortUrlEdit->validSince(), $shortUrl->getValidSince());
@ -121,19 +126,19 @@ class ShortUrlServiceTest extends TestCase
'validUntil' => Chronos::parse('2017-01-05 00:00:00')->toAtomString(), 'validUntil' => Chronos::parse('2017-01-05 00:00:00')->toAtomString(),
'maxVisits' => 5, 'maxVisits' => 5,
], ],
)]; ), null];
yield 'long URL' => [1, ShortUrlEdit::fromRawData( yield 'long URL' => [1, ShortUrlEdit::fromRawData(
[ [
'validSince' => Chronos::parse('2017-01-01 00:00:00')->toAtomString(), 'validSince' => Chronos::parse('2017-01-01 00:00:00')->toAtomString(),
'maxVisits' => 10, 'maxVisits' => 10,
'longUrl' => 'modifiedLongUrl', 'longUrl' => 'modifiedLongUrl',
], ],
)]; ), new ApiKey()];
yield 'long URL with validation' => [1, ShortUrlEdit::fromRawData( yield 'long URL with validation' => [1, ShortUrlEdit::fromRawData(
[ [
'longUrl' => 'modifiedLongUrl', 'longUrl' => 'modifiedLongUrl',
'validateUrl' => true, 'validateUrl' => true,
], ],
)]; ), null];
} }
} }

View file

@ -11,6 +11,7 @@ use Shlinkio\Shlink\Core\Model\ShortUrlEdit;
use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier; use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier;
use Shlinkio\Shlink\Core\Service\ShortUrlServiceInterface; use Shlinkio\Shlink\Core\Service\ShortUrlServiceInterface;
use Shlinkio\Shlink\Rest\Action\AbstractRestAction; use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
class EditShortUrlAction extends AbstractRestAction class EditShortUrlAction extends AbstractRestAction
{ {
@ -28,8 +29,9 @@ class EditShortUrlAction extends AbstractRestAction
{ {
$shortUrlEdit = ShortUrlEdit::fromRawData((array) $request->getParsedBody()); $shortUrlEdit = ShortUrlEdit::fromRawData((array) $request->getParsedBody());
$identifier = ShortUrlIdentifier::fromApiRequest($request); $identifier = ShortUrlIdentifier::fromApiRequest($request);
$apiKey = AuthenticationMiddleware::apiKeyFromRequest($request);
$this->shortUrlService->updateMetadataByShortCode($identifier, $shortUrlEdit); $this->shortUrlService->updateMetadataByShortCode($identifier, $shortUrlEdit, $apiKey);
return new EmptyResponse(); return new EmptyResponse();
} }
} }

View file

@ -13,6 +13,7 @@ use Shlinkio\Shlink\Core\Entity\ShortUrl;
use Shlinkio\Shlink\Core\Exception\ValidationException; use Shlinkio\Shlink\Core\Exception\ValidationException;
use Shlinkio\Shlink\Core\Service\ShortUrlServiceInterface; use Shlinkio\Shlink\Core\Service\ShortUrlServiceInterface;
use Shlinkio\Shlink\Rest\Action\ShortUrl\EditShortUrlAction; use Shlinkio\Shlink\Rest\Action\ShortUrl\EditShortUrlAction;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
class EditShortUrlActionTest extends TestCase class EditShortUrlActionTest extends TestCase
{ {
@ -43,6 +44,7 @@ class EditShortUrlActionTest extends TestCase
public function correctShortCodeReturnsSuccess(): void public function correctShortCodeReturnsSuccess(): void
{ {
$request = (new ServerRequest())->withAttribute('shortCode', 'abc123') $request = (new ServerRequest())->withAttribute('shortCode', 'abc123')
->withAttribute(ApiKey::class, new ApiKey())
->withParsedBody([ ->withParsedBody([
'maxVisits' => 5, 'maxVisits' => 5,
]); ]);