Allow hiding IP addresses

This commit introduces a new feature where users can disable the collection and display of IP addresses. It's hardcoded in the .env config file for security reasons, and demo mode ignores this setting, because it already hides IPs by default.
This commit is contained in:
Miguel Nogueira 2021-10-23 07:26:47 +01:00
parent fd6dab0c2b
commit ab037a3474
Signed by: miguel456
GPG Key ID: 2CF61B825316C6A0
13 changed files with 91 additions and 34 deletions

View File

@ -7,14 +7,17 @@ APP_LOGO="https://www.raspberrypi.org/app/uploads/2020/05/Raspberry-Pi-OS-downlo
APP_SITEHOMEPAGE=""
# This can be your main homepage, other than this site itself
# Forces ssl connections even if the environment is set to "local".
# Void if env is production.
NONPROD_FORCE_SECURE=false
# Hides IP addresses
HIDE_IPS=false
# Disables certain features for security purposes while running an open authentication system
# Enable only for demonostration purposes
DEMO_MODE=false
# Forces ssl connections even if the environment is set to "local".
# Void if env is production.
NONPROD_FORCE_SECURE=false
LOG_CHANNEL=daily
DB_CONNECTION=mysql

View File

@ -23,9 +23,38 @@ namespace App\CustomFacades;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class IP
{
// Central source of truth for all operations that deal with IP addresses.
// For views, this is in a service provider, and is shared with all of them
/**
* Determines whether you should collect/display IP addresses in the app.
* @return bool Whether you should collect/display IPs, in the context in which this is called
*/
public function shouldCollect(): bool
{
// should collect or display IPs?
// demo mode = true
// hide ips = false
if (config('demo.is_enabled') || config('app.hide_ips'))
{
Log::debug('Global shouldCollect: ', [
'shouldCollect' => false
]);
return false; // do not collect!
}
Log::debug('Global shouldCollect: ', [
'shouldCollect' => true
]);
return true;
}
/**
* Looks up information on a specified IP address. Caches results automatically.
* @param string $IP IP address to lookup
@ -38,14 +67,16 @@ class IP
'ip' => $IP,
];
if ($this->shouldCollect()) {
if (!config('demo.is_enabled')) {
return json_decode(Cache::remember($IP, 3600, function () use ($IP) {
return Http::get(config('general.urls.ipapi.ipcheck'), [
'apiKey' => config('general.keys.ipapi.apikey'),
'ip' => $IP,
])->body();
}));
}
return new class {

View File

@ -26,6 +26,7 @@ use App\Exceptions\ApplicationNotFoundException;
use App\Exceptions\IncompleteApplicationException;
use App\Exceptions\UnavailableApplicationException;
use App\Exceptions\VacancyNotFoundException;
use App\Facades\IP;
use App\Services\ApplicationService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

View File

@ -26,6 +26,7 @@ use App\User;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use App\Facades\IP;
class LoginController extends Controller
{
@ -81,7 +82,7 @@ class LoginController extends Controller
public function authenticated(Request $request, User $user)
{
if (!config('demo.is_enabled')) {
if (IP::shouldCollect()) {
if ($user->originalIP !== $request->ip())
{
Log::alert('User IP address changed from last login. Updating.', [

View File

@ -124,7 +124,7 @@ class RegisterController extends Controller
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
'originalIP' => config('demo.is_enabled') ? '0.0.0.0' : request()->ip(),
'originalIP' => IP::shouldCollect() ? '0.0.0.0' : request()->ip(),
]);
$user->assignRole('user');

View File

@ -38,7 +38,7 @@ class ForceLogoutMiddleware
if (Auth::user()->isBanned()) {
Auth::logout();
$request->session()->flash('error', 'Error: Your session has been forcefully terminated. Please try again in a few days.');
$request->session()->flash('error', __('Your account is suspended. You will not be able to login or register until the suspension is lifted.'));
return redirect('/');
}

View File

@ -1,21 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class IPHistoryMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
return $next($request);
}
}

View File

@ -27,11 +27,13 @@ use App\Observers\ApplicationObserver;
use App\Observers\UserObserver;
use App\User;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
use Sentry;
class AppServiceProvider extends ServiceProvider
{
/**
@ -56,19 +58,24 @@ class AppServiceProvider extends ServiceProvider
]);
Schema::defaultStringLength(191);
Paginator::useBootstrap();
User::observe(UserObserver::class);
Application::observe(ApplicationObserver::class);
$https = ($this->app->environment() != 'local');
$collect = true;
if(config('app.force_secure') && $this->app->environment() != 'production')
$https = true;
if (config('app.hide_ips') || config('demo.is_enabled'))
{
$collect = false;
}
$this->app['request']->server->set('HTTPS', $https);
View::share('shouldCollect', $collect);
View::share('demoActive', config('demo.is_enabled'));
}
}

View File

@ -77,6 +77,23 @@ return [
*/
'force_secure' => env('NONPROD_FORCE_SECURE', false),
/*
|--------------------------------------------------------------------------
| IP address anonymity
|--------------------------------------------------------------------------
|
| RB Recruiter collects IP addresses and stores them in the database in order to
| display them to site admins.
|
| This feature allows you to disable the display and collection of IP addresses,
| just like in demo mode, without needing to be in demo mode.
|
| If enabled, demo mode will override this feature if it's set to false.
|
*/
'hide_ips' => env('HIDE_IPS'),
/*
|--------------------------------------------------------------------------
| Application Environment

View File

@ -317,7 +317,7 @@
<p class="text-muted">{{$profile->profileShortBio}}</p>
<p class="text-muted">{{__('messages.reusable.member_since', ['date' => $since])}}</p>
@if (Auth::user()->hasRole('admin'))
<button type="button" class="btn btn-sm btn-info" onclick="$('#ipInfo').modal('show')">{{__('messages.reusable.lookup', ['ipAddress' => (!$demoActive) ? $profile->user->originalIP : '0.0.0.0'])}}</button>
<button type="button" class="btn btn-sm btn-info" onclick="$('#ipInfo').modal('show')">{{__('messages.reusable.lookup', ['ipAddress' => ($shouldCollect) ? $profile->user->originalIP : '0.0.0.0'])}}</button>
@endif
@if ($profile->user->is(Auth::user()))

View File

@ -307,7 +307,7 @@
<div class="tab-pane fade p-3" id="sessions" role="tabpanel" aria-labelledby="sessionsTab">
<h5 class="card-title">{{__('messages.profile.session_manager')}}</h5>
<p class="card-text">{{__('messages.profile.terminate_others')}}</p>
<p>{{__('messages.profile.current_session', ['ipAddress' => ($demoActive) ? '0.0.0.0 (censored)' : $ip])}}</p>
<p>{{__('messages.profile.current_session', ['ipAddress' => (!$shouldCollect) ? '0.0.0.0 (censored)' : $ip])}}</p>
<button type="button" class="btn btn-warning" onclick="$('#authenticationForm').modal('show')">{{__('messages.profile.flush_session')}}</button>
</div>
<div class="tab-pane fade p-3" id="contactSettings" role="tabpanel" aria-labelledby="contactSettingsTab">

View File

@ -132,7 +132,7 @@
<p><b>{{__('messages.application_m.applicant_name')}} </b> <span class="badge badge-primary">{{$application->user->name}}</span></p>
@if (Auth::user()->hasRole('hiringManager'))
<p><b>{{__('messages.view_app.appl_ip')}}</b> <span class="badge badge-primary">{{ ($demoActive) ? '0.0.0.0 (censored)' : $application->user->originalIP }}</span></p>
<p><b>{{__('messages.view_app.appl_ip')}}</b> <span class="badge badge-primary">{{ (!$shouldCollect) ? '0.0.0.0 (censored)' : $application->user->originalIP }}</span></p>
@endif
<p><b>{{__('messages.application_m.application_date')}}</b> <span class="badge badge-primary">{{$application->created_at}}</span></p>
<p><b>{{__('messages.last_updated')}}</b><span class="badge badge-primary">{{$application->updated_at}}</span></p>

View File

@ -0,0 +1,18 @@
<?php
namespace Tests\Unit;
use PHPUnit\Framework\TestCase;
class ShouldCollectTest extends TestCase
{
/**
* A basic unit test example.
*
* @return void
*/
public function test_example()
{
$this->assertTrue(true);
}
}