浏览代码

Add diagnostics to error page and admin dashboard

Daniel Supernault 4 年之前
父节点
当前提交
64725ecce7

+ 25 - 0
app/Http/Controllers/AdminController.php

@@ -440,4 +440,29 @@ class AdminController extends Controller
 		$redirect = $news->published_at ? $news->permalink() : $news->editUrl();
 		return redirect($redirect);
 	}
+
+	public function diagnosticsHome(Request $request)
+	{
+		return view('admin.diagnostics.home');
+	}
+
+	public function diagnosticsDecrypt(Request $request)
+	{
+		$this->validate($request, [
+			'payload' => 'required'
+		]);
+
+		$key = 'exception_report:';
+		$decrypted = decrypt($request->input('payload'));
+
+		if(!starts_with($decrypted, $key)) {
+			abort(403, 'Can only decrypt error diagnostics');
+		}
+
+		$res = [
+			'decrypted' => substr($decrypted, strlen($key))
+		];
+
+		return response()->json($res);
+	}
 }

+ 111 - 0
resources/views/admin/diagnostics/home.blade.php

@@ -0,0 +1,111 @@
+@extends('admin.partial.template')
+
+@include('admin.settings.sidebar')
+
+@section('section')
+<div class="title mb-4">
+	<h3 class="font-weight-bold">Diagnostics</h3>
+	<p class="lead mb-0">Instance diagnostics</p>
+</div>
+
+<div class="pb-3 border-bottom">
+	<p class="font-weight-bold text-muted">
+		Information
+		<span class="small text-primary ml-3 copy-information cursor-pointer text-uppercase font-weight-bold">Copy</span>
+	</p>
+	<ul class="information">
+		<li>
+			<strong>APP_URL:</strong>
+			<span>{{config_cache('app.url')}}</span>
+		</li>
+		<li>
+			<strong>APP_DOMAIN:</strong>
+			<span>{{config_cache('pixelfed.domain.app')}}</span>
+		</li>
+		<li>
+			<strong>Version:</strong>
+			<span>{{config('pixelfed.version')}}</span>
+		</li>
+		<li>
+			<strong>PHP:</strong>
+			<span>{{phpversion()}}</span>
+		</li>
+		@foreach([
+			'bcmath',
+			'ctype',
+			'curl',
+			'intl',
+			'json',
+			'mbstring',
+			'openssl',
+			'redis'
+		] as $ext)
+		<li>
+			<strong>PHP-{{$ext}}:</strong>
+			<span>{{extension_loaded($ext) ? 'Installed' : 'Not installed'}}</span>
+		</li>
+		@endforeach
+		<li>
+			<strong>Database:</strong>
+			@php($v = explode(' ', DB::select('select version() as version')[0]->version))
+			<span>{{config('database.default')}} ({{count($v) == 1 ? $v[0] : $v[1]}})</span>
+		</li>
+		<li>
+			<strong>Bootstrap:</strong>
+			<span>{{is_writable(base_path('bootstrap/')) ? 'Writable' : 'Not writable'}}</span>
+		</li>
+		<li>
+			<strong>Storage:</strong>
+			<span>{{is_writable(base_path('storage/')) ? 'Writable' : 'Not writable'}}</span>
+		</li>
+	</ul>
+</div>
+<div class="pb-3 border-bottom">
+	<div class="form-group mb-0">
+		<div class="ml-n4 mr-n2 p-3">
+			<label class="font-weight-bold text-muted">Decrypt Payload</label>
+			<textarea class="form-control payload-input" rows="5" name="payload" placeholder="Enter payload here"></textarea>
+			<p class="help-text small text-muted mt-3 mb-0">The payload is from the "Something went wrong" page, anyone can copy the payload for you to decrypt.<br />Contents are encrypted due to potential sensitive information.</p>
+		</div>
+	</div>
+
+
+	<div class="form-group row">
+		<div class="col-12">
+			<button type="button" class="btn btn-primary font-weight-bold px-5 decrypt-payload">Decrypt</button>
+		</div>
+	</div>
+</div>
+@endsection
+
+@push('scripts')
+<script type="text/javascript" src="{{mix('js/components.js')}}"></script>
+<script type="text/javascript">
+	$('.decrypt-payload').on('click', function(e) {
+		let payload = document.querySelector('.payload-input').value;
+		axios.post('{{route('admin.diagnostics.decrypt')}}', {
+			'payload': payload
+		}).then(res => {
+			swal(
+				'Payload',
+				res.data.decrypted,
+				'info'
+			);
+			document.querySelector('.payload-input').value = '';
+		}).catch(err => {
+			swal(
+				'Error',
+				err.response.data.error,
+				'error'
+			);
+		});
+	});
+
+	$('.copy-information').on('click', function(e) {
+		let text = document.querySelector('.information').innerText;
+		let payload = '=======================\n Instance Diagnostic \n=======================\n' + text + '\n========= END =========\n';
+		navigator.clipboard.writeText(payload);
+		swal('Copied', 'Successfully copied diagnostic information to clipboard!', 'success');
+	});
+</script>
+@endpush

