diff --git a/app/Http/Controllers/Admin/AdminUserRoleHistoryController.php b/app/Http/Controllers/Admin/AdminUserRoleHistoryController.php new file mode 100644 index 000000000..2175414eb --- /dev/null +++ b/app/Http/Controllers/Admin/AdminUserRoleHistoryController.php @@ -0,0 +1,108 @@ +setAdminPrefs(); + + $meta_title = $title = 'User Role History'; + + // Get all roles for filter + $roles = Role::all()->pluck('name', 'id')->toArray(); + + // Build query + $query = UserRoleHistory::with(['user', 'oldRole', 'newRole', 'changedByUser']) + ->orderBy('created_at', 'desc'); + + // Apply filters + if ($request->has('user_id') && !empty($request->input('user_id'))) { + $query->where('user_id', $request->input('user_id')); + } + + if ($request->has('username') && !empty($request->input('username'))) { + $query->whereHas('user', function ($q) use ($request) { + $q->where('username', 'like', '%' . $request->input('username') . '%'); + }); + } + + if ($request->has('role_id') && !empty($request->input('role_id'))) { + $query->where(function ($q) use ($request) { + $q->where('old_role_id', $request->input('role_id')) + ->orWhere('new_role_id', $request->input('role_id')); + }); + } + + if ($request->has('change_reason') && !empty($request->input('change_reason'))) { + $query->where('change_reason', 'like', '%' . $request->input('change_reason') . '%'); + } + + if ($request->has('date_from') && !empty($request->input('date_from'))) { + $query->where('created_at', '>=', $request->input('date_from') . ' 00:00:00'); + } + + if ($request->has('date_to') && !empty($request->input('date_to'))) { + $query->where('created_at', '<=', $request->input('date_to') . ' 23:59:59'); + } + + // Pagination + $page = $request->has('page') && is_numeric($request->input('page')) ? $request->input('page') : 1; + $perPage = config('nntmux.items_per_page', 50); + + $results = $query->paginate($perPage, ['*'], 'page', $page); + + $this->viewData = array_merge($this->viewData, [ + 'title' => $title, + 'meta_title' => $meta_title, + 'history' => $results, + 'roles' => $roles, + 'filters' => [ + 'user_id' => $request->input('user_id', ''), + 'username' => $request->input('username', ''), + 'role_id' => $request->input('role_id', ''), + 'change_reason' => $request->input('change_reason', ''), + 'date_from' => $request->input('date_from', ''), + 'date_to' => $request->input('date_to', ''), + ], + ]); + + return view('admin.user-role-history.index', $this->viewData); + } + + /** + * Display role history for a specific user + */ + public function show(Request $request, int $userId) + { + $this->setAdminPrefs(); + + $user = User::findOrFail($userId); + $meta_title = $title = 'Role History for ' . $user->username; + + $history = UserRoleHistory::with(['oldRole', 'newRole', 'changedByUser']) + ->where('user_id', $userId) + ->orderBy('created_at', 'desc') + ->paginate(config('nntmux.items_per_page', 50)); + + $this->viewData = array_merge($this->viewData, [ + 'title' => $title, + 'meta_title' => $meta_title, + 'user' => $user, + 'history' => $history, + ]); + + return view('admin.user-role-history.show', $this->viewData); + } +} + diff --git a/resources/views/admin/user-role-history/index.blade.php b/resources/views/admin/user-role-history/index.blade.php new file mode 100644 index 000000000..9927b57a9 --- /dev/null +++ b/resources/views/admin/user-role-history/index.blade.php @@ -0,0 +1,212 @@ +@extends('layouts.admin') + +@section('content') +
+
+ +
+
+

+ {{ $title }} +

+
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+ +
+
+ + +
+ + + + + + + + + + + + + + + + + @forelse($history as $record) + + + + + + + + + + + + + @empty + + + + @endforelse + +
+ Date + + User + + Old Role + + New Role + + Old Expiry + + New Expiry + + Stacked + + Reason + + Changed By + + Actions +
+ {{ $record->created_at->format('Y-m-d H:i:s') }} + + @if($record->user) + + {{ $record->user->username }} + + @else + User #{{ $record->user_id }} + @endif + + @if($record->oldRole) + + {{ $record->oldRole->name }} + + @else + - + @endif + + @if($record->newRole) + + {{ $record->newRole->name }} + + @else + - + @endif + + {{ $record->old_expiry_date ? $record->old_expiry_date->format('Y-m-d H:i') : '-' }} + + {{ $record->new_expiry_date ? $record->new_expiry_date->format('Y-m-d H:i') : '-' }} + + @if($record->is_stacked) + + Yes + + @else + No + @endif + + {{ $record->change_reason ?? '-' }} + + @if($record->changedByUser) + {{ $record->changedByUser->username }} + @else + System + @endif + +
+ @if($record->user) + + + + + + + @endif +
+
+ No role history records found +
+
+ + + @if($history->hasPages()) +
+ {{ $history->links() }} +
+ @endif +
+
+@endsection + diff --git a/resources/views/admin/user-role-history/show.blade.php b/resources/views/admin/user-role-history/show.blade.php new file mode 100644 index 000000000..005468607 --- /dev/null +++ b/resources/views/admin/user-role-history/show.blade.php @@ -0,0 +1,173 @@ +@extends('layouts.admin') + +@section('content') +
+
+ +
+
+

