mirror of
https://github.com/shlinkio/shlink.git
synced 2026-03-08 08:13:11 +08:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3af493758 | ||
|
|
7b9ebbbb5f | ||
|
|
ea735fc0a0 | ||
|
|
06227e97d0 | ||
|
|
aa00e33b6d | ||
|
|
4ef04c641e | ||
|
|
bfcccd8c33 | ||
|
|
f7d3c73c4a |
34
CHANGELOG.md
34
CHANGELOG.md
@@ -4,6 +4,40 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com), and this project adheres to [Semantic Versioning](https://semver.org).
|
The format is based on [Keep a Changelog](https://keepachangelog.com), and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
|
|
||||||
|
## [2.7.2] - 2021-07-30
|
||||||
|
### Added
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
### Deprecated
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* [#1128](https://github.com/shlinkio/shlink/issues/1128) Increased memory limit reserved for the docker image, preventing it from crashing on GeoLite db download.
|
||||||
|
|
||||||
|
|
||||||
|
## [2.7.1] - 2021-05-30
|
||||||
|
### Added
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
### Deprecated
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* [#1100](https://github.com/shlinkio/shlink/issues/1100) Fixed Shlink trying to download GeoLite2 db files even when tracking has been disabled.
|
||||||
|
|
||||||
|
|
||||||
## [2.7.0] - 2021-05-23
|
## [2.7.0] - 2021-05-23
|
||||||
### Added
|
### Added
|
||||||
* [#1044](https://github.com/shlinkio/shlink/issues/1044) Added ability to set names on API keys, which helps to identify them when the list grows.
|
* [#1044](https://github.com/shlinkio/shlink/issues/1044) Added ability to set names on API keys, which helps to identify them when the list grows.
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
"endroid/qr-code": "^4.0",
|
"endroid/qr-code": "^4.0",
|
||||||
"geoip2/geoip2": "^2.9",
|
"geoip2/geoip2": "^2.9",
|
||||||
"guzzlehttp/guzzle": "^7.0",
|
"guzzlehttp/guzzle": "^7.0",
|
||||||
|
"guzzlehttp/psr7": "^1.7",
|
||||||
"happyr/doctrine-specification": "^2.0",
|
"happyr/doctrine-specification": "^2.0",
|
||||||
"jaybizzle/crawler-detect": "^1.2",
|
"jaybizzle/crawler-detect": "^1.2",
|
||||||
"laminas/laminas-config": "^3.3",
|
"laminas/laminas-config": "^3.3",
|
||||||
@@ -52,7 +53,7 @@
|
|||||||
"shlinkio/shlink-event-dispatcher": "^2.1",
|
"shlinkio/shlink-event-dispatcher": "^2.1",
|
||||||
"shlinkio/shlink-importer": "^2.3",
|
"shlinkio/shlink-importer": "^2.3",
|
||||||
"shlinkio/shlink-installer": "^6.0",
|
"shlinkio/shlink-installer": "^6.0",
|
||||||
"shlinkio/shlink-ip-geolocation": "^1.5",
|
"shlinkio/shlink-ip-geolocation": "^2.0",
|
||||||
"symfony/console": "^5.1",
|
"symfony/console": "^5.1",
|
||||||
"symfony/filesystem": "^5.1",
|
"symfony/filesystem": "^5.1",
|
||||||
"symfony/lock": "^5.1",
|
"symfony/lock": "^5.1",
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
log_errors_max_len=0
|
log_errors_max_len=0
|
||||||
zend.assertions=1
|
zend.assertions=1
|
||||||
assert.exception=1
|
assert.exception=1
|
||||||
|
memory_limit=256M
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ return [
|
|||||||
],
|
],
|
||||||
|
|
||||||
'geolite2' => [
|
'geolite2' => [
|
||||||
'license_key' => env('GEOLITE_LICENSE_KEY', 'G4Lm0C60yJsnkdPi'), // Deprecated. Remove the default value
|
'license_key' => env('GEOLITE_LICENSE_KEY', 'G4Lm0C60yJsnkdPi'), // Deprecated. Remove hardcoded license on v3
|
||||||
],
|
],
|
||||||
|
|
||||||
'mercure' => $helper->getMercureConfig(),
|
'mercure' => $helper->getMercureConfig(),
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory;
|
|||||||
use Laminas\ServiceManager\Factory\InvokableFactory;
|
use Laminas\ServiceManager\Factory\InvokableFactory;
|
||||||
use Shlinkio\Shlink\Common\Doctrine\NoDbNameConnectionFactory;
|
use Shlinkio\Shlink\Common\Doctrine\NoDbNameConnectionFactory;
|
||||||
use Shlinkio\Shlink\Core\Domain\DomainService;
|
use Shlinkio\Shlink\Core\Domain\DomainService;
|
||||||
|
use Shlinkio\Shlink\Core\Options\TrackingOptions;
|
||||||
use Shlinkio\Shlink\Core\Service;
|
use Shlinkio\Shlink\Core\Service;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifier;
|
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifier;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformer;
|
use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformer;
|
||||||
@@ -64,7 +65,12 @@ return [
|
|||||||
],
|
],
|
||||||
|
|
||||||
ConfigAbstractFactory::class => [
|
ConfigAbstractFactory::class => [
|
||||||
Util\GeolocationDbUpdater::class => [DbUpdater::class, Reader::class, LOCAL_LOCK_FACTORY],
|
Util\GeolocationDbUpdater::class => [
|
||||||
|
DbUpdater::class,
|
||||||
|
Reader::class,
|
||||||
|
LOCAL_LOCK_FACTORY,
|
||||||
|
TrackingOptions::class,
|
||||||
|
],
|
||||||
Util\ProcessRunner::class => [SymfonyCli\Helper\ProcessHelper::class],
|
Util\ProcessRunner::class => [SymfonyCli\Helper\ProcessHelper::class],
|
||||||
ApiKey\RoleResolver::class => [DomainService::class],
|
ApiKey\RoleResolver::class => [DomainService::class],
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use Cake\Chronos\Chronos;
|
|||||||
use GeoIp2\Database\Reader;
|
use GeoIp2\Database\Reader;
|
||||||
use MaxMind\Db\Reader\Metadata;
|
use MaxMind\Db\Reader\Metadata;
|
||||||
use Shlinkio\Shlink\CLI\Exception\GeolocationDbUpdateFailedException;
|
use Shlinkio\Shlink\CLI\Exception\GeolocationDbUpdateFailedException;
|
||||||
|
use Shlinkio\Shlink\Core\Options\TrackingOptions;
|
||||||
use Shlinkio\Shlink\IpGeolocation\Exception\RuntimeException;
|
use Shlinkio\Shlink\IpGeolocation\Exception\RuntimeException;
|
||||||
use Shlinkio\Shlink\IpGeolocation\GeoLite2\DbUpdaterInterface;
|
use Shlinkio\Shlink\IpGeolocation\GeoLite2\DbUpdaterInterface;
|
||||||
use Symfony\Component\Lock\LockFactory;
|
use Symfony\Component\Lock\LockFactory;
|
||||||
@@ -21,12 +22,18 @@ class GeolocationDbUpdater implements GeolocationDbUpdaterInterface
|
|||||||
private DbUpdaterInterface $dbUpdater;
|
private DbUpdaterInterface $dbUpdater;
|
||||||
private Reader $geoLiteDbReader;
|
private Reader $geoLiteDbReader;
|
||||||
private LockFactory $locker;
|
private LockFactory $locker;
|
||||||
|
private TrackingOptions $trackingOptions;
|
||||||
|
|
||||||
public function __construct(DbUpdaterInterface $dbUpdater, Reader $geoLiteDbReader, LockFactory $locker)
|
public function __construct(
|
||||||
{
|
DbUpdaterInterface $dbUpdater,
|
||||||
|
Reader $geoLiteDbReader,
|
||||||
|
LockFactory $locker,
|
||||||
|
TrackingOptions $trackingOptions
|
||||||
|
) {
|
||||||
$this->dbUpdater = $dbUpdater;
|
$this->dbUpdater = $dbUpdater;
|
||||||
$this->geoLiteDbReader = $geoLiteDbReader;
|
$this->geoLiteDbReader = $geoLiteDbReader;
|
||||||
$this->locker = $locker;
|
$this->locker = $locker;
|
||||||
|
$this->trackingOptions = $trackingOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,6 +41,10 @@ class GeolocationDbUpdater implements GeolocationDbUpdaterInterface
|
|||||||
*/
|
*/
|
||||||
public function checkDbUpdate(?callable $beforeDownload = null, ?callable $handleProgress = null): void
|
public function checkDbUpdate(?callable $beforeDownload = null, ?callable $handleProgress = null): void
|
||||||
{
|
{
|
||||||
|
if ($this->trackingOptions->disableTracking() || $this->trackingOptions->disableIpTracking()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$lock = $this->locker->createLock(self::LOCK_NAME);
|
$lock = $this->locker->createLock(self::LOCK_NAME);
|
||||||
$lock->acquire(true); // Block until lock is released
|
$lock->acquire(true); // Block until lock is released
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use Prophecy\PhpUnit\ProphecyTrait;
|
|||||||
use Prophecy\Prophecy\ObjectProphecy;
|
use Prophecy\Prophecy\ObjectProphecy;
|
||||||
use Shlinkio\Shlink\CLI\Exception\GeolocationDbUpdateFailedException;
|
use Shlinkio\Shlink\CLI\Exception\GeolocationDbUpdateFailedException;
|
||||||
use Shlinkio\Shlink\CLI\Util\GeolocationDbUpdater;
|
use Shlinkio\Shlink\CLI\Util\GeolocationDbUpdater;
|
||||||
|
use Shlinkio\Shlink\Core\Options\TrackingOptions;
|
||||||
use Shlinkio\Shlink\IpGeolocation\Exception\RuntimeException;
|
use Shlinkio\Shlink\IpGeolocation\Exception\RuntimeException;
|
||||||
use Shlinkio\Shlink\IpGeolocation\GeoLite2\DbUpdaterInterface;
|
use Shlinkio\Shlink\IpGeolocation\GeoLite2\DbUpdaterInterface;
|
||||||
use Symfony\Component\Lock;
|
use Symfony\Component\Lock;
|
||||||
@@ -28,11 +29,13 @@ class GeolocationDbUpdaterTest extends TestCase
|
|||||||
private GeolocationDbUpdater $geolocationDbUpdater;
|
private GeolocationDbUpdater $geolocationDbUpdater;
|
||||||
private ObjectProphecy $dbUpdater;
|
private ObjectProphecy $dbUpdater;
|
||||||
private ObjectProphecy $geoLiteDbReader;
|
private ObjectProphecy $geoLiteDbReader;
|
||||||
|
private TrackingOptions $trackingOptions;
|
||||||
|
|
||||||
public function setUp(): void
|
public function setUp(): void
|
||||||
{
|
{
|
||||||
$this->dbUpdater = $this->prophesize(DbUpdaterInterface::class);
|
$this->dbUpdater = $this->prophesize(DbUpdaterInterface::class);
|
||||||
$this->geoLiteDbReader = $this->prophesize(Reader::class);
|
$this->geoLiteDbReader = $this->prophesize(Reader::class);
|
||||||
|
$this->trackingOptions = new TrackingOptions();
|
||||||
|
|
||||||
$locker = $this->prophesize(Lock\LockFactory::class);
|
$locker = $this->prophesize(Lock\LockFactory::class);
|
||||||
$lock = $this->prophesize(Lock\LockInterface::class);
|
$lock = $this->prophesize(Lock\LockInterface::class);
|
||||||
@@ -45,6 +48,7 @@ class GeolocationDbUpdaterTest extends TestCase
|
|||||||
$this->dbUpdater->reveal(),
|
$this->dbUpdater->reveal(),
|
||||||
$this->geoLiteDbReader->reveal(),
|
$this->geoLiteDbReader->reveal(),
|
||||||
$locker->reveal(),
|
$locker->reveal(),
|
||||||
|
$this->trackingOptions,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,4 +178,27 @@ class GeolocationDbUpdaterTest extends TestCase
|
|||||||
'record_size' => 4,
|
'record_size' => 4,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @dataProvider provideTrackingOptions
|
||||||
|
*/
|
||||||
|
public function downloadDbIsSkippedIfTrackingIsDisabled(array $props): void
|
||||||
|
{
|
||||||
|
foreach ($props as $prop) {
|
||||||
|
$this->trackingOptions->{$prop} = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->geolocationDbUpdater->checkDbUpdate();
|
||||||
|
|
||||||
|
$this->dbUpdater->databaseFileExists(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||||
|
$this->geoLiteDbReader->metadata(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideTrackingOptions(): iterable
|
||||||
|
{
|
||||||
|
yield 'disableTracking' => [['disableTracking']];
|
||||||
|
yield 'disableIpTracking' => [['disableIpTracking']];
|
||||||
|
yield 'both' => [['disableTracking', 'disableIpTracking']];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,18 @@ namespace Shlinkio\Shlink\Rest\Middleware;
|
|||||||
|
|
||||||
use Laminas\Diactoros\Response\EmptyResponse;
|
use Laminas\Diactoros\Response\EmptyResponse;
|
||||||
use Mezzio\Router\Middleware\ImplicitOptionsMiddleware;
|
use Mezzio\Router\Middleware\ImplicitOptionsMiddleware;
|
||||||
|
use Psr\Http\Message\ResponseFactoryInterface;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
|
||||||
class EmptyResponseImplicitOptionsMiddlewareFactory
|
class EmptyResponseImplicitOptionsMiddlewareFactory
|
||||||
{
|
{
|
||||||
public function __invoke(): ImplicitOptionsMiddleware
|
public function __invoke(): ImplicitOptionsMiddleware
|
||||||
{
|
{
|
||||||
return new ImplicitOptionsMiddleware(fn () => new EmptyResponse());
|
return new ImplicitOptionsMiddleware(new class implements ResponseFactoryInterface {
|
||||||
|
public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface
|
||||||
|
{
|
||||||
|
return new EmptyResponse();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace ShlinkioTest\Shlink\Rest\Middleware;
|
|||||||
use Laminas\Diactoros\Response\EmptyResponse;
|
use Laminas\Diactoros\Response\EmptyResponse;
|
||||||
use Mezzio\Router\Middleware\ImplicitOptionsMiddleware;
|
use Mezzio\Router\Middleware\ImplicitOptionsMiddleware;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Psr\Http\Message\ResponseFactoryInterface;
|
||||||
use ReflectionObject;
|
use ReflectionObject;
|
||||||
use Shlinkio\Shlink\Rest\Middleware\EmptyResponseImplicitOptionsMiddlewareFactory;
|
use Shlinkio\Shlink\Rest\Middleware\EmptyResponseImplicitOptionsMiddlewareFactory;
|
||||||
|
|
||||||
@@ -34,6 +35,10 @@ class EmptyResponseImplicitOptionsMiddlewareFactoryTest extends TestCase
|
|||||||
$ref = new ReflectionObject($instance);
|
$ref = new ReflectionObject($instance);
|
||||||
$prop = $ref->getProperty('responseFactory');
|
$prop = $ref->getProperty('responseFactory');
|
||||||
$prop->setAccessible(true);
|
$prop->setAccessible(true);
|
||||||
self::assertInstanceOf(EmptyResponse::class, $prop->getValue($instance)());
|
|
||||||
|
/** @var ResponseFactoryInterface $value */
|
||||||
|
$value = $prop->getValue($instance);
|
||||||
|
|
||||||
|
self::assertInstanceOf(EmptyResponse::class, $value->createResponse());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user