diff --git a/app/Activity/Models/View.php b/app/Activity/Models/View.php index 512e08295..b593a7d27 100644 --- a/app/Activity/Models/View.php +++ b/app/Activity/Models/View.php @@ -41,7 +41,7 @@ class View extends Model public static function incrementFor(Viewable $viewable): int { $user = user(); - if (is_null($user) || $user->isDefault()) { + if (is_null($user) || $user->isGuest()) { return 0; } diff --git a/app/Activity/Tools/UserEntityWatchOptions.php b/app/Activity/Tools/UserEntityWatchOptions.php index 231204fdf..559d7903d 100644 --- a/app/Activity/Tools/UserEntityWatchOptions.php +++ b/app/Activity/Tools/UserEntityWatchOptions.php @@ -22,7 +22,7 @@ class UserEntityWatchOptions public function canWatch(): bool { - return $this->user->can('receive-notifications') && !$this->user->isDefault(); + return $this->user->can('receive-notifications') && !$this->user->isGuest(); } public function getWatchLevel(): string diff --git a/app/App/Providers/AuthServiceProvider.php b/app/App/Providers/AuthServiceProvider.php index dc482ce33..26d180310 100644 --- a/app/App/Providers/AuthServiceProvider.php +++ b/app/App/Providers/AuthServiceProvider.php @@ -9,6 +9,7 @@ use BookStack\Access\LdapService; use BookStack\Access\LoginService; use BookStack\Access\RegistrationService; use BookStack\Api\ApiTokenGuard; +use BookStack\Users\Models\User; use Illuminate\Support\Facades\Auth; use Illuminate\Support\ServiceProvider; use Illuminate\Validation\Rules\Password; @@ -65,5 +66,11 @@ class AuthServiceProvider extends ServiceProvider Auth::provider('external-users', function ($app, array $config) { return new ExternalBaseUserProvider($config['model']); }); + + // Bind and provide the default system user as a singleton to the app instance when needed. + // This effectively "caches" fetching the user at an app-instance level. + $this->app->singleton('users.default', function () { + return User::query()->where('system_name', '=', 'public')->first(); + }); } } diff --git a/app/App/helpers.php b/app/App/helpers.php index 00d3e9243..b59a63448 100644 --- a/app/App/helpers.php +++ b/app/App/helpers.php @@ -35,23 +35,7 @@ function versioned_asset(string $file = ''): string */ function user(): User { - return auth()->user() ?: User::getDefault(); -} - -/** - * Check if current user is a signed in user. - */ -function signedInUser(): bool -{ - return auth()->user() && !auth()->user()->isDefault(); -} - -/** - * Check if the current user has general access. - */ -function hasAppAccess(): bool -{ - return !auth()->guest() || setting('app-public'); + return auth()->user() ?: User::getGuest(); } /** @@ -61,7 +45,7 @@ function hasAppAccess(): bool function userCan(string $permission, Model $ownable = null): bool { if ($ownable === null) { - return user() && user()->can($permission); + return user()->can($permission); } // Check permission on ownable item diff --git a/app/Entities/Queries/RecentlyViewed.php b/app/Entities/Queries/RecentlyViewed.php index ffa346888..5895b97a2 100644 --- a/app/Entities/Queries/RecentlyViewed.php +++ b/app/Entities/Queries/RecentlyViewed.php @@ -10,7 +10,7 @@ class RecentlyViewed extends EntityQuery public function run(int $count, int $page): Collection { $user = user(); - if ($user === null || $user->isDefault()) { + if ($user === null || $user->isGuest()) { return collect(); } diff --git a/app/Entities/Queries/TopFavourites.php b/app/Entities/Queries/TopFavourites.php index cbccf35b0..a2f8d9ea1 100644 --- a/app/Entities/Queries/TopFavourites.php +++ b/app/Entities/Queries/TopFavourites.php @@ -10,7 +10,7 @@ class TopFavourites extends EntityQuery public function run(int $count, int $skip = 0) { $user = user(); - if ($user->isDefault()) { + if ($user->isGuest()) { return collect(); } diff --git a/app/Http/Controller.php b/app/Http/Controller.php index 584cea3aa..6e81dfd65 100644 --- a/app/Http/Controller.php +++ b/app/Http/Controller.php @@ -71,7 +71,7 @@ abstract class Controller extends BaseController */ protected function preventGuestAccess(): void { - if (!signedInUser()) { + if (user()->isGuest()) { $this->showPermissionError(); } } diff --git a/app/Http/Middleware/ApiAuthenticate.php b/app/Http/Middleware/ApiAuthenticate.php index b348473cf..5f3ad3168 100644 --- a/app/Http/Middleware/ApiAuthenticate.php +++ b/app/Http/Middleware/ApiAuthenticate.php @@ -31,7 +31,7 @@ class ApiAuthenticate { // Return if the user is already found to be signed in via session-based auth. // This is to make it easy to browser the API via browser after just logging into the system. - if (signedInUser() || session()->isStarted()) { + if (!user()->isGuest() || session()->isStarted()) { if (!$this->sessionUserHasApiAccess()) { throw new ApiAuthException(trans('errors.api_user_no_api_permission'), 403); } @@ -53,6 +53,6 @@ class ApiAuthenticate { $hasApiPermission = user()->can('access-api'); - return $hasApiPermission && hasAppAccess(); + return $hasApiPermission && user()->hasAppAccess(); } } diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index a32029112..6a5c6e354 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -12,7 +12,7 @@ class Authenticate */ public function handle(Request $request, Closure $next) { - if (!hasAppAccess()) { + if (!user()->hasAppAccess()) { if ($request->ajax()) { return response('Unauthorized.', 401); } diff --git a/app/Http/Middleware/PreventAuthenticatedResponseCaching.php b/app/Http/Middleware/PreventAuthenticatedResponseCaching.php index 60c913811..0a90ddd9e 100644 --- a/app/Http/Middleware/PreventAuthenticatedResponseCaching.php +++ b/app/Http/Middleware/PreventAuthenticatedResponseCaching.php @@ -20,7 +20,7 @@ class PreventAuthenticatedResponseCaching /** @var Response $response */ $response = $next($request); - if (signedInUser()) { + if (!user()->isGuest()) { $response->headers->set('Cache-Control', 'max-age=0, no-store, private'); $response->headers->set('Pragma', 'no-cache'); $response->headers->set('Expires', 'Sun, 12 Jul 2015 19:01:00 GMT'); diff --git a/app/Settings/SettingController.php b/app/Settings/SettingController.php index bd55222f2..bdbc3c78a 100644 --- a/app/Settings/SettingController.php +++ b/app/Settings/SettingController.php @@ -34,7 +34,7 @@ class SettingController extends Controller return view('settings.' . $category, [ 'category' => $category, 'version' => $version, - 'guestUser' => User::getDefault(), + 'guestUser' => User::getGuest(), ]); } diff --git a/app/Settings/SettingService.php b/app/Settings/SettingService.php index 1c5cbdf5a..31debdaea 100644 --- a/app/Settings/SettingService.php +++ b/app/Settings/SettingService.php @@ -47,7 +47,7 @@ class SettingService $default = config('setting-defaults.user.' . $key, false); } - if ($user->isDefault()) { + if ($user->isGuest()) { return $this->getFromSession($key, $default); } @@ -206,7 +206,7 @@ class SettingService */ public function putUser(User $user, string $key, string $value): bool { - if ($user->isDefault()) { + if ($user->isGuest()) { session()->put($key, $value); return true; diff --git a/app/Translation/LanguageManager.php b/app/Translation/LanguageManager.php index ec116fd70..f3432d038 100644 --- a/app/Translation/LanguageManager.php +++ b/app/Translation/LanguageManager.php @@ -75,7 +75,7 @@ class LanguageManager return $default; } - if ($user->isDefault() && config('app.auto_detect_locale')) { + if ($user->isGuest() && config('app.auto_detect_locale')) { return $this->autoDetectLocale($request, $default); } diff --git a/app/Users/Controllers/UserSearchController.php b/app/Users/Controllers/UserSearchController.php index 1c7786f58..b6f37bce0 100644 --- a/app/Users/Controllers/UserSearchController.php +++ b/app/Users/Controllers/UserSearchController.php @@ -14,7 +14,7 @@ class UserSearchController extends Controller */ public function forSelect(Request $request) { - $hasPermission = signedInUser() && ( + $hasPermission = !user()->isGuest() && ( userCan('users-manage') || userCan('restrictions-manage-own') || userCan('restrictions-manage-all') diff --git a/app/Users/Models/User.php b/app/Users/Models/User.php index 2479521a2..1eeacfe2e 100644 --- a/app/Users/Models/User.php +++ b/app/Users/Models/User.php @@ -88,38 +88,31 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon */ protected string $avatarUrl = ''; - /** - * This holds the default user when loaded. - */ - protected static ?User $defaultUser = null; - /** * Returns the default public user. + * Fetches from the container as a singleton to effectively cache at an app level. */ - public static function getDefault(): self + public static function getGuest(): self { - if (!is_null(static::$defaultUser)) { - return static::$defaultUser; - } - - static::$defaultUser = static::query()->where('system_name', '=', 'public')->first(); - - return static::$defaultUser; - } - - public static function clearDefault(): void - { - static::$defaultUser = null; + return app()->make('users.default'); } /** * Check if the user is the default public user. */ - public function isDefault(): bool + public function isGuest(): bool { return $this->system_name === 'public'; } + /** + * Check if the user has general access to the application. + */ + public function hasAppAccess(): bool + { + return !$this->isGuest() || setting('app-public'); + } + /** * The roles that belong to the user. * diff --git a/resources/views/books/show.blade.php b/resources/views/books/show.blade.php index e3aef845c..9e7df4156 100644 --- a/resources/views/books/show.blade.php +++ b/resources/views/books/show.blade.php @@ -142,7 +142,7 @@ @if($watchOptions->canWatch() && !$watchOptions->isWatching()) @include('entities.watch-action', ['entity' => $book]) @endif - @if(signedInUser()) + @if(!user()->isGuest()) @include('entities.favourite-action', ['entity' => $book]) @endif @if(userCan('content-export')) diff --git a/resources/views/chapters/show.blade.php b/resources/views/chapters/show.blade.php index 3cb512ccc..0e5224d54 100644 --- a/resources/views/chapters/show.blade.php +++ b/resources/views/chapters/show.blade.php @@ -160,7 +160,7 @@ @if($watchOptions->canWatch() && !$watchOptions->isWatching()) @include('entities.watch-action', ['entity' => $chapter]) @endif - @if(signedInUser()) + @if(!user()->isGuest()) @include('entities.favourite-action', ['entity' => $chapter]) @endif @if(userCan('content-export')) diff --git a/resources/views/common/header-user-menu.blade.php b/resources/views/common/header-user-menu.blade.php new file mode 100644 index 000000000..8ba750f95 --- /dev/null +++ b/resources/views/common/header-user-menu.blade.php @@ -0,0 +1,47 @@ +