Updated logic to generate random short codes, increasing entropy

This commit is contained in:
Alejandro Celaya
2019-10-11 09:14:25 +02:00
parent c8d950e04d
commit 2f09ff456c
13 changed files with 91 additions and 149 deletions

View File

@@ -19,20 +19,21 @@ use Shlinkio\Shlink\Core\Service\ShortUrl\DeleteShortUrlService;
use function Functional\map;
use function range;
use function sprintf;
class DeleteShortUrlServiceTest extends TestCase
{
/** @var DeleteShortUrlService */
private $service;
/** @var ObjectProphecy */
private $em;
/** @var string */
private $shortCode;
public function setUp(): void
{
$shortUrl = (new ShortUrl(''))->setShortCode('abc123')
->setVisits(new ArrayCollection(map(range(0, 10), function () {
return new Visit(new ShortUrl(''), Visitor::emptyInstance());
})));
$shortUrl = (new ShortUrl(''))->setVisits(new ArrayCollection(map(range(0, 10), function () {
return new Visit(new ShortUrl(''), Visitor::emptyInstance());
})));
$this->shortCode = $shortUrl->getShortCode();
$this->em = $this->prophesize(EntityManagerInterface::class);
@@ -42,55 +43,56 @@ class DeleteShortUrlServiceTest extends TestCase
}
/** @test */
public function deleteByShortCodeThrowsExceptionWhenThresholdIsReached()
public function deleteByShortCodeThrowsExceptionWhenThresholdIsReached(): void
{
$service = $this->createService();
$this->expectException(DeleteShortUrlException::class);
$this->expectExceptionMessage(
'Impossible to delete short URL with short code "abc123" since it has more than "5" visits.'
);
$this->expectExceptionMessage(sprintf(
'Impossible to delete short URL with short code "%s" since it has more than "5" visits.',
$this->shortCode
));
$service->deleteByShortCode('abc123');
$service->deleteByShortCode($this->shortCode);
}
/** @test */
public function deleteByShortCodeDeletesUrlWhenThresholdIsReachedButExplicitlyIgnored()
public function deleteByShortCodeDeletesUrlWhenThresholdIsReachedButExplicitlyIgnored(): void
{
$service = $this->createService();
$remove = $this->em->remove(Argument::type(ShortUrl::class))->willReturn(null);
$flush = $this->em->flush()->willReturn(null);
$service->deleteByShortCode('abc123', true);
$service->deleteByShortCode($this->shortCode, true);
$remove->shouldHaveBeenCalledOnce();
$flush->shouldHaveBeenCalledOnce();
}
/** @test */
public function deleteByShortCodeDeletesUrlWhenThresholdIsReachedButCheckIsDisabled()
public function deleteByShortCodeDeletesUrlWhenThresholdIsReachedButCheckIsDisabled(): void
{
$service = $this->createService(false);
$remove = $this->em->remove(Argument::type(ShortUrl::class))->willReturn(null);
$flush = $this->em->flush()->willReturn(null);
$service->deleteByShortCode('abc123');
$service->deleteByShortCode($this->shortCode);
$remove->shouldHaveBeenCalledOnce();
$flush->shouldHaveBeenCalledOnce();
}
/** @test */
public function deleteByShortCodeDeletesUrlWhenThresholdIsNotReached()
public function deleteByShortCodeDeletesUrlWhenThresholdIsNotReached(): void
{
$service = $this->createService(true, 100);
$remove = $this->em->remove(Argument::type(ShortUrl::class))->willReturn(null);
$flush = $this->em->flush()->willReturn(null);
$service->deleteByShortCode('abc123');
$service->deleteByShortCode($this->shortCode);
$remove->shouldHaveBeenCalledOnce();
$flush->shouldHaveBeenCalledOnce();

View File

@@ -17,7 +17,6 @@ use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\Core\Entity\ShortUrl;
use Shlinkio\Shlink\Core\Entity\Tag;
use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException;
use Shlinkio\Shlink\Core\Exception\InvalidUrlException;
use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException;
use Shlinkio\Shlink\Core\Exception\RuntimeException;
@@ -74,13 +73,13 @@ class UrlShortenerTest extends TestCase
/** @test */
public function urlIsProperlyShortened(): void
{
// 10 -> 0Q1Y
$shortUrl = $this->urlShortener->urlToShortCode(
new Uri('http://foobar.com/12345/hello?foo=bar'),
[],
ShortUrlMeta::createEmpty()
);
$this->assertEquals('0Q1Y', $shortUrl->getShortCode());
$this->assertEquals('http://foobar.com/12345/hello?foo=bar', $shortUrl->getLongUrl());
}
/** @test */
@@ -243,9 +242,8 @@ class UrlShortenerTest extends TestCase
/** @test */
public function shortCodeIsProperlyParsed(): void
{
$shortCode = '12C1c';
$shortUrl = new ShortUrl('expected_url');
$shortUrl->setShortCode($shortCode);
$shortCode = $shortUrl->getShortCode();
$repo = $this->prophesize(ShortUrlRepositoryInterface::class);
$repo->findOneByShortCode($shortCode, null)->willReturn($shortUrl);
@@ -254,11 +252,4 @@ class UrlShortenerTest extends TestCase
$url = $this->urlShortener->shortCodeToUrl($shortCode);
$this->assertSame($shortUrl, $url);
}
/** @test */
public function invalidCharSetThrowsException(): void
{
$this->expectException(InvalidShortCodeException::class);
$this->urlShortener->shortCodeToUrl('&/(');
}
}