+ 14 - 0
resources/views/admin/partial/sidenav.blade.php

@@ -64,6 +64,13 @@
 						</a>
 					</li>
 
+					<li class="nav-item">
+						<a class="nav-link {{request()->is('*diagnostics*')?'active':''}}" href="{{route('admin.diagnostics')}}">
+							<i class="ni ni-bold-right text-primary"></i>
+							<span class="nav-link-text">Diagnostics <span class="badge badge-primary ml-1">NEW</span></span>
+						</a>
+					</li>
+
 					<li class="nav-item">
 						<a class="nav-link {{request()->is('*hashtags*')?'active':''}}" href="{{route('admin.hashtags')}}">
 							<i class="ni ni-bold-right text-primary"></i>
@@ -71,6 +78,13 @@
 						</a>
 					</li>
 
+					<li class="nav-item">
+						<a class="nav-link" href="/horizon">
+							<i class="ni ni-bold-right text-primary"></i>
+							<span class="nav-link-text">Horizon</span>
+						</a>
+					</li>
+
 					<li class="nav-item">
 						<a class="nav-link {{request()->is('*instances*')?'active':''}}" href="{{route('admin.instances')}}">
 							<i class="ni ni-bold-right text-primary"></i>

+ 37 - 3
resources/views/errors/500.blade.php

@@ -2,9 +2,43 @@
 
 @section('content')
 <div class="container">
-  <div class="error-page py-5 my-5 text-center">
-    <h3 class="font-weight-bold">Something went wrong</h3>
-    <p class="lead">We cannot process your request at this time, please try again later. <a href="/">Go back to Pixelfed.</a></p>
+  <div class="error-page py-5 my-5">
+  	<div class="text-center">
+		<h3 class="font-weight-bold">Something went wrong</h3>
+		<p class="lead py-3">We cannot process your request at this time, please try again later. </p>
+		<p class="mb-0">
+			<a href="/" class="btn btn-primary font-weight-bold">Go back to timeline</a>
+		</p>
+  	</div>
+  	@if($exception && $exception->getMessage())
+  	<hr>
+    <p class="text-center small payload text-uppercase font-weight-bold text-primary cursor-pointer" data-payload="{{encrypt('exception_report:'.$exception->getMessage()) ?? ''}}">
+    	Copy diagnostic details
+    </p>
+    @endif
   </div>
 </div>
 @endsection
+
+@push('scripts')
+<script type="text/javascript">
+	let payload = document.querySelector('.payload').getAttribute('data-payload');
+
+	$('.payload').click(function(e) {
+		try {
+			App.util.clipboard(payload);
+			swal(
+				'Copied',
+				'The error details have been copied. Please share this with the administrators to help fix this issue.',
+				'success'
+			);
+		} catch {
+			swal(
+				'Diagnostic Details',
+				payload,
+				'info'
+			);
+		}
+	});
+</script>
+@endpush

+ 3 - 0
routes/web.php

@@ -77,6 +77,9 @@ Route::domain(config('pixelfed.domain.admin'))->prefix('i/admin')->group(functio
 	Route::post('newsroom/edit/{id}', 'AdminController@newsroomUpdate');
 	Route::delete('newsroom/edit/{id}', 'AdminController@newsroomDelete');
 	Route::post('newsroom/create', 'AdminController@newsroomStore');
+
+	Route::get('diagnostics/home', 'AdminController@diagnosticsHome')->name('admin.diagnostics');
+	Route::post('diagnostics/decrypt', 'AdminController@diagnosticsDecrypt')->name('admin.diagnostics.decrypt');
 });
 
 Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofactor', 'localization','interstitial'])->group(function () {