Skip to content
Open
13 changes: 12 additions & 1 deletion app/Audit.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,21 @@ public function getTimeDateAttribute() {
}

public static function newAudit(string $message): void {
$impersonated_by_id = null;
$impersonation_string = '';
if (session()->has('impersonating_user')) {
$impersonated_by_id = session('impersonating_user');
$impersonation_user = User::find($impersonated_by_id);

$impersonation_string = 'IMPERSONATED BY ' . (is_null($impersonation_user) ? 'UNKNOWN' : $impersonation_user->full_name) . ': ';
}
$impersonated_by_id = session()->has('impersonating_user') ? session('impersonating_user') : null;

$audit = new Audit;
$audit->cid = Auth::id();
$audit->impersonated_by_id = $impersonated_by_id;
$audit->ip = $_SERVER['REMOTE_ADDR'];
$audit->what = Auth::user()->full_name . ' ' . $message;
$audit->what = $impersonation_string . Auth::user()->full_name . ' ' . $message;
$audit->save();
}
}
33 changes: 33 additions & 0 deletions app/Http/Controllers/ImpersonationController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace App\Http\Controllers;

use App\Audit;
use App\User;
use Illuminate\Http\Request;

class ImpersonationController extends Controller {
public function start(Request $request) {
$user = User::find($request->user_id);
$is_impersonating = session()->has('impersonate');
if (is_null($user)) {
return redirect()->back()->with('error', 'That user does not exist');
}

if ($is_impersonating) {
return redirect()->back()->with('error', 'You must first stop impersonating your current user before beginning a new session');
}

session()->put('impersonate', $user->id);

Audit::newAudit('started impersonating user ' . $user->impersonation_name . '.');
return redirect('/dashboard')->with('warning', 'Successfully started impersonationg ' . $user->full_name . '. CAUTION: Impersonating actively logs you into the user\'s REAL account. Changes made while impersonating will be reflected on the user\'s actual account. PROCEED WITH CARE.');
}

public function stop() {
Audit::newAudit('impersonation session ending...');

session()->forget('impersonate');
return redirect('/dashboard');
}
}
1 change: 1 addition & 0 deletions app/Http/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class Kernel extends HttpKernel {
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\Impersonation::class,
],

'api' => [
Expand Down
24 changes: 24 additions & 0 deletions app/Http/Middleware/Impersonation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace App\Http\Middleware;

use Auth;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class Impersonation {
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response {
if (toggleEnabled('impersonation') && session()->has('impersonate') && Auth::user()->isAbleTo('snrStaff')) {
session()->put('impersonating_user', Auth::id());
Auth::onceUsingId(session('impersonate'));
}

return $next($request);
}
}
4 changes: 4 additions & 0 deletions app/Providers/AppServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

namespace App\Providers;

use App\View\Composers\ImpersonationComposer;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Vite;
use Illuminate\Support\ServiceProvider;

Expand All @@ -24,6 +26,8 @@ public function boot(): void {
return toggleEnabled($toggle_name);
});

View::composer('inc.dashboard_head', ImpersonationComposer::class);

/**
* Paginate a standard Laravel Collection.
*
Expand Down
16 changes: 16 additions & 0 deletions app/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,22 @@ public function getFullNameRatingAttribute() {
return $this->full_name . ' - ' . $this->rating_short;
}

public function getImpersonationNameAttribute() {
$roles = array_reduce($this->roles->toArray(), function ($role_string, $role) {
return $role_string . $role['name'] . ', ';
}, '');

if ($this->visitor) {
$roles = 'visitor';
}

if ($roles != '') {
$roles = ' (' . trim($roles, ', ') . ')';
}

return $this->backwards_name . ' ' . $this->id . ' - ' . $this->rating_short . $roles;
}

public static $RatingShort = [
0 => 'N/A',
1 => 'OBS', 2 => 'S1',
Expand Down
32 changes: 32 additions & 0 deletions app/View/Composers/ImpersonationComposer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace App\View\Composers;

use App\User;
use Auth;
use Illuminate\View\View;

class ImpersonationComposer {
/**
* Create a new profile composer.
*/
public function __construct(
) {
}