+ {{ $title }} +

+ +
+
+ + +
+
+
+ +
{{ $user->username }}
+
+
+ +
{{ $user->email }}
+
+
+ +
+ @if($user->role) + + {{ $user->role->name }} + + @else + No role assigned + @endif +
+
+
+ @if($user->rolechangedate) +
+ +
+ {{ \Carbon\Carbon::parse($user->rolechangedate)->format('Y-m-d H:i:s') }} + @if(\Carbon\Carbon::parse($user->rolechangedate)->isPast()) + + Expired + + @else + + Active + + @endif +
+
+ @endif +
+ + +
+ + + + + + + + + + + + + + + + @forelse($history as $record) + + + + + + + + + + + + @empty + + + + @endforelse + +
+ Date + + Old Role + + New Role + + Old Expiry + + New Expiry + + Effective Date + + Stacked + + Reason + + Changed By +
+ {{ $record->created_at->format('Y-m-d H:i:s') }} + + @if($record->oldRole) + + {{ $record->oldRole->name }} + + @else + - + @endif + + @if($record->newRole) + + {{ $record->newRole->name }} + + @else + - + @endif + + {{ $record->old_expiry_date ? $record->old_expiry_date->format('Y-m-d H:i') : '-' }} + + {{ $record->new_expiry_date ? $record->new_expiry_date->format('Y-m-d H:i') : '-' }} + + {{ $record->effective_date ? $record->effective_date->format('Y-m-d H:i') : '-' }} + + @if($record->is_stacked) + + Yes + + @else + No + @endif + + {{ $record->change_reason ?? '-' }} + + @if($record->changedByUser) + {{ $record->changedByUser->username }} + @else + System + @endif +
+ No role history records found for this user +
+
+ + + @if($history->hasPages()) +
+ {{ $history->links() }} +
+ @endif +
+
+@endsection + diff --git a/resources/views/admin/users/edit.blade.php b/resources/views/admin/users/edit.blade.php index 9750c68f8..82e71833d 100644 --- a/resources/views/admin/users/edit.blade.php +++ b/resources/views/admin/users/edit.blade.php @@ -5,9 +5,16 @@
-

- {{ $title }} -

+
+

+ {{ $title }} +

+ @if(!empty($user['id'])) + + View Role History + + @endif +
diff --git a/resources/views/admin/users/index.blade.php b/resources/views/admin/users/index.blade.php index 3003d1616..ac1e98bf4 100644 --- a/resources/views/admin/users/index.blade.php +++ b/resources/views/admin/users/index.blade.php @@ -315,6 +315,11 @@ title="Edit"> + + + @if(!$user->verified)
@csrf diff --git a/resources/views/partials/admin-menu.blade.php b/resources/views/partials/admin-menu.blade.php index c7b7a72c9..b5ec1747c 100644 --- a/resources/views/partials/admin-menu.blade.php +++ b/resources/views/partials/admin-menu.blade.php @@ -19,6 +19,7 @@ diff --git a/routes/web.php b/routes/web.php index 46ce9d4eb..cb0729d18 100644 --- a/routes/web.php +++ b/routes/web.php @@ -36,6 +36,7 @@ use App\Http\Controllers\Admin\AdminShowsController; use App\Http\Controllers\Admin\AdminSiteController; use App\Http\Controllers\Admin\AdminTmuxController; use App\Http\Controllers\Admin\AdminUserController; +use App\Http\Controllers\Admin\AdminUserRoleHistoryController; use App\Http\Controllers\Admin\DeletedUsersController; use App\Http\Controllers\AdultController; use App\Http\Controllers\AjaxController; @@ -194,6 +195,8 @@ Route::middleware('role:Admin', '2fa')->prefix('admin')->group(function () { Route::post('user-delete', [AdminUserController::class, 'destroy'])->name('admin.user-delete'); Route::post('verify', [AdminUserController::class, 'verify'])->name('admin.verify'); Route::post('resendverification', [AdminUserController::class, 'resendVerification'])->name('admin.resend-verification'); + Route::get('user-role-history', [AdminUserRoleHistoryController::class, 'index'])->name('admin.user-role-history'); + Route::get('user-role-history/{userId}', [AdminUserRoleHistoryController::class, 'show'])->name('admin.user-role-history.show'); Route::match(['GET', 'POST'], 'site-edit', [AdminSiteController::class, 'edit'])->name('admin.site-edit'); Route::get('site-stats', [AdminSiteController::class, 'stats'])->name('admin.site-stats'); Route::get('role-list', [AdminRoleController::class, 'index'])->name('admin.role-list');