From 6eda1c1fb28142d432bf0ca05d7eaba9bf16f0d0 Mon Sep 17 00:00:00 2001 From: Dan Brown <ssddanbrown@googlemail.com> Date: Sun, 17 Jan 2021 13:21:57 +0000 Subject: [PATCH] Added status endpoint For #2467 --- app/Http/Controllers/StatusController.php | 47 +++++++++++++++++++ routes/web.php | 1 + tests/StatusTest.php | 56 +++++++++++++++++++++++ version | 2 +- 4 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 app/Http/Controllers/StatusController.php create mode 100644 tests/StatusTest.php diff --git a/app/Http/Controllers/StatusController.php b/app/Http/Controllers/StatusController.php new file mode 100644 index 000000000..9f4ed4d89 --- /dev/null +++ b/app/Http/Controllers/StatusController.php @@ -0,0 +1,47 @@ +<?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; + } + } +} diff --git a/routes/web.php b/routes/web.php index e8f217862..64d08e165 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,5 +1,6 @@ <?php +Route::get('/status', 'StatusController@show'); Route::get('/robots.txt', 'HomeController@getRobots'); // Authenticated routes... diff --git a/tests/StatusTest.php b/tests/StatusTest.php new file mode 100644 index 000000000..ca150d0d6 --- /dev/null +++ b/tests/StatusTest.php @@ -0,0 +1,56 @@ +<?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 diff --git a/version b/version index 31c2e1d4b..92d9faea7 100644 --- a/version +++ b/version @@ -1 +1 @@ -v0.30-dev +v0.32-dev