/**
* Bind data to the view.
*/
public function compose(View $view): void {
if (toggleEnabled('impersonation')) {
$users = null;
$is_impersonating = session()->has('impersonate');

if (Auth::user()->isAbleTo('snrStaff')) {
$users = User::where('status', 1)->orderBy('lname', 'ASC')->get()->pluck('impersonation_name', 'id');
}

$view->with('users', $users)->with('is_impersonating', $is_impersonating);
}
}
}
46 changes: 25 additions & 21 deletions resources/views/inc/dashboard_head.blade.php
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
<nav class="navbar navbar-expand-lg navbar-light">
<div class="container-fluid">
<nav class="navbar navbar-expand-lg navbar-light">
<div class="container-fluid">
<a class="navbar-brand" href="/dashboard">
@include('inc.logo', ['color' => 'black'])
</a>
<div class="d-flex justify-content-start ms-5 collapse navbar-collapse">

{{ html()->form()->route('searchAirport')->class(['row','row-cols-lg-auto'])->open() }}
<div class="col-12 input-group">
{{ html()->text('apt', null)->placeholder('Search Airport ICAO')->class(['form-control']) }}
&nbsp;
<button class="btn btn-success" type="submit">Search</button>
</div>
<ul class="navbar-nav me-auto align-items-center">
{{ html()->form()->route('searchAirport')->class(['form-inline'])->open() }}
<div class="col-12 input-group">
{{ html()->text('apt', null)->placeholder('Search Airport ICAO')->class(['form-control']) }}
&nbsp;
<button class="btn btn-success" type="submit">Search</button>
</div>
{{ html()->form()->close() }}
</ul>
<ul class="navbar-nav ml-auto align-items-center">
<a class="nav-link {{ Nav::isRoute('controller_dash_home') }}" href="/dashboard">Dashboard Home</a>
@if(toggleEnabled('impersonation') && $is_impersonating)
<a class="nav-link" href="/dashboard/admin/impersonation/stop">End Impersonation</a>
@endif
@if(toggleEnabled('impersonation') && Auth::user()->isAbleTo('snrStaff'))
{{ html()->form()->route('startImpersonation')->class(['form-inline'])->open() }}
{{ html()->select('user_id', $users, Auth::id())->class(['form-select'])->attributes(['onchange' => 'this.form.submit()'])->disabled($is_impersonating) }}
{{ html()->form()->close() }}
</div>

<ul class="navbar-nav ms-auto">
<a class="nav-link {{ Nav::isRoute('controller_dash_home') }}" href="/dashboard">Dashboard Home</a>
<li class="nav-item dropdown">
<a class="nav-link" style="pointer-events:none">{{ Auth::user()->full_name }} - {{ Auth::user()->rating_short }}</a>
</li>
</ul>
</div>
</div>
</nav>
@else
<a class="nav-link disabled">{{ Auth::user()->full_name }} - {{ Auth::user()->rating_short }}</a>
@endif
</ul>
</div>
</nav>

7 changes: 7 additions & 0 deletions resources/views/inc/messages.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@
</div>
@endif

@if(session('warning'))
<br>
<div class="alert alert-warning">
{{ session('warning') }}
</div>
@endif

@if(session('error'))
<br>
<div class="alert alert-danger">
Expand Down
5 changes: 5 additions & 0 deletions routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,11 @@
Route::prefix('monitor')->middleware('permission:staff')->group(function () {
Route::get('/', 'AdminDash@backgroundMonitor');
});

Route::prefix('impersonation')->middleware('toggle:impersonation')->group(function () {
Route::post('/', 'ImpersonationController@start')->middleware('permission:snrStaff')->name('startImpersonation');
Route::get('/stop', 'ImpersonationController@stop')->name('stopImpersonation');
});
});
});
/*
Expand Down