Merge pull request #5607 from BookStackApp/system_info_endpoint
API: System info endpoint
This commit is contained in:
		
						commit
						59e2c5e52a
					
				| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
 | 
			
		||||
namespace BookStack\Api;
 | 
			
		||||
 | 
			
		||||
use BookStack\App\AppVersion;
 | 
			
		||||
use BookStack\Http\ApiController;
 | 
			
		||||
use Exception;
 | 
			
		||||
use Illuminate\Contracts\Container\BindingResolutionException;
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +26,7 @@ class ApiDocsGenerator
 | 
			
		|||
     */
 | 
			
		||||
    public static function generateConsideringCache(): Collection
 | 
			
		||||
    {
 | 
			
		||||
        $appVersion = trim(file_get_contents(base_path('version')));
 | 
			
		||||
        $appVersion = AppVersion::get();
 | 
			
		||||
        $cacheKey = 'api-docs::' . $appVersion;
 | 
			
		||||
        $isProduction = config('app.env') === 'production';
 | 
			
		||||
        $cacheVal = $isProduction ? Cache::get($cacheKey) : null;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
namespace BookStack\App;
 | 
			
		||||
 | 
			
		||||
class AppVersion
 | 
			
		||||
{
 | 
			
		||||
    protected static string $version = '';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the application's version number from its top-level `version` text file.
 | 
			
		||||
     */
 | 
			
		||||
    public static function get(): string
 | 
			
		||||
    {
 | 
			
		||||
        if (!empty(static::$version)) {
 | 
			
		||||
            return static::$version;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $versionFile = base_path('version');
 | 
			
		||||
        $version = trim(file_get_contents($versionFile));
 | 
			
		||||
        static::$version = $version;
 | 
			
		||||
 | 
			
		||||
        return $version;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,31 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
namespace BookStack\App;
 | 
			
		||||
 | 
			
		||||
use BookStack\Http\ApiController;
 | 
			
		||||
use Illuminate\Http\JsonResponse;
 | 
			
		||||
 | 
			
		||||
class SystemApiController extends ApiController
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Read details regarding the BookStack instance.
 | 
			
		||||
     * Some details may be null where not set, like the app logo for example.
 | 
			
		||||
     */
 | 
			
		||||
    public function read(): JsonResponse
 | 
			
		||||
    {
 | 
			
		||||
        $logoSetting = setting('app-logo', '');
 | 
			
		||||
        if ($logoSetting === 'none') {
 | 
			
		||||
            $logo = null;
 | 
			
		||||
        } else {
 | 
			
		||||
            $logo = $logoSetting ? url($logoSetting) : url('/logo.png');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return response()->json([
 | 
			
		||||
            'version' => AppVersion::get(),
 | 
			
		||||
            'instance_id' => setting('instance-id'),
 | 
			
		||||
            'app_name' => setting('app-name'),
 | 
			
		||||
            'app_logo' => $logo,
 | 
			
		||||
            'base_url' => url('/'),
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
use BookStack\App\AppVersion;
 | 
			
		||||
use BookStack\App\Model;
 | 
			
		||||
use BookStack\Facades\Theme;
 | 
			
		||||
use BookStack\Permissions\PermissionApplicator;
 | 
			
		||||
| 
						 | 
				
			
			@ -13,12 +14,7 @@ use BookStack\Users\Models\User;
 | 
			
		|||
 */
 | 
			
		||||
function versioned_asset(string $file = ''): string
 | 
			
		||||
{
 | 
			
		||||
    static $version = null;
 | 
			
		||||
 | 
			
		||||
    if (is_null($version)) {
 | 
			
		||||
        $versionFile = base_path('version');
 | 
			
		||||
        $version = trim(file_get_contents($versionFile));
 | 
			
		||||
    }
 | 
			
		||||
    $version = AppVersion::get();
 | 
			
		||||
 | 
			
		||||
    $additional = '';
 | 
			
		||||
    if (config('app.env') === 'development') {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
 | 
			
		||||
namespace BookStack\Exceptions;
 | 
			
		||||
 | 
			
		||||
use BookStack\App\AppVersion;
 | 
			
		||||
use Illuminate\Contracts\Foundation\ExceptionRenderer;
 | 
			
		||||
 | 
			
		||||
class BookStackExceptionHandlerPage implements ExceptionRenderer
 | 
			
		||||
| 
						 | 
				
			
			@ -30,9 +31,7 @@ class BookStackExceptionHandlerPage implements ExceptionRenderer
 | 
			
		|||
        return [
 | 
			
		||||
            'PHP Version'       => phpversion(),
 | 
			
		||||
            'BookStack Version' => $this->safeReturn(function () {
 | 
			
		||||
                $versionFile = base_path('version');
 | 
			
		||||
 | 
			
		||||
                return trim(file_get_contents($versionFile));
 | 
			
		||||
                return AppVersion::get();
 | 
			
		||||
            }, 'unknown'),
 | 
			
		||||
            'Theme Configured' => $this->safeReturn(function () {
 | 
			
		||||
                return config('view.theme');
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
 | 
			
		||||
namespace BookStack\Exports\ZipExports;
 | 
			
		||||
 | 
			
		||||
use BookStack\App\AppVersion;
 | 
			
		||||
use BookStack\Entities\Models\Book;
 | 
			
		||||
use BookStack\Entities\Models\Chapter;
 | 
			
		||||
use BookStack\Entities\Models\Page;
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +71,7 @@ class ZipExportBuilder
 | 
			
		|||
        $this->data['exported_at'] = date(DATE_ATOM);
 | 
			
		||||
        $this->data['instance'] = [
 | 
			
		||||
            'id'      => setting('instance-id', ''),
 | 
			
		||||
            'version' => trim(file_get_contents(base_path('version'))),
 | 
			
		||||
            'version' => AppVersion::get(),
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        $zipFile = tempnam(sys_get_temp_dir(), 'bszip-');
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
namespace BookStack\Settings;
 | 
			
		||||
 | 
			
		||||
use BookStack\Activity\ActivityType;
 | 
			
		||||
use BookStack\App\AppVersion;
 | 
			
		||||
use BookStack\Entities\Tools\TrashCan;
 | 
			
		||||
use BookStack\Http\Controller;
 | 
			
		||||
use BookStack\References\ReferenceStore;
 | 
			
		||||
| 
						 | 
				
			
			@ -19,14 +20,11 @@ class MaintenanceController extends Controller
 | 
			
		|||
        $this->checkPermission('settings-manage');
 | 
			
		||||
        $this->setPageTitle(trans('settings.maint'));
 | 
			
		||||
 | 
			
		||||
        // Get application version
 | 
			
		||||
        $version = trim(file_get_contents(base_path('version')));
 | 
			
		||||
 | 
			
		||||
        // Recycle bin details
 | 
			
		||||
        $recycleStats = $trashCan->getTrashedCounts();
 | 
			
		||||
 | 
			
		||||
        return view('settings.maintenance', [
 | 
			
		||||
            'version'      => $version,
 | 
			
		||||
            'version'      => AppVersion::get(),
 | 
			
		||||
            'recycleStats' => $recycleStats,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
namespace BookStack\Settings;
 | 
			
		||||
 | 
			
		||||
use BookStack\Activity\ActivityType;
 | 
			
		||||
use BookStack\App\AppVersion;
 | 
			
		||||
use BookStack\Http\Controller;
 | 
			
		||||
use BookStack\Users\Models\User;
 | 
			
		||||
use Illuminate\Http\Request;
 | 
			
		||||
| 
						 | 
				
			
			@ -26,12 +27,9 @@ class SettingController extends Controller
 | 
			
		|||
        $this->checkPermission('settings-manage');
 | 
			
		||||
        $this->setPageTitle(trans('settings.settings'));
 | 
			
		||||
 | 
			
		||||
        // Get application version
 | 
			
		||||
        $version = trim(file_get_contents(base_path('version')));
 | 
			
		||||
 | 
			
		||||
        return view('settings.categories.' . $category, [
 | 
			
		||||
            'category'  => $category,
 | 
			
		||||
            'version'   => $version,
 | 
			
		||||
            'version'   => AppVersion::get(),
 | 
			
		||||
            'guestUser' => User::getGuest(),
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
{
 | 
			
		||||
  "version": "v25.02.4",
 | 
			
		||||
  "instance_id": "1234abcd-cc12-7808-af0a-264cb0cbd611",
 | 
			
		||||
  "app_name": "My BookStack Instance",
 | 
			
		||||
  "app_logo": "https://docs.example.com/uploads/images/system/2025-05/cat-icon.png",
 | 
			
		||||
  "base_url": "https://docs.example.com"
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -8,6 +8,7 @@
 | 
			
		|||
 | 
			
		||||
use BookStack\Activity\Controllers\AuditLogApiController;
 | 
			
		||||
use BookStack\Api\ApiDocsController;
 | 
			
		||||
use BookStack\App\SystemApiController;
 | 
			
		||||
use BookStack\Entities\Controllers as EntityControllers;
 | 
			
		||||
use BookStack\Exports\Controllers as ExportControllers;
 | 
			
		||||
use BookStack\Permissions\ContentPermissionApiController;
 | 
			
		||||
| 
						 | 
				
			
			@ -92,3 +93,5 @@ Route::get('content-permissions/{contentType}/{contentId}', [ContentPermissionAp
 | 
			
		|||
Route::put('content-permissions/{contentType}/{contentId}', [ContentPermissionApiController::class, 'update']);
 | 
			
		||||
 | 
			
		||||
Route::get('audit-log', [AuditLogApiController::class, 'list']);
 | 
			
		||||
 | 
			
		||||
Route::get('system', [SystemApiController::class, 'read']);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Api;
 | 
			
		||||
 | 
			
		||||
use BookStack\Activity\ActivityType;
 | 
			
		||||
use BookStack\Facades\Activity;
 | 
			
		||||
use Tests\Api\TestsApi;
 | 
			
		||||
use Tests\TestCase;
 | 
			
		||||
 | 
			
		||||
class SystemApiTest extends TestCase
 | 
			
		||||
{
 | 
			
		||||
    use TestsApi;
 | 
			
		||||
 | 
			
		||||
    public function test_read_returns_app_info(): void
 | 
			
		||||
    {
 | 
			
		||||
        $resp = $this->actingAsApiEditor()->get('/api/system');
 | 
			
		||||
        $data = $resp->json();
 | 
			
		||||
 | 
			
		||||
        $this->assertStringStartsWith('v', $data['version']);
 | 
			
		||||
        $this->assertEquals(setting('instance-id'), $data['instance_id']);
 | 
			
		||||
        $this->assertEquals(setting('app-name'), $data['app_name']);
 | 
			
		||||
        $this->assertEquals(url('/logo.png'), $data['app_logo']);
 | 
			
		||||
        $this->assertEquals(url('/'), $data['base_url']);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue