diff --git a/app/Audit.php b/app/Audit.php
index 86769df98..4e5a1b85e 100644
--- a/app/Audit.php
+++ b/app/Audit.php
@@ -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();
}
}
diff --git a/app/Http/Controllers/ImpersonationController.php b/app/Http/Controllers/ImpersonationController.php
new file mode 100644
index 000000000..af688b507
--- /dev/null
+++ b/app/Http/Controllers/ImpersonationController.php
@@ -0,0 +1,33 @@
+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');
+ }
+}
diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php
index 869e64d7e..a86084528 100644
--- a/app/Http/Kernel.php
+++ b/app/Http/Kernel.php
@@ -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' => [
diff --git a/app/Http/Middleware/Impersonation.php b/app/Http/Middleware/Impersonation.php
new file mode 100644
index 000000000..880b45299
--- /dev/null
+++ b/app/Http/Middleware/Impersonation.php
@@ -0,0 +1,24 @@
+has('impersonate') && Auth::user()->isAbleTo('snrStaff')) {
+ session()->put('impersonating_user', Auth::id());
+ Auth::onceUsingId(session('impersonate'));
+ }
+
+ return $next($request);
+ }
+}
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index 01e6b2750..d25d7db14 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -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;
@@ -24,6 +26,8 @@ public function boot(): void {
return toggleEnabled($toggle_name);
});
+ View::composer('inc.dashboard_head', ImpersonationComposer::class);
+
/**
* Paginate a standard Laravel Collection.
*
diff --git a/app/User.php b/app/User.php
index 08bb784ff..837ac01e4 100644
--- a/app/User.php
+++ b/app/User.php
@@ -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',
diff --git a/app/View/Composers/ImpersonationComposer.php b/app/View/Composers/ImpersonationComposer.php
new file mode 100644
index 000000000..97e347e53
--- /dev/null
+++ b/app/View/Composers/ImpersonationComposer.php
@@ -0,0 +1,32 @@
+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);
+ }
+ }
+}
diff --git a/resources/views/inc/dashboard_head.blade.php b/resources/views/inc/dashboard_head.blade.php
index 4efd8d2aa..ddfbcd3f5 100644
--- a/resources/views/inc/dashboard_head.blade.php
+++ b/resources/views/inc/dashboard_head.blade.php
@@ -1,26 +1,30 @@
-
+ @else
+ {{ Auth::user()->full_name }} - {{ Auth::user()->rating_short }}
+ @endif
+
+
+
diff --git a/resources/views/inc/messages.blade.php b/resources/views/inc/messages.blade.php
index 35a72786d..d50b64a62 100644
--- a/resources/views/inc/messages.blade.php
+++ b/resources/views/inc/messages.blade.php
@@ -17,6 +17,13 @@
@endif
+ @if(session('warning'))
+
+