diff --git a/app/Auth/User.php b/app/Auth/User.php index 259b8eec0..e5a8a3931 100644 --- a/app/Auth/User.php +++ b/app/Auth/User.php @@ -168,14 +168,14 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon */ public function getAvatar($size = 50) { - $default = baseUrl('/user_avatar.png'); + $default = url('/user_avatar.png'); $imageId = $this->image_id; if ($imageId === 0 || $imageId === '0' || $imageId === null) { return $default; } try { - $avatar = $this->avatar ? baseUrl($this->avatar->getThumb($size, $size, false)) : $default; + $avatar = $this->avatar ? url($this->avatar->getThumb($size, $size, false)) : $default; } catch (\Exception $err) { $avatar = $default; } @@ -197,7 +197,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon */ public function getEditUrl() { - return baseUrl('/settings/users/' . $this->id); + return url('/settings/users/' . $this->id); } /** @@ -206,7 +206,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon */ public function getProfileUrl() { - return baseUrl('/user/' . $this->id); + return url('/user/' . $this->id); } /** diff --git a/app/Config/app.php b/app/Config/app.php index aaeafb98d..0a0c17a53 100755 --- a/app/Config/app.php +++ b/app/Config/app.php @@ -45,6 +45,10 @@ return [ // and used by BookStack in URL generation. 'url' => env('APP_URL', '') === 'http://bookstack.dev' ? '' : env('APP_URL', ''), + // Rewrite URL, Used to rewrite the base of request URLs + // for scenarios + 'url_base_rewrite' => env('APP_URL_BASE_REWRITE', null), + // Application timezone for back-end date functions. 'timezone' => env('APP_TIMEZONE', 'UTC'), diff --git a/app/Entities/Book.php b/app/Entities/Book.php index decdde9dc..7d3d5e4ae 100644 --- a/app/Entities/Book.php +++ b/app/Entities/Book.php @@ -25,9 +25,9 @@ class Book extends Entity public function getUrl($path = false) { if ($path !== false) { - return baseUrl('/books/' . urlencode($this->slug) . '/' . trim($path, '/')); + return url('/books/' . urlencode($this->slug) . '/' . trim($path, '/')); } - return baseUrl('/books/' . urlencode($this->slug)); + return url('/books/' . urlencode($this->slug)); } /** @@ -44,7 +44,7 @@ class Book extends Entity } try { - $cover = $this->cover ? baseUrl($this->cover->getThumb($width, $height, false)) : $default; + $cover = $this->cover ? url($this->cover->getThumb($width, $height, false)) : $default; } catch (\Exception $err) { $cover = $default; } diff --git a/app/Entities/Bookshelf.php b/app/Entities/Bookshelf.php index c8f8b990c..db6685688 100644 --- a/app/Entities/Bookshelf.php +++ b/app/Entities/Bookshelf.php @@ -39,9 +39,9 @@ class Bookshelf extends Entity public function getUrl($path = false) { if ($path !== false) { - return baseUrl('/shelves/' . urlencode($this->slug) . '/' . trim($path, '/')); + return url('/shelves/' . urlencode($this->slug) . '/' . trim($path, '/')); } - return baseUrl('/shelves/' . urlencode($this->slug)); + return url('/shelves/' . urlencode($this->slug)); } /** @@ -59,7 +59,7 @@ class Bookshelf extends Entity } try { - $cover = $this->cover ? baseUrl($this->cover->getThumb($width, $height, false)) : $default; + $cover = $this->cover ? url($this->cover->getThumb($width, $height, false)) : $default; } catch (\Exception $err) { $cover = $default; } diff --git a/app/Entities/Chapter.php b/app/Entities/Chapter.php index 936404758..b204f1903 100644 --- a/app/Entities/Chapter.php +++ b/app/Entities/Chapter.php @@ -42,10 +42,13 @@ class Chapter extends Entity public function getUrl($path = false) { $bookSlug = $this->getAttribute('bookSlug') ? $this->getAttribute('bookSlug') : $this->book->slug; + $fullPath = '/books/' . urlencode($bookSlug) . '/chapter/' . urlencode($this->slug); + if ($path !== false) { - return baseUrl('/books/' . urlencode($bookSlug) . '/chapter/' . urlencode($this->slug) . '/' . trim($path, '/')); + $fullPath .= '/' . trim($path, '/'); } - return baseUrl('/books/' . urlencode($bookSlug) . '/chapter/' . urlencode($this->slug)); + + return url($fullPath); } /** diff --git a/app/Entities/Page.php b/app/Entities/Page.php index 1c2cc5cff..c32417418 100644 --- a/app/Entities/Page.php +++ b/app/Entities/Page.php @@ -96,10 +96,10 @@ class Page extends Entity $idComponent = $this->draft ? $this->id : urlencode($this->slug); if ($path !== false) { - return baseUrl('/books/' . urlencode($bookSlug) . $midText . $idComponent . '/' . trim($path, '/')); + return url('/books/' . urlencode($bookSlug) . $midText . $idComponent . '/' . trim($path, '/')); } - return baseUrl('/books/' . urlencode($bookSlug) . $midText . $idComponent); + return url('/books/' . urlencode($bookSlug) . $midText . $idComponent); } /** diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 21ded2355..c739fd9a3 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -53,8 +53,8 @@ class LoginController extends Controller $this->socialAuthService = $socialAuthService; $this->ldapService = $ldapService; $this->userRepo = $userRepo; - $this->redirectPath = baseUrl('/'); - $this->redirectAfterLogout = baseUrl('/login'); + $this->redirectPath = url('/'); + $this->redirectAfterLogout = url('/login'); parent::__construct(); } diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index d57105b62..a285899cc 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -2,17 +2,23 @@ namespace BookStack\Http\Controllers\Auth; +use BookStack\Auth\Access\EmailConfirmationService; +use BookStack\Auth\Access\SocialAuthService; use BookStack\Auth\SocialAccount; use BookStack\Auth\User; use BookStack\Auth\UserRepo; +use BookStack\Exceptions\SocialDriverNotConfigured; use BookStack\Exceptions\SocialSignInAccountNotUsed; use BookStack\Exceptions\SocialSignInException; use BookStack\Exceptions\UserRegistrationException; use BookStack\Http\Controllers\Controller; use Exception; use Illuminate\Foundation\Auth\RegistersUsers; +use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Http\Response; +use Illuminate\Routing\Redirector; +use Illuminate\View\View; use Laravel\Socialite\Contracts\User as SocialUser; use Validator; @@ -46,18 +52,18 @@ class RegisterController extends Controller /** * Create a new controller instance. * - * @param \BookStack\Auth\Access\SocialAuthService $socialAuthService + * @param SocialAuthService $socialAuthService * @param \BookStack\Auth\EmailConfirmationService $emailConfirmationService - * @param \BookStack\Auth\UserRepo $userRepo + * @param UserRepo $userRepo */ - public function __construct(\BookStack\Auth\Access\SocialAuthService $socialAuthService, \BookStack\Auth\Access\EmailConfirmationService $emailConfirmationService, UserRepo $userRepo) + public function __construct(SocialAuthService $socialAuthService, EmailConfirmationService $emailConfirmationService, UserRepo $userRepo) { $this->middleware('guest')->only(['getRegister', 'postRegister', 'socialRegister']); $this->socialAuthService = $socialAuthService; $this->emailConfirmationService = $emailConfirmationService; $this->userRepo = $userRepo; - $this->redirectTo = baseUrl('/'); - $this->redirectPath = baseUrl('/'); + $this->redirectTo = url('/'); + $this->redirectPath = url('/'); parent::__construct(); } @@ -101,8 +107,8 @@ class RegisterController extends Controller /** * Handle a registration request for the application. - * @param Request|\Illuminate\Http\Request $request - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @param Request|Request $request + * @return RedirectResponse|Redirector * @throws UserRegistrationException */ public function postRegister(Request $request) @@ -117,7 +123,7 @@ class RegisterController extends Controller /** * Create a new user instance after a valid registration. * @param array $data - * @return \BookStack\Auth\User + * @return User */ protected function create(array $data) { @@ -133,7 +139,7 @@ class RegisterController extends Controller * @param array $userData * @param bool|false|SocialAccount $socialAccount * @param bool $emailVerified - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @return RedirectResponse|Redirector * @throws UserRegistrationException */ protected function registerUser(array $userData, $socialAccount = false, $emailVerified = false) @@ -182,7 +188,7 @@ class RegisterController extends Controller /** * Confirms an email via a token and logs the user into the system. * @param $token - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @return RedirectResponse|Redirector * @throws UserRegistrationException */ public function confirmEmail($token) @@ -200,7 +206,7 @@ class RegisterController extends Controller /** * Shows a notice that a user's email address has not been confirmed, * Also has the option to re-send the confirmation email. - * @return \Illuminate\View\View + * @return View */ public function showAwaitingConfirmation() { @@ -210,7 +216,7 @@ class RegisterController extends Controller /** * Resend the confirmation email * @param Request $request - * @return \Illuminate\View\View + * @return View */ public function resendConfirmation(Request $request) { @@ -235,7 +241,7 @@ class RegisterController extends Controller * @param $socialDriver * @return mixed * @throws UserRegistrationException - * @throws \BookStack\Exceptions\SocialDriverNotConfigured + * @throws SocialDriverNotConfigured */ public function socialRegister($socialDriver) { @@ -248,10 +254,10 @@ class RegisterController extends Controller * The callback for social login services. * @param $socialDriver * @param Request $request - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @return RedirectResponse|Redirector * @throws SocialSignInException * @throws UserRegistrationException - * @throws \BookStack\Exceptions\SocialDriverNotConfigured + * @throws SocialDriverNotConfigured */ public function socialCallback($socialDriver, Request $request) { @@ -292,7 +298,7 @@ class RegisterController extends Controller /** * Detach a social account from a user. * @param $socialDriver - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @return RedirectResponse|Redirector */ public function detachSocialAccount($socialDriver) { @@ -303,7 +309,7 @@ class RegisterController extends Controller * Register a new user after a registration callback. * @param string $socialDriver * @param SocialUser $socialUser - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @return RedirectResponse|Redirector * @throws UserRegistrationException */ protected function socialRegisterCallback(string $socialDriver, SocialUser $socialUser) diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php index 16a7d5a5e..89fb83fd9 100644 --- a/app/Http/Controllers/PageController.php +++ b/app/Http/Controllers/PageController.php @@ -541,7 +541,7 @@ class PageController extends Controller public function showRecentlyUpdated() { // TODO - Still exist? - $pages = $this->pageRepo->getRecentlyUpdatedPaginated('page', 20)->setPath(baseUrl('/pages/recently-updated')); + $pages = $this->pageRepo->getRecentlyUpdatedPaginated('page', 20)->setPath(url('/pages/recently-updated')); return view('pages.detailed-listing', [ 'title' => trans('entities.recently_updated_pages'), 'pages' => $pages diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php index 4bcf7b40e..1691ee9b0 100644 --- a/app/Http/Controllers/SearchController.php +++ b/app/Http/Controllers/SearchController.php @@ -48,7 +48,7 @@ class SearchController extends Controller $this->setPageTitle(trans('entities.search_for_term', ['term' => $searchTerm])); $page = intval($request->get('page', '0')) ?: 1; - $nextPageLink = baseUrl('/search?term=' . urlencode($searchTerm) . '&page=' . ($page+1)); + $nextPageLink = url('/search?term=' . urlencode($searchTerm) . '&page=' . ($page+1)); $results = $this->searchService->searchEntities($searchTerm, 'all', $page, 20); diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index 1a3384367..d840a9b2e 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -41,7 +41,7 @@ class Authenticate if ($request->ajax()) { return response('Unauthorized.', 401); } else { - return redirect()->guest(baseUrl('/login')); + return redirect()->guest(url('/login')); } } diff --git a/app/Http/Request.php b/app/Http/Request.php new file mode 100644 index 000000000..bd2761a0b --- /dev/null +++ b/app/Http/Request.php @@ -0,0 +1,26 @@ +getScheme().'://'.$this->getHttpHost(); + } + + return $base; + } + +} \ No newline at end of file diff --git a/app/Notifications/ConfirmEmail.php b/app/Notifications/ConfirmEmail.php index 7ecadc298..229408f5c 100644 --- a/app/Notifications/ConfirmEmail.php +++ b/app/Notifications/ConfirmEmail.php @@ -26,6 +26,6 @@ class ConfirmEmail extends MailNotification ->subject(trans('auth.email_confirm_subject', $appName)) ->greeting(trans('auth.email_confirm_greeting', $appName)) ->line(trans('auth.email_confirm_text')) - ->action(trans('auth.email_confirm_action'), baseUrl('/register/confirm/' . $this->token)); + ->action(trans('auth.email_confirm_action'), url('/register/confirm/' . $this->token)); } } diff --git a/app/Notifications/ResetPassword.php b/app/Notifications/ResetPassword.php index 305a7da72..208752764 100644 --- a/app/Notifications/ResetPassword.php +++ b/app/Notifications/ResetPassword.php @@ -29,7 +29,7 @@ class ResetPassword extends MailNotification return $this->newMailMessage() ->subject(trans('auth.email_reset_subject', ['appName' => setting('app-name')])) ->line(trans('auth.email_reset_text')) - ->action(trans('auth.reset_password'), baseUrl('password/reset/' . $this->token)) + ->action(trans('auth.reset_password'), url('password/reset/' . $this->token)) ->line(trans('auth.email_reset_not_requested')); } } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 6bc1f9047..a2fc673f4 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -8,11 +8,11 @@ use BookStack\Entities\Chapter; use BookStack\Entities\Page; use BookStack\Settings\Setting; use BookStack\Settings\SettingService; -use BookStack\UrlGenerator; use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Support\Facades\View; use Illuminate\Support\ServiceProvider; use Schema; +use URL; use Validator; class AppServiceProvider extends ServiceProvider @@ -24,6 +24,9 @@ class AppServiceProvider extends ServiceProvider */ public function boot() { + // Set root URL + URL::forceRootUrl(config('app.url')); + // Custom validation methods Validator::extend('image_extension', function ($attribute, $value, $parameters, $validator) { $validImageExtensions = ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'tiff', 'webp']; @@ -73,10 +76,5 @@ class AppServiceProvider extends ServiceProvider $this->app->singleton(SettingService::class, function ($app) { return new SettingService($app->make(Setting::class), $app->make('Illuminate\Contracts\Cache\Repository')); }); - - $this->app->bind( - \Illuminate\Contracts\Routing\UrlGenerator::class, - UrlGenerator::class - ); } } diff --git a/app/Providers/PaginationServiceProvider.php b/app/Providers/PaginationServiceProvider.php index 3a695c5e3..1c982b82e 100644 --- a/app/Providers/PaginationServiceProvider.php +++ b/app/Providers/PaginationServiceProvider.php @@ -18,7 +18,7 @@ class PaginationServiceProvider extends IlluminatePaginationServiceProvider }); Paginator::currentPathResolver(function () { - return baseUrl($this->app['request']->path()); + return url($this->app['request']->path()); }); Paginator::currentPageResolver(function ($pageName = 'page') { diff --git a/app/Uploads/Attachment.php b/app/Uploads/Attachment.php index eb9a0fe68..8720d3c09 100644 --- a/app/Uploads/Attachment.php +++ b/app/Uploads/Attachment.php @@ -37,6 +37,6 @@ class Attachment extends Ownable if ($this->external && strpos($this->path, 'http') !== 0) { return $this->path; } - return baseUrl('/attachments/' . $this->id); + return url('/attachments/' . $this->id); } } diff --git a/app/Uploads/ImageService.php b/app/Uploads/ImageService.php index ae1c6a254..860230d00 100644 --- a/app/Uploads/ImageService.php +++ b/app/Uploads/ImageService.php @@ -417,7 +417,7 @@ class ImageService extends UploadService $isLocal = strpos(trim($uri), 'http') !== 0; // Attempt to find local files even if url not absolute - $base = baseUrl('/'); + $base = url('/'); if (!$isLocal && strpos($uri, $base) === 0) { $isLocal = true; $uri = str_replace($base, '', $uri); @@ -474,7 +474,7 @@ class ImageService extends UploadService $this->storageUrl = $storageUrl; } - $basePath = ($this->storageUrl == false) ? baseUrl('/') : $this->storageUrl; + $basePath = ($this->storageUrl == false) ? url('/') : $this->storageUrl; return rtrim($basePath, '/') . $filePath; } } diff --git a/app/UrlGenerator.php b/app/UrlGenerator.php deleted file mode 100644 index 471792cdf..000000000 --- a/app/UrlGenerator.php +++ /dev/null @@ -1,58 +0,0 @@ -formatParameters($extra)) - ); - - $defaultRoot = $this->formatRoot($this->formatScheme($secure)); - - list($path, $query) = $this->extractQueryString($path); - - return $this->formatWithBase( - $defaultRoot, trim($path.'/'.$tail, '/') - ).$query; - } - - /** - * Format the given URL segments into a single URL. - * - * @param string $defaultRoot - * @param string $path - * @return string - */ - public function formatWithBase($defaultRoot, $path) - { - $isFullPath = strpos($path, 'http') === 0; - $setBasePath = trim(config('app.url'), '/'); - - if ($isFullPath) { - return $path; - } - - if (! empty($setBasePath)) { - $defaultRoot = $setBasePath; - } - - // TODO - Add mechanism to set path correctly for intended() and back() redirects - // TODO - Update tests to align with new system - // TODO - Clean up helpers and refactor their usage. - - return trim($defaultRoot. '/' .$path, '/'); - } - -} \ No newline at end of file diff --git a/app/helpers.php b/app/helpers.php index 7bc116555..9bbfcfbf0 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -1,8 +1,9 @@ user() ?: \BookStack\Auth\User::getDefault(); + return auth()->user() ?: User::getDefault(); } /** @@ -63,9 +64,9 @@ function hasAppAccess() : bool * that particular item. * @param string $permission * @param Ownable $ownable - * @return mixed + * @return bool */ -function userCan(string $permission, Ownable $ownable = null) +function userCan(string $permission, Ownable $ownable = null) : bool { if ($ownable === null) { return user() && user()->can($permission); @@ -83,7 +84,7 @@ function userCan(string $permission, Ownable $ownable = null) * @param string|null $entityClass * @return bool */ -function userCanOnAny(string $permission, string $entityClass = null) +function userCanOnAny(string $permission, string $entityClass = null) : bool { $permissionService = app(PermissionService::class); return $permissionService->checkUserHasPermissionOnAnything($permission, $entityClass); @@ -93,84 +94,27 @@ function userCanOnAny(string $permission, string $entityClass = null) * Helper to access system settings. * @param $key * @param bool $default - * @return bool|string|\BookStack\Settings\SettingService + * @return bool|string|SettingService */ function setting($key = null, $default = false) { - $settingService = resolve(\BookStack\Settings\SettingService::class); + $settingService = resolve(SettingService::class); if (is_null($key)) { return $settingService; } return $settingService->get($key, $default); } -/** - * Helper to create url's relative to the applications root path. - * @param string $path - * @param bool $forceAppDomain - * @return string - */ -function baseUrl($path, $forceAppDomain = false) -{ - return url($path); - $isFullUrl = strpos($path, 'http') === 0; - if ($isFullUrl && !$forceAppDomain) { - return $path; - } - - $path = trim($path, '/'); - $base = rtrim(config('app.url'), '/'); - - // Remove non-specified domain if forced and we have a domain - if ($isFullUrl && $forceAppDomain) { - if (!empty($base) && strpos($path, $base) === 0) { - $path = mb_substr($path, mb_strlen($base)); - } else { - $explodedPath = explode('/', $path); - $path = implode('/', array_splice($explodedPath, 3)); - } - } - - // Return normal url path if not specified in config - if (config('app.url') === '') { - return url($path); - } - - return $base . '/' . ltrim($path, '/'); -} - -/** - * Get an instance of the redirector. - * Overrides the default laravel redirect helper. - * Ensures it redirects even when the app is in a subdirectory. - * - * @param string|null $to - * @param int $status - * @param array $headers - * @param bool $secure - * @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse - */ -function redirect($to = null, $status = 302, $headers = [], $secure = null) -{ - if (is_null($to)) { - return app('redirect'); - } - - $to = baseUrl($to); - - return app('redirect')->to($to, $status, $headers, $secure); -} - /** * Get a path to a theme resource. * @param string $path - * @return string|boolean + * @return string */ -function theme_path($path = '') +function theme_path($path = '') : string { $theme = config('view.theme'); if (!$theme) { - return false; + return ''; } return base_path('themes/' . $theme .($path ? DIRECTORY_SEPARATOR.$path : $path)); @@ -242,5 +186,5 @@ function sortUrl($path, $data, $overrideData = []) return $path; } - return baseUrl($path . '?' . implode('&', $queryStringSections)); + return url($path . '?' . implode('&', $queryStringSections)); } diff --git a/public/index.php b/public/index.php index ad378d7e0..820576472 100644 --- a/public/index.php +++ b/public/index.php @@ -34,6 +34,7 @@ require __DIR__.'/../bootstrap/init.php'; */ $app = require_once __DIR__.'/../bootstrap/app.php'; +$app->alias('request', \BookStack\Http\Request::class); /* |-------------------------------------------------------------------------- @@ -50,7 +51,7 @@ $app = require_once __DIR__.'/../bootstrap/app.php'; $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); $response = $kernel->handle( - $request = Illuminate\Http\Request::capture() + $request = \BookStack\Http\Request::capture() ); $response->send(); diff --git a/resources/views/auth/forms/login/standard.blade.php b/resources/views/auth/forms/login/standard.blade.php index ea63cf7ac..dc6081637 100644 --- a/resources/views/auth/forms/login/standard.blade.php +++ b/resources/views/auth/forms/login/standard.blade.php @@ -7,6 +7,6 @@ @include('form.password', ['name' => 'password', 'tabindex' => 1]) - {{ trans('auth.forgot_password') }} + {{ trans('auth.forgot_password') }} diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index a0e5f716c..76aa3a6e9 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -9,7 +9,7 @@