mirror of
https://github.com/shlinkio/shlink.git
synced 2025-03-14 04:00:57 +03:00
Merge pull request #687 from acelaya-forks/feature/real-ip-geolocation
Feature/real ip geolocation
This commit is contained in:
commit
59c0d36c0b
8 changed files with 39 additions and 19 deletions
|
@ -15,11 +15,9 @@ vendor
|
|||
docs
|
||||
indocker
|
||||
docker-*
|
||||
php*
|
||||
.php*
|
||||
phpstan.neon
|
||||
php*xml*
|
||||
infection.json
|
||||
**/test*
|
||||
build*
|
||||
.git*
|
||||
.scrutinizer.yml
|
||||
.travis.yml
|
||||
**/.*
|
||||
|
|
|
@ -6,6 +6,9 @@ checks:
|
|||
code_rating: true
|
||||
duplication: true
|
||||
build:
|
||||
dependencies:
|
||||
override:
|
||||
- composer install --no-interaction --no-scripts --ignore-platform-reqs
|
||||
nodes:
|
||||
analysis:
|
||||
tests:
|
||||
|
|
|
@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this
|
|||
* [#626](https://github.com/shlinkio/shlink/issues/626) Added support for Microsoft SQL Server.
|
||||
* [#556](https://github.com/shlinkio/shlink/issues/556) Short code lengths can now be customized, both globally and on a per-short URL basis.
|
||||
* [#541](https://github.com/shlinkio/shlink/issues/541) Added a request ID that is returned on `X-Request-Id` header, can be provided from outside and is set in log entries.
|
||||
* [#642](https://github.com/shlinkio/shlink/issues/642) IP geolocation is now performed over the non-anonymized IP address when using swoole.
|
||||
|
||||
#### Changed
|
||||
|
||||
|
|
|
@ -40,9 +40,10 @@ RUN wget https://download.microsoft.com/download/e/4/e/e4e67866-dffd-428c-aac7-8
|
|||
FROM base as builder
|
||||
COPY . .
|
||||
COPY --from=composer:1.10.1 /usr/bin/composer ./composer.phar
|
||||
RUN php composer.phar install --no-dev --optimize-autoloader --prefer-dist --no-progress --no-interaction && \
|
||||
RUN apk add --no-cache git && \
|
||||
php composer.phar install --no-dev --optimize-autoloader --prefer-dist --no-progress --no-interaction && \
|
||||
php composer.phar clear-cache && \
|
||||
rm composer.* && \
|
||||
rm -r docker composer.* && \
|
||||
sed -i "s/%SHLINK_VERSION%/${SHLINK_VERSION}/g" config/autoload/app_options.global.php
|
||||
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ class LocateShortUrlVisit
|
|||
}
|
||||
|
||||
if ($this->downloadOrUpdateGeoLiteDb($visitId)) {
|
||||
$this->locateVisit($visitId, $visit);
|
||||
$this->locateVisit($visitId, $shortUrlVisited->originalIpAddress(), $visit);
|
||||
}
|
||||
|
||||
$this->eventDispatcher->dispatch(new VisitLocated($visitId));
|
||||
|
@ -80,12 +80,13 @@ class LocateShortUrlVisit
|
|||
return true;
|
||||
}
|
||||
|
||||
private function locateVisit(string $visitId, Visit $visit): void
|
||||
private function locateVisit(string $visitId, ?string $originalIpAddress, Visit $visit): void
|
||||
{
|
||||
$isLocatable = $originalIpAddress !== null || $visit->isLocatable();
|
||||
$addr = $originalIpAddress ?? $visit->getRemoteAddr();
|
||||
|
||||
try {
|
||||
$location = $visit->isLocatable()
|
||||
? $this->ipLocationResolver->resolveIpLocation($visit->getRemoteAddr())
|
||||
: Location::emptyInstance();
|
||||
$location = $isLocatable ? $this->ipLocationResolver->resolveIpLocation($addr) : Location::emptyInstance();
|
||||
|
||||
$visit->locate(new VisitLocation($location));
|
||||
$this->em->flush();
|
||||
|
|
|
@ -9,10 +9,12 @@ use JsonSerializable;
|
|||
final class ShortUrlVisited implements JsonSerializable
|
||||
{
|
||||
private string $visitId;
|
||||
private ?string $originalIpAddress;
|
||||
|
||||
public function __construct(string $visitId)
|
||||
public function __construct(string $visitId, ?string $originalIpAddress = null)
|
||||
{
|
||||
$this->visitId = $visitId;
|
||||
$this->originalIpAddress = $originalIpAddress;
|
||||
}
|
||||
|
||||
public function visitId(): string
|
||||
|
@ -20,8 +22,13 @@ final class ShortUrlVisited implements JsonSerializable
|
|||
return $this->visitId;
|
||||
}
|
||||
|
||||
public function originalIpAddress(): ?string
|
||||
{
|
||||
return $this->originalIpAddress;
|
||||
}
|
||||
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return ['visitId' => $this->visitId];
|
||||
return ['visitId' => $this->visitId, 'originalIpAddress' => $this->originalIpAddress];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ class VisitsTracker implements VisitsTrackerInterface
|
|||
$this->em->persist($visit);
|
||||
$this->em->flush();
|
||||
|
||||
$this->eventDispatcher->dispatch(new ShortUrlVisited($visit->getId()));
|
||||
$this->eventDispatcher->dispatch(new ShortUrlVisited($visit->getId(), $visitor->getRemoteAddress()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -130,13 +130,16 @@ class LocateShortUrlVisitTest extends TestCase
|
|||
yield 'localhost' => [new Visit($shortUrl, new Visitor('', '', IpAddress::LOCALHOST))];
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function locatableVisitsResolveToLocation(): void
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider provideIpAddresses
|
||||
*/
|
||||
public function locatableVisitsResolveToLocation(string $anonymizedIpAddress, ?string $originalIpAddress): void
|
||||
{
|
||||
$ipAddr = '1.2.3.0';
|
||||
$ipAddr = $originalIpAddress ?? $anonymizedIpAddress;
|
||||
$visit = new Visit(new ShortUrl(''), new Visitor('', '', $ipAddr));
|
||||
$location = new Location('', '', '', '', 0.0, 0.0, '');
|
||||
$event = new ShortUrlVisited('123');
|
||||
$event = new ShortUrlVisited('123', $originalIpAddress);
|
||||
|
||||
$findVisit = $this->em->find(Visit::class, '123')->willReturn($visit);
|
||||
$flush = $this->em->flush()->will(function (): void {
|
||||
|
@ -155,6 +158,12 @@ class LocateShortUrlVisitTest extends TestCase
|
|||
$dispatch->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
|
||||
public function provideIpAddresses(): iterable
|
||||
{
|
||||
yield 'no original IP address' => ['1.2.3.0', null];
|
||||
yield 'original IP address' => ['1.2.3.0', '1.2.3.4'];
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function errorWhenUpdatingGeoLiteWithExistingCopyLogsWarning(): void
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue