Allowed port number on domain field when creating shotr URLs

This commit is contained in:
Alejandro Celaya 2019-10-20 10:30:11 +02:00
parent 232bf5a68b
commit b5e4da847a
3 changed files with 44 additions and 13 deletions

View file

@ -50,9 +50,7 @@ class ShortUrlMetaInputFilter extends InputFilter
$this->add($this->createBooleanInput(self::FIND_IF_EXISTS, false));
$domain = $this->createInput(self::DOMAIN, false);
$domain->getValidatorChain()->attach(new Validator\Hostname([
'allow' => Validator\Hostname::ALLOW_DNS | Validator\Hostname::ALLOW_LOCAL,
]));
$domain->getValidatorChain()->attach(new Validation\HostAndPortValidator());
$this->add($domain);
}
}

View file

@ -7,6 +7,7 @@ namespace Shlinkio\Shlink\Rest\Action\ShortUrl;
use Cake\Chronos\Chronos;
use Psr\Http\Message\ServerRequestInterface as Request;
use Shlinkio\Shlink\Core\Exception\InvalidArgumentException;
use Shlinkio\Shlink\Core\Exception\ValidationException;
use Shlinkio\Shlink\Core\Model\CreateShortUrlData;
use Shlinkio\Shlink\Core\Model\ShortUrlMeta;
use Zend\Diactoros\Uri;
@ -29,18 +30,20 @@ class CreateShortUrlAction extends AbstractCreateShortUrlAction
throw new InvalidArgumentException('A URL was not provided');
}
return new CreateShortUrlData(
new Uri($postData['longUrl']),
(array) ($postData['tags'] ?? []),
ShortUrlMeta::createFromParams(
try {
$meta = ShortUrlMeta::createFromParams(
$this->getOptionalDate($postData, 'validSince'),
$this->getOptionalDate($postData, 'validUntil'),
$postData['customSlug'] ?? null,
$postData['maxVisits'] ?? null,
$postData['findIfExists'] ?? null,
$postData['domain'] ?? null
)
);
);
return new CreateShortUrlData(new Uri($postData['longUrl']), (array) ($postData['tags'] ?? []), $meta);
} catch (ValidationException $e) {
throw new InvalidArgumentException('Provided meta data is not valid', -1, $e);
}
}
private function getOptionalDate(array $postData, string $fieldName): ?Chronos

View file

@ -15,6 +15,7 @@ use Shlinkio\Shlink\Core\Model\ShortUrlMeta;
use Shlinkio\Shlink\Core\Service\UrlShortener;
use Shlinkio\Shlink\Rest\Action\ShortUrl\CreateShortUrlAction;
use Shlinkio\Shlink\Rest\Util\RestUtils;
use Zend\Diactoros\Response\JsonResponse;
use Zend\Diactoros\ServerRequest;
use Zend\Diactoros\Uri;
@ -50,8 +51,8 @@ class CreateShortUrlActionTest extends TestCase
{
$shortUrl = new ShortUrl('');
$this->urlShortener->urlToShortCode(Argument::type(Uri::class), Argument::type('array'), Argument::cetera())
->willReturn($shortUrl)
->shouldBeCalledOnce();
->willReturn($shortUrl)
->shouldBeCalledOnce();
$request = (new ServerRequest())->withParsedBody([
'longUrl' => 'http://www.domain.com/foo/bar',
@ -65,8 +66,8 @@ class CreateShortUrlActionTest extends TestCase
public function anInvalidUrlReturnsError(): void
{
$this->urlShortener->urlToShortCode(Argument::type(Uri::class), Argument::type('array'), Argument::cetera())
->willThrow(InvalidUrlException::class)
->shouldBeCalledOnce();
->willThrow(InvalidUrlException::class)
->shouldBeCalledOnce();
$request = (new ServerRequest())->withParsedBody([
'longUrl' => 'http://www.domain.com/foo/bar',
@ -76,6 +77,35 @@ class CreateShortUrlActionTest extends TestCase
$this->assertTrue(strpos($response->getBody()->getContents(), RestUtils::INVALID_URL_ERROR) > 0);
}
/**
* @test
* @dataProvider provideInvalidDomains
*/
public function anInvalidDomainReturnsError(string $domain): void
{
$shortUrl = new ShortUrl('');
$urlToShortCode = $this->urlShortener->urlToShortCode(Argument::cetera())->willReturn($shortUrl);
$request = (new ServerRequest())->withParsedBody([
'longUrl' => 'http://www.domain.com/foo/bar',
'domain' => $domain,
]);
/** @var JsonResponse $response */
$response = $this->action->handle($request);
$payload = $response->getPayload();
$this->assertEquals(400, $response->getStatusCode());
$this->assertEquals(RestUtils::INVALID_ARGUMENT_ERROR, $payload['error']);
$urlToShortCode->shouldNotHaveBeenCalled();
}
public function provideInvalidDomains(): iterable
{
yield ['localhost:80000'];
yield ['127.0.0.1'];
yield ['???/&%$&'];
}
/** @test */
public function nonUniqueSlugReturnsError(): void
{