From 339b0feb6dc1d4c9b447984abc4dd8eb3160ece7 Mon Sep 17 00:00:00 2001 From: Alexis Saettler Date: Sat, 6 Nov 2021 20:35:13 +0100 Subject: [PATCH] feat: use ipdata to get infos from ip (#5680) --- app/Helpers/RequestHelper.php | 38 ++++++++++++++++-- config/location.php | 50 +++++++++++++++++++++++- tests/Fixtures/Helpers/ipdata.json | 48 +++++++++++++++++++++++ tests/Unit/Helpers/RequestHelperTest.php | 41 +++++++++++++++++++ 4 files changed, 172 insertions(+), 5 deletions(-) create mode 100644 tests/Fixtures/Helpers/ipdata.json diff --git a/app/Helpers/RequestHelper.php b/app/Helpers/RequestHelper.php index ba601307b31..a49f61cf3f8 100644 --- a/app/Helpers/RequestHelper.php +++ b/app/Helpers/RequestHelper.php @@ -5,6 +5,7 @@ use Vectorface\Whip\Whip; use Illuminate\Support\Arr; use OK\Ipstack\Client as Ipstack; +use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Request; use Stevebauman\Location\Facades\Location; @@ -56,19 +57,48 @@ public static function infos($ip) $ipstack = new Ipstack(config('location.ipstack_apikey')); $position = $ipstack->get($ip, true); - if (! is_null($position) && Arr::get($position, 'country_code', null)) { + if (! is_null($position) && Arr::get($position, 'country_code')) { return [ - 'country' => Arr::get($position, 'country_code', null), - 'currency' => Arr::get($position, 'currency.code', null), - 'timezone' => Arr::get($position, 'time_zone.id', null), + 'country' => Arr::get($position, 'country_code'), + 'currency' => Arr::get($position, 'currency.code'), + 'timezone' => Arr::get($position, 'time_zone.id'), ]; } } + if (config('location.ipdata.token') != null) { + try { + $position = static::getIpData($ip); + + return [ + 'country' => Arr::get($position, 'country_code'), + 'currency' => Arr::get($position, 'currency.code'), + 'timezone' => Arr::get($position, 'time_zone.name'), + ]; + } catch (\Exception $e) { + // skip + } + } + return [ 'country' => static::country($ip), 'currency' => null, 'timezone' => null, ]; } + + /** + * Get data from ipdata. + * + * @param string $ip + * @return array + */ + private static function getIpData(string $ip): array + { + $token = config('location.ipdata.token', ''); + + $url = "https://api.ipdata.co/{$ip}?api-key=".$token; + + return Http::get($url)->throw()->json(); + } } diff --git a/config/location.php b/config/location.php index de28e457f26..8846d0488c8 100644 --- a/config/location.php +++ b/config/location.php @@ -39,6 +39,18 @@ Stevebauman\Location\Drivers\MaxMind::class, ], + /* + |-------------------------------------------------------------------------- + | Position + |-------------------------------------------------------------------------- + | + | Here you may configure the position instance that is created + | and returned from the above drivers. The instance you + | create must extend the built-in Position class. + | + */ + 'position' => Stevebauman\Location\Position::class, + /* |-------------------------------------------------------------------------- | MaxMind Configuration @@ -66,6 +78,42 @@ ], ], + /* + |-------------------------------------------------------------------------- + | IP API Pro Configuration + |-------------------------------------------------------------------------- + | + | The configuration for the IP API Pro driver. + | + */ + 'ip_api' => [ + 'token' => env('IP_API_TOKEN'), + ], + + /* + |-------------------------------------------------------------------------- + | IPInfo Configuration + |-------------------------------------------------------------------------- + | + | The configuration for the IPInfo driver. + | + */ + 'ipinfo' => [ + 'token' => env('IPINFO_TOKEN'), + ], + + /* + |-------------------------------------------------------------------------- + | IPData Configuration + |-------------------------------------------------------------------------- + | + | The configuration for the IPData driver. + | + */ + 'ipdata' => [ + 'token' => env('IPDATA_TOKEN'), + ], + /* |-------------------------------------------------------------------------- | Localhost Testing @@ -78,7 +126,7 @@ | */ 'testing' => [ - 'enabled' => false, + 'enabled' => env('LOCATION_TESTING', false), 'ip' => '66.102.0.0', ], diff --git a/tests/Fixtures/Helpers/ipdata.json b/tests/Fixtures/Helpers/ipdata.json new file mode 100644 index 00000000000..74026227550 --- /dev/null +++ b/tests/Fixtures/Helpers/ipdata.json @@ -0,0 +1,48 @@ +{ + "ip": "12.34.56.78", + "is_eu": true, + "city": "Paris", + "region": "\u00cele-de-France", + "region_code": "IDF", + "country_name": "France", + "country_code": "FR", + "continent_name": "Europe", + "continent_code": "EU", + "latitude": 0, + "longitude": 0, + "postal": "75000", + "calling_code": "33", + "flag": "https://ipdata.co/flags/fr.png", + "emoji_flag": "\ud83c\uddeb\ud83c\uddf7", + "emoji_unicode": "U+1F1EB U+1F1F7", + "languages": [ + { + "name": "French", + "native": "Fran\u00e7ais" + } + ], + "currency": { + "name": "Euro", + "code": "EUR", + "symbol": "\u20ac", + "native": "\u20ac", + "plural": "euros" + }, + "time_zone": { + "name": "Europe/Paris", + "abbr": "CET", + "offset": "+0100", + "is_dst": false, + "current_time": "2021-11-01T00:00:00+01:00" + }, + "threat": { + "is_tor": false, + "is_proxy": false, + "is_anonymous": false, + "is_known_attacker": false, + "is_known_abuser": false, + "is_threat": false, + "is_bogon": false + }, + "count": "0" +} diff --git a/tests/Unit/Helpers/RequestHelperTest.php b/tests/Unit/Helpers/RequestHelperTest.php index 536b4db1b01..8c5d6ed07d9 100644 --- a/tests/Unit/Helpers/RequestHelperTest.php +++ b/tests/Unit/Helpers/RequestHelperTest.php @@ -5,6 +5,7 @@ use Tests\TestCase; use Mockery\MockInterface; use App\Helpers\RequestHelper; +use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Request; use Stevebauman\Location\Facades\Location; @@ -62,4 +63,44 @@ public function get_country_from_ip() RequestHelper::country(null) ); } + + /** @test */ + public function get_infos_from_ip() + { + config(['location.ipdata.token' => 'test']); + + $body = file_get_contents(base_path('tests/Fixtures/Helpers/ipdata.json')); + Http::fake([ + 'https://api.ipdata.co/*' => Http::response($body, 200), + ]); + + $this->assertEquals( + [ + 'country' => 'FR', + 'currency' => 'EUR', + 'timezone' => 'Europe/Paris', + ], + RequestHelper::infos('test') + ); + } + + /** @test */ + public function get_infos_from_ip_fail() + { + config(['location.ipdata.token' => 'test']); + + Http::fake([ + 'https://api.ipdata.co/*' => Http::response(null, 500), + ]); + Request::instance()->headers->set('Cf-Ipcountry', 'XX'); + + $this->assertEquals( + [ + 'country' => 'XX', + 'currency' => null, + 'timezone' => null, + ], + RequestHelper::infos('test') + ); + } }