--- /dev/null
+<?php namespace BookStack\Http\Controllers;
+
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Session;
+use Illuminate\Support\Str;
+
+class StatusController extends Controller
+{
+
+ /**
+ * Show the system status as a simple json page.
+ */
+ public function show()
+ {
+ $statuses = [
+ 'database' => $this->trueWithoutError(function () {
+ return DB::table('migrations')->count() > 0;
+ }),
+ 'cache' => $this->trueWithoutError(function () {
+ $rand = Str::random();
+ Cache::set('status_test', $rand);
+ return Cache::get('status_test') === $rand;
+ }),
+ 'session' => $this->trueWithoutError(function () {
+ $rand = Str::random();
+ Session::put('status_test', $rand);
+ return Session::get('status_test') === $rand;
+ }),
+ ];
+
+ $hasError = in_array(false, $statuses);
+ return response()->json($statuses, $hasError ? 500 : 200);
+ }
+
+ /**
+ * Check the callable passed returns true and does not throw an exception.
+ */
+ protected function trueWithoutError(callable $test): bool
+ {
+ try {
+ return $test() === true;
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+}
<?php
+Route::get('/status', 'StatusController@show');
Route::get('/robots.txt', 'HomeController@getRobots');
// Authenticated routes...
--- /dev/null
+<?php
+
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Session;
+use Tests\TestCase;
+
+class StatusTest extends TestCase
+{
+ public function test_returns_json_with_expected_results()
+ {
+ $resp = $this->get("/status");
+ $resp->assertStatus(200);
+ $resp->assertJson([
+ 'database' => true,
+ 'cache' => true,
+ 'session' => true,
+ ]);
+ }
+
+ public function test_returns_500_status_and_false_on_db_error()
+ {
+ DB::shouldReceive('table')->andThrow(new Exception());
+
+ $resp = $this->get("/status");
+ $resp->assertStatus(500);
+ $resp->assertJson([
+ 'database' => false,
+ ]);
+ }
+
+ public function test_returns_500_status_and_false_on_wrong_cache_return()
+ {
+ Cache::partialMock()->shouldReceive('get')->andReturn('cat');
+
+ $resp = $this->get("/status");
+ $resp->assertStatus(500);
+ $resp->assertJson([
+ 'cache' => false,
+ ]);
+ }
+
+ public function test_returns_500_status_and_false_on_wrong_session_return()
+ {
+ $session = Session::getFacadeRoot();
+ $mockSession = Mockery::mock($session)->makePartial();
+ Session::swap($mockSession);
+ $mockSession->shouldReceive('get')->andReturn('cat');
+
+ $resp = $this->get("/status");
+ $resp->assertStatus(500);
+ $resp->assertJson([
+ 'session' => false,
+ ]);
+ }
+}
\ No newline at end of file