1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2024-11-23 19:32:29 +01:00

Merge branch 'laravel-upgrade'

This commit is contained in:
Dan Brown 2019-09-14 14:21:24 +01:00
commit 1ee3e779e4
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
244 changed files with 2548 additions and 1336 deletions

View File

@ -89,7 +89,7 @@ REDIS_SERVERS=127.0.0.1:6379:0
# Queue driver to use # Queue driver to use
# Queue not really currently used but may be configurable in the future. # Queue not really currently used but may be configurable in the future.
# Would advise not to change this for now. # Would advise not to change this for now.
QUEUE_DRIVER=sync QUEUE_CONNECTION=sync
# Storage system to use # Storage system to use
# Can be 'local', 'local_secure' or 's3' # Can be 'local', 'local_secure' or 's3'

3
.gitignore vendored
View File

@ -21,4 +21,5 @@ nbproject
.buildpath .buildpath
.project .project
.settings/ .settings/
webpack-stats.json webpack-stats.json
.phpunit.result.cache

View File

@ -1,9 +1,11 @@
dist: trusty dist: bionic
sudo: false
language: php language: php
php: php:
- 7.0.20 - '7.2'
- 7.1.9 - '7.3'
services:
- mysql
cache: cache:
directories: directories:
@ -21,8 +23,7 @@ before_script:
- php artisan migrate --force -n --database=mysql_testing - php artisan migrate --force -n --database=mysql_testing
- php artisan db:seed --force -n --class=DummyContentSeeder --database=mysql_testing - php artisan db:seed --force -n --class=DummyContentSeeder --database=mysql_testing
script: vendor/bin/phpunit --configuration phpunit.xml
after_failure: after_failure:
- cat storage/logs/laravel.log - cat storage/logs/laravel.log
script:
- phpunit

View File

@ -13,7 +13,12 @@ class Application extends \Illuminate\Foundation\Application
*/ */
public function configPath($path = '') public function configPath($path = '')
{ {
return $this->basePath.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'Config'.($path ? DIRECTORY_SEPARATOR.$path : $path); return $this->basePath
. DIRECTORY_SEPARATOR
. 'app'
. DIRECTORY_SEPARATOR
. 'Config'
. ($path ? DIRECTORY_SEPARATOR.$path : $path);
} }
} }

View File

@ -5,6 +5,7 @@ use BookStack\Auth\UserRepo;
use BookStack\Exceptions\SocialDriverNotConfigured; use BookStack\Exceptions\SocialDriverNotConfigured;
use BookStack\Exceptions\SocialSignInAccountNotUsed; use BookStack\Exceptions\SocialSignInAccountNotUsed;
use BookStack\Exceptions\UserRegistrationException; use BookStack\Exceptions\UserRegistrationException;
use Illuminate\Support\Str;
use Laravel\Socialite\Contracts\Factory as Socialite; use Laravel\Socialite\Contracts\Factory as Socialite;
use Laravel\Socialite\Contracts\User as SocialUser; use Laravel\Socialite\Contracts\User as SocialUser;
@ -104,6 +105,7 @@ class SocialAuthService
$socialAccount = $this->socialAccount->where('driver_id', '=', $socialId)->first(); $socialAccount = $this->socialAccount->where('driver_id', '=', $socialId)->first();
$isLoggedIn = auth()->check(); $isLoggedIn = auth()->check();
$currentUser = user(); $currentUser = user();
$titleCaseDriver = Str::title($socialDriver);
// When a user is not logged in and a matching SocialAccount exists, // When a user is not logged in and a matching SocialAccount exists,
// Simply log the user into the application. // Simply log the user into the application.
@ -117,26 +119,26 @@ class SocialAuthService
if ($isLoggedIn && $socialAccount === null) { if ($isLoggedIn && $socialAccount === null) {
$this->fillSocialAccount($socialDriver, $socialUser); $this->fillSocialAccount($socialDriver, $socialUser);
$currentUser->socialAccounts()->save($this->socialAccount); $currentUser->socialAccounts()->save($this->socialAccount);
session()->flash('success', trans('settings.users_social_connected', ['socialAccount' => title_case($socialDriver)])); session()->flash('success', trans('settings.users_social_connected', ['socialAccount' => $titleCaseDriver]));
return redirect($currentUser->getEditUrl()); return redirect($currentUser->getEditUrl());
} }
// When a user is logged in and the social account exists and is already linked to the current user. // When a user is logged in and the social account exists and is already linked to the current user.
if ($isLoggedIn && $socialAccount !== null && $socialAccount->user->id === $currentUser->id) { if ($isLoggedIn && $socialAccount !== null && $socialAccount->user->id === $currentUser->id) {
session()->flash('error', trans('errors.social_account_existing', ['socialAccount' => title_case($socialDriver)])); session()->flash('error', trans('errors.social_account_existing', ['socialAccount' => $titleCaseDriver]));
return redirect($currentUser->getEditUrl()); return redirect($currentUser->getEditUrl());
} }
// When a user is logged in, A social account exists but the users do not match. // When a user is logged in, A social account exists but the users do not match.
if ($isLoggedIn && $socialAccount !== null && $socialAccount->user->id != $currentUser->id) { if ($isLoggedIn && $socialAccount !== null && $socialAccount->user->id != $currentUser->id) {
session()->flash('error', trans('errors.social_account_already_used_existing', ['socialAccount' => title_case($socialDriver)])); session()->flash('error', trans('errors.social_account_already_used_existing', ['socialAccount' => $titleCaseDriver]));
return redirect($currentUser->getEditUrl()); return redirect($currentUser->getEditUrl());
} }
// Otherwise let the user know this social account is not used by anyone. // Otherwise let the user know this social account is not used by anyone.
$message = trans('errors.social_account_not_used', ['socialAccount' => title_case($socialDriver)]); $message = trans('errors.social_account_not_used', ['socialAccount' => $titleCaseDriver]);
if (setting('registration-enabled')) { if (setting('registration-enabled')) {
$message .= trans('errors.social_account_register_instructions', ['socialAccount' => title_case($socialDriver)]); $message .= trans('errors.social_account_register_instructions', ['socialAccount' => $titleCaseDriver]);
} }
throw new SocialSignInAccountNotUsed($message, '/login'); throw new SocialSignInAccountNotUsed($message, '/login');
@ -157,7 +159,7 @@ class SocialAuthService
abort(404, trans('errors.social_driver_not_found')); abort(404, trans('errors.social_driver_not_found'));
} }
if (!$this->checkDriverConfigured($driver)) { if (!$this->checkDriverConfigured($driver)) {
throw new SocialDriverNotConfigured(trans('errors.social_driver_not_configured', ['socialAccount' => title_case($socialDriver)])); throw new SocialDriverNotConfigured(trans('errors.social_driver_not_configured', ['socialAccount' => Str::title($socialDriver)]));
} }
return $driver; return $driver;
@ -244,7 +246,7 @@ class SocialAuthService
public function detachSocialAccount($socialDriver) public function detachSocialAccount($socialDriver)
{ {
user()->socialAccounts()->where('driver', '=', $socialDriver)->delete(); user()->socialAccounts()->where('driver', '=', $socialDriver)->delete();
session()->flash('success', trans('settings.users_social_disconnected', ['socialAccount' => title_case($socialDriver)])); session()->flash('success', trans('settings.users_social_disconnected', ['socialAccount' => Str::title($socialDriver)]));
return redirect(user()->getEditUrl()); return redirect(user()->getEditUrl());
} }

View File

@ -5,6 +5,7 @@ use BookStack\Exceptions\UserTokenExpiredException;
use BookStack\Exceptions\UserTokenNotFoundException; use BookStack\Exceptions\UserTokenNotFoundException;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Database\Connection as Database; use Illuminate\Database\Connection as Database;
use Illuminate\Support\Str;
use stdClass; use stdClass;
class UserTokenService class UserTokenService
@ -73,9 +74,9 @@ class UserTokenService
*/ */
protected function generateToken() : string protected function generateToken() : string
{ {
$token = str_random(24); $token = Str::random(24);
while ($this->tokenExists($token)) { while ($this->tokenExists($token)) {
$token = str_random(25); $token = Str::random(25);
} }
return $token; return $token;
} }

View File

@ -3,6 +3,7 @@
use BookStack\Auth\Permissions; use BookStack\Auth\Permissions;
use BookStack\Auth\Role; use BookStack\Auth\Role;
use BookStack\Exceptions\PermissionsException; use BookStack\Exceptions\PermissionsException;
use Illuminate\Support\Str;
class PermissionsRepo class PermissionsRepo
{ {
@ -66,7 +67,7 @@ class PermissionsRepo
$role->name = str_replace(' ', '-', strtolower($roleData['display_name'])); $role->name = str_replace(' ', '-', strtolower($roleData['display_name']));
// Prevent duplicate names // Prevent duplicate names
while ($this->role->where('name', '=', $role->name)->count() > 0) { while ($this->role->where('name', '=', $role->name)->count() > 0) {
$role->name .= strtolower(str_random(2)); $role->name .= strtolower(Str::random(2));
} }
$role->save(); $role->save();

View File

@ -57,6 +57,9 @@ return [
// Application Fallback Locale // Application Fallback Locale
'fallback_locale' => 'en', 'fallback_locale' => 'en',
// Faker Locale
'faker_locale' => 'en_GB',
// Enable right-to-left text control. // Enable right-to-left text control.
'rtl' => false, 'rtl' => false,
@ -72,10 +75,6 @@ return [
// Encryption cipher // Encryption cipher
'cipher' => 'AES-256-CBC', 'cipher' => 'AES-256-CBC',
// Logging configuration
// Options: single, daily, syslog, errorlog
'log' => env('APP_LOGGING', 'single'),
// Application Services Provides // Application Services Provides
'providers' => [ 'providers' => [
@ -137,6 +136,7 @@ return [
// Laravel // Laravel
'App' => Illuminate\Support\Facades\App::class, 'App' => Illuminate\Support\Facades\App::class,
'Arr' => Illuminate\Support\Arr::class,
'Artisan' => Illuminate\Support\Facades\Artisan::class, 'Artisan' => Illuminate\Support\Facades\Artisan::class,
'Auth' => Illuminate\Support\Facades\Auth::class, 'Auth' => Illuminate\Support\Facades\Auth::class,
'Blade' => Illuminate\Support\Facades\Blade::class, 'Blade' => Illuminate\Support\Facades\Blade::class,
@ -166,6 +166,7 @@ return [
'Schema' => Illuminate\Support\Facades\Schema::class, 'Schema' => Illuminate\Support\Facades\Schema::class,
'Session' => Illuminate\Support\Facades\Session::class, 'Session' => Illuminate\Support\Facades\Session::class,
'Storage' => Illuminate\Support\Facades\Storage::class, 'Storage' => Illuminate\Support\Facades\Storage::class,
'Str' => Illuminate\Support\Str::class,
'URL' => Illuminate\Support\Facades\URL::class, 'URL' => Illuminate\Support\Facades\URL::class,
'Validator' => Illuminate\Support\Facades\Validator::class, 'Validator' => Illuminate\Support\Facades\Validator::class,
'View' => Illuminate\Support\Facades\View::class, 'View' => Illuminate\Support\Facades\View::class,

View File

@ -36,6 +36,7 @@ return [
'api' => [ 'api' => [
'driver' => 'token', 'driver' => 'token',
'provider' => 'users', 'provider' => 'users',
'hash' => false,
], ],
], ],

View File

@ -24,9 +24,13 @@ return [
'pusher' => [ 'pusher' => [
'driver' => 'pusher', 'driver' => 'pusher',
'key' => env('PUSHER_KEY'), 'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_SECRET'), 'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'), 'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => true,
],
], ],
'redis' => [ 'redis' => [
@ -38,6 +42,11 @@ return [
'driver' => 'log', 'driver' => 'log',
], ],
'null' => [
'driver' => 'null',
],
], ],
]; ];

View File

@ -62,6 +62,6 @@ return [
// Cache key prefix // Cache key prefix
// Used to prevent collisions in shared cache systems. // Used to prevent collisions in shared cache systems.
'prefix' => env('CACHE_PREFIX', 'bookstack'), 'prefix' => env('CACHE_PREFIX', 'bookstack_cache'),
]; ];

View File

@ -14,7 +14,7 @@ if (env('REDIS_SERVERS', false)) {
$redisDefaults = ['host' => '127.0.0.1', 'port' => '6379', 'database' => '0', 'password' => null]; $redisDefaults = ['host' => '127.0.0.1', 'port' => '6379', 'database' => '0', 'password' => null];
$redisServers = explode(',', trim(env('REDIS_SERVERS', '127.0.0.1:6379:0'), ',')); $redisServers = explode(',', trim(env('REDIS_SERVERS', '127.0.0.1:6379:0'), ','));
$redisConfig = []; $redisConfig = ['client' => 'predis'];
$cluster = count($redisServers) > 1; $cluster = count($redisServers) > 1;
if ($cluster) { if ($cluster) {
@ -59,14 +59,9 @@ return [
// Many of those shown here are unsupported by BookStack. // Many of those shown here are unsupported by BookStack.
'connections' => [ 'connections' => [
'sqlite' => [
'driver' => 'sqlite',
'database' => storage_path('database.sqlite'),
'prefix' => '',
],
'mysql' => [ 'mysql' => [
'driver' => 'mysql', 'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => $mysql_host, 'host' => $mysql_host,
'database' => env('DB_DATABASE', 'forge'), 'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'), 'username' => env('DB_USERNAME', 'forge'),
@ -76,43 +71,28 @@ return [
'charset' => 'utf8mb4', 'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci', 'collation' => 'utf8mb4_unicode_ci',
'prefix' => '', 'prefix' => '',
'prefix_indexes' => true,
'strict' => false, 'strict' => false,
'engine' => null, 'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
], ],
'mysql_testing' => [ 'mysql_testing' => [
'driver' => 'mysql', 'driver' => 'mysql',
'url' => env('TEST_DATABASE_URL'),
'host' => '127.0.0.1', 'host' => '127.0.0.1',
'database' => 'bookstack-test', 'database' => 'bookstack-test',
'username' => env('MYSQL_USER', 'bookstack-test'), 'username' => env('MYSQL_USER', 'bookstack-test'),
'password' => env('MYSQL_PASSWORD', 'bookstack-test'), 'password' => env('MYSQL_PASSWORD', 'bookstack-test'),
'charset' => 'utf8', 'charset' => 'utf8mb4',
'collation' => 'utf8_unicode_ci', 'collation' => 'utf8mb4_unicode_ci',
'prefix' => '', 'prefix' => '',
'prefix_indexes' => true,
'strict' => false, 'strict' => false,
], ],
'pgsql' => [
'driver' => 'pgsql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'schema' => 'public',
],
'sqlsrv' => [
'driver' => 'sqlsrv',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
],
], ],
// Migration Repository Table // Migration Repository Table

37
app/Config/hashing.php Normal file
View File

@ -0,0 +1,37 @@
<?php
/**
* Hashing configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
return [
// Default Hash Driver
// This option controls the default hash driver that will be used to hash
// passwords for your application. By default, the bcrypt algorithm is used.
// Supported: "bcrypt", "argon", "argon2id"
'driver' => 'bcrypt',
// Bcrypt Options
// Here you may specify the configuration options that should be used when
// passwords are hashed using the Bcrypt algorithm. This will allow you
// to control the amount of time it takes to hash the given password.
'bcrypt' => [
'rounds' => env('BCRYPT_ROUNDS', 10),
],
// Argon Options
// Here you may specify the configuration options that should be used when
// passwords are hashed using the Argon algorithm. These will allow you
// to control the amount of time it takes to hash the given password.
'argon' => [
'memory' => 1024,
'threads' => 2,
'time' => 2,
],
];

82
app/Config/logging.php Normal file
View File

@ -0,0 +1,82 @@
<?php
use Monolog\Handler\NullHandler;
use Monolog\Handler\StreamHandler;
/**
* Logging configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
return [
// Default Log Channel
// This option defines the default log channel that gets used when writing
// messages to the logs. The name specified in this option should match
// one of the channels defined in the "channels" configuration array.
'default' => env('LOG_CHANNEL', 'single'),
// Log Channels
// Here you may configure the log channels for your application. Out of
// the box, Laravel uses the Monolog PHP logging library. This gives
// you a variety of powerful log handlers / formatters to utilize.
// Available Drivers: "single", "daily", "slack", "syslog",
// "errorlog", "monolog",
// "custom", "stack"
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['daily'],
'ignore_exceptions' => false,
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
'days' => 14,
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
'days' => 7,
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => 'Laravel Log',
'emoji' => ':boom:',
'level' => 'critical',
],
'stderr' => [
'driver' => 'monolog',
'handler' => StreamHandler::class,
'with' => [
'stream' => 'php://stderr',
],
],
'syslog' => [
'driver' => 'syslog',
'level' => 'debug',
],
'errorlog' => [
'driver' => 'errorlog',
'level' => 'debug',
],
'null' => [
'driver' => 'monolog',
'handler' => NullHandler::class,
],
],
];

View File

@ -46,4 +46,10 @@ return [
], ],
], ],
// Log Channel
// If you are using the "log" driver, you may specify the logging channel
// if you prefer to keep mail messages separate from other log entries
// for simpler reading. Otherwise, the default channel will be used.
'log_channel' => env('MAIL_LOG_CHANNEL'),
]; ];

View File

@ -12,11 +12,12 @@ return [
// Default driver to use for the queue // Default driver to use for the queue
// Options: null, sync, redis // Options: null, sync, redis
'default' => env('QUEUE_DRIVER', 'sync'), 'default' => env('QUEUE_CONNECTION', 'sync'),
// Queue connection configuration // Queue connection configuration
'connections' => [ 'connections' => [
'sync' => [ 'sync' => [
'driver' => 'sync', 'driver' => 'sync',
], ],
@ -25,38 +26,15 @@ return [
'driver' => 'database', 'driver' => 'database',
'table' => 'jobs', 'table' => 'jobs',
'queue' => 'default', 'queue' => 'default',
'expire' => 60, 'retry_after' => 90,
],
'beanstalkd' => [
'driver' => 'beanstalkd',
'host' => 'localhost',
'queue' => 'default',
'ttr' => 60,
],
'sqs' => [
'driver' => 'sqs',
'key' => 'your-public-key',
'secret' => 'your-secret-key',
'queue' => 'your-queue-url',
'region' => 'us-east-1',
],
'iron' => [
'driver' => 'iron',
'host' => 'mq-aws-us-east-1.iron.io',
'token' => 'your-token',
'project' => 'your-project-id',
'queue' => 'your-queue-name',
'encrypt' => true,
], ],
'redis' => [ 'redis' => [
'driver' => 'redis', 'driver' => 'redis',
'connection' => 'default', 'connection' => 'default',
'queue' => 'default', 'queue' => env('REDIS_QUEUE', 'default'),
'expire' => 60, 'retry_after' => 90,
'block_for' => null,
], ],
], ],

View File

@ -22,23 +22,6 @@ return [
// Callback URL for social authentication methods // Callback URL for social authentication methods
'callback_url' => env('APP_URL', false), 'callback_url' => env('APP_URL', false),
'mailgun' => [
'domain' => '',
'secret' => '',
],
'ses' => [
'key' => '',
'secret' => '',
'region' => 'us-east-1',
],
'stripe' => [
'model' => \BookStack\Auth\User::class,
'key' => '',
'secret' => '',
],
'github' => [ 'github' => [
'client_id' => env('GITHUB_APP_ID', false), 'client_id' => env('GITHUB_APP_ID', false),
'client_secret' => env('GITHUB_APP_SECRET', false), 'client_secret' => env('GITHUB_APP_SECRET', false),

View File

@ -35,13 +35,18 @@ return [
// Session database table, if database driver is in use // Session database table, if database driver is in use
'table' => 'sessions', 'table' => 'sessions',
// Session Cache Store
// When using the "apc" or "memcached" session drivers, you may specify a
// cache store that should be used for these sessions. This value must
// correspond with one of the application's configured cache stores.
'store' => null,
// Session Sweeping Lottery // Session Sweeping Lottery
// Some session drivers must manually sweep their storage location to get // Some session drivers must manually sweep their storage location to get
// rid of old sessions from storage. Here are the chances that it will // rid of old sessions from storage. Here are the chances that it will
// happen on a given request. By default, the odds are 2 out of 100. // happen on a given request. By default, the odds are 2 out of 100.
'lottery' => [2, 100], 'lottery' => [2, 100],
// Session Cookie Name // Session Cookie Name
// Here you may change the name of the cookie used to identify a session // Here you may change the name of the cookie used to identify a session
// instance by ID. The name specified here will get used every time a // instance by ID. The name specified here will get used every time a

View File

@ -23,8 +23,9 @@ class BreadcrumbsViewComposer
public function compose(View $view) public function compose(View $view)
{ {
$crumbs = $view->getData()['crumbs']; $crumbs = $view->getData()['crumbs'];
if (array_first($crumbs) instanceof Book) { $firstCrumb = $crumbs[0] ?? null;
$shelf = $this->entityContextManager->getContextualShelfForBook(array_first($crumbs)); if ($firstCrumb instanceof Book) {
$shelf = $this->entityContextManager->getContextualShelfForBook($firstCrumb);
if ($shelf) { if ($shelf) {
array_unshift($crumbs, $shelf); array_unshift($crumbs, $shelf);
$view->with('crumbs', $crumbs); $view->with('crumbs', $crumbs);

View File

@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Query\Builder; use Illuminate\Database\Query\Builder;
use Illuminate\Database\Query\JoinClause; use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Str;
class SearchService class SearchService
{ {
@ -210,7 +211,7 @@ class SearchService
// Handle filters // Handle filters
foreach ($terms['filters'] as $filterTerm => $filterValue) { foreach ($terms['filters'] as $filterTerm => $filterValue) {
$functionName = camel_case('filter_' . $filterTerm); $functionName = Str::camel('filter_' . $filterTerm);
if (method_exists($this, $functionName)) { if (method_exists($this, $functionName)) {
$this->$functionName($entitySelect, $entity, $filterValue); $this->$functionName($entitySelect, $entity, $filterValue);
} }
@ -514,7 +515,7 @@ class SearchService
protected function filterSortBy(EloquentBuilder $query, Entity $model, $input) protected function filterSortBy(EloquentBuilder $query, Entity $model, $input)
{ {
$functionName = camel_case('sort_by_' . $input); $functionName = Str::camel('sort_by_' . $input);
if (method_exists($this, $functionName)) { if (method_exists($this, $functionName)) {
$this->$functionName($query, $model); $this->$functionName($query, $model);
} }

View File

@ -18,6 +18,8 @@ use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Response; use Illuminate\Http\Response;
use Illuminate\Routing\Redirector; use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Laravel\Socialite\Contracts\User as SocialUser; use Laravel\Socialite\Contracts\User as SocialUser;
use Validator; use Validator;
@ -77,7 +79,7 @@ class RegisterController extends Controller
return Validator::make($data, [ return Validator::make($data, [
'name' => 'required|min:2|max:255', 'name' => 'required|min:2|max:255',
'email' => 'required|email|max:255|unique:users', 'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6', 'password' => 'required|min:8',
]); ]);
} }
@ -129,7 +131,7 @@ class RegisterController extends Controller
return User::create([ return User::create([
'name' => $data['name'], 'name' => $data['name'],
'email' => $data['email'], 'email' => $data['email'],
'password' => bcrypt($data['password']), 'password' => Hash::make($data['password']),
]); ]);
} }
@ -261,7 +263,7 @@ class RegisterController extends Controller
$userData = [ $userData = [
'name' => $socialUser->getName(), 'name' => $socialUser->getName(),
'email' => $socialUser->getEmail(), 'email' => $socialUser->getEmail(),
'password' => str_random(30) 'password' => Str::random(30)
]; ];
return $this->registerUser($userData, $socialAccount, $emailVerified); return $this->registerUser($userData, $socialAccount, $emailVerified);
} }

View File

@ -4,6 +4,7 @@ namespace BookStack\Http\Controllers\Auth;
use BookStack\Http\Controllers\Controller; use BookStack\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords; use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Http\Request;
class ResetPasswordController extends Controller class ResetPasswordController extends Controller
{ {
@ -36,10 +37,11 @@ class ResetPasswordController extends Controller
/** /**
* Get the response for a successful password reset. * Get the response for a successful password reset.
* *
* @param string $response * @param Request $request
* @param string $response
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
protected function sendResetResponse($response) protected function sendResetResponse(Request $request, $response)
{ {
$message = trans('auth.reset_password_success'); $message = trans('auth.reset_password_success');
session()->flash('success', $message); session()->flash('success', $message);

View File

@ -62,7 +62,7 @@ class UserInviteController extends Controller
public function setPassword(string $token, Request $request) public function setPassword(string $token, Request $request)
{ {
$this->validate($request, [ $this->validate($request, [
'password' => 'required|min:6' 'password' => 'required|min:8'
]); ]);
try { try {

View File

@ -8,6 +8,7 @@ use BookStack\Exceptions\UserUpdateException;
use BookStack\Uploads\ImageRepo; use BookStack\Uploads\ImageRepo;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Response; use Illuminate\Http\Response;
use Illuminate\Support\Str;
class UserController extends Controller class UserController extends Controller
{ {
@ -92,7 +93,7 @@ class UserController extends Controller
$user = $this->user->fill($request->all()); $user = $this->user->fill($request->all());
if ($authMethod === 'standard') { if ($authMethod === 'standard') {
$user->password = bcrypt($request->get('password', str_random(32))); $user->password = bcrypt($request->get('password', Str::random(32)));
} elseif ($authMethod === 'ldap') { } elseif ($authMethod === 'ldap') {
$user->external_auth_id = $request->get('external_auth_id'); $user->external_auth_id = $request->get('external_auth_id');
} }

View File

@ -12,7 +12,7 @@ class Kernel extends HttpKernel
* @var array * @var array
*/ */
protected $middleware = [ protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class, \BookStack\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\BookStack\Http\Middleware\TrimStrings::class, \BookStack\Http\Middleware\TrimStrings::class,
\BookStack\Http\Middleware\TrustProxies::class, \BookStack\Http\Middleware\TrustProxies::class,
@ -29,6 +29,7 @@ class Kernel extends HttpKernel
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class, \Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class,
\BookStack\Http\Middleware\VerifyCsrfToken::class, \BookStack\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class, \Illuminate\Routing\Middleware\SubstituteBindings::class,
\BookStack\Http\Middleware\Localization::class \BookStack\Http\Middleware\Localization::class

View File

@ -0,0 +1,17 @@
<?php
namespace BookStack\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as Middleware;
class CheckForMaintenanceMode extends Middleware
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array
*/
protected $except = [
//
];
}

View File

@ -16,17 +16,11 @@ class TrustProxies extends Middleware
protected $proxies; protected $proxies;
/** /**
* The current proxy header mappings. * The headers that should be used to detect proxies.
* *
* @var array * @var int
*/ */
protected $headers = [ protected $headers = Request::HEADER_X_FORWARDED_ALL;
Request::HEADER_FORWARDED => 'FORWARDED',
Request::HEADER_X_FORWARDED_FOR => 'X_FORWARDED_FOR',
Request::HEADER_X_FORWARDED_HOST => 'X_FORWARDED_HOST',
Request::HEADER_X_FORWARDED_PORT => 'X_FORWARDED_PORT',
Request::HEADER_X_FORWARDED_PROTO => 'X_FORWARDED_PROTO',
];
/** /**
* Handle the request, Set the correct user-configured proxy information. * Handle the request, Set the correct user-configured proxy information.

View File

@ -6,6 +6,13 @@ use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware class VerifyCsrfToken extends Middleware
{ {
/**
* Indicates whether the XSRF-TOKEN cookie should be set on the response.
*
* @var bool
*/
protected $addHttpCookie = true;
/** /**
* The URIs that should be excluded from CSRF verification. * The URIs that should be excluded from CSRF verification.
* *

View File

@ -13,7 +13,7 @@ class Attachment extends Ownable
*/ */
public function getFileName() public function getFileName()
{ {
if (str_contains($this->name, '.')) { if (strpos($this->name, '.') !== false) {
return $this->name; return $this->name;
} }
return $this->name . '.' . $this->extension; return $this->name . '.' . $this->extension;

View File

@ -2,6 +2,7 @@
use BookStack\Exceptions\FileUploadException; use BookStack\Exceptions\FileUploadException;
use Exception; use Exception;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\File\UploadedFile;
class AttachmentService extends UploadService class AttachmentService extends UploadService
@ -185,9 +186,9 @@ class AttachmentService extends UploadService
$storage = $this->getStorage(); $storage = $this->getStorage();
$basePath = 'uploads/files/' . Date('Y-m-M') . '/'; $basePath = 'uploads/files/' . Date('Y-m-M') . '/';
$uploadFileName = str_random(16) . '.' . $uploadedFile->getClientOriginalExtension(); $uploadFileName = Str::random(16) . '.' . $uploadedFile->getClientOriginalExtension();
while ($storage->exists($basePath . $uploadFileName)) { while ($storage->exists($basePath . $uploadFileName)) {
$uploadFileName = str_random(3) . $uploadFileName; $uploadFileName = Str::random(3) . $uploadFileName;
} }
$attachmentPath = $basePath . $uploadFileName; $attachmentPath = $basePath . $uploadFileName;

View File

@ -7,6 +7,7 @@ use DB;
use Exception; use Exception;
use Illuminate\Contracts\Cache\Repository as Cache; use Illuminate\Contracts\Cache\Repository as Cache;
use Illuminate\Contracts\Filesystem\Factory as FileSystem; use Illuminate\Contracts\Filesystem\Factory as FileSystem;
use Illuminate\Support\Str;
use Intervention\Image\Exception\NotSupportedException; use Intervention\Image\Exception\NotSupportedException;
use Intervention\Image\ImageManager; use Intervention\Image\ImageManager;
use phpDocumentor\Reflection\Types\Integer; use phpDocumentor\Reflection\Types\Integer;
@ -140,12 +141,12 @@ class ImageService extends UploadService
$imagePath = '/uploads/images/' . $type . '/' . Date('Y-m') . '/'; $imagePath = '/uploads/images/' . $type . '/' . Date('Y-m') . '/';
while ($storage->exists($imagePath . $imageName)) { while ($storage->exists($imagePath . $imageName)) {
$imageName = str_random(3) . $imageName; $imageName = Str::random(3) . $imageName;
} }
$fullPath = $imagePath . $imageName; $fullPath = $imagePath . $imageName;
if ($secureUploads) { if ($secureUploads) {
$fullPath = $imagePath . str_random(16) . '-' . $imageName; $fullPath = $imagePath . Str::random(16) . '-' . $imageName;
} }
try { try {
@ -220,7 +221,7 @@ class ImageService extends UploadService
$storage->put($thumbFilePath, $thumbData); $storage->put($thumbFilePath, $thumbData);
$storage->setVisibility($thumbFilePath, 'public'); $storage->setVisibility($thumbFilePath, 'public');
$this->cache->put('images-' . $image->id . '-' . $thumbFilePath, $thumbFilePath, 60 * 72); $this->cache->put('images-' . $image->id . '-' . $thumbFilePath, $thumbFilePath, 60 * 60 * 72);
return $this->getPublicUrl($thumbFilePath); return $this->getPublicUrl($thumbFilePath);
} }

View File

@ -142,7 +142,7 @@ function icon($name, $attrs = [])
$attrString .= $attrName . '="' . $attr . '" '; $attrString .= $attrName . '="' . $attr . '" ';
} }
$iconPath = resource_path('assets/icons/' . $name . '.svg'); $iconPath = resource_path('icons/' . $name . '.svg');
$themeIconPath = theme_path('icons/' . $name . '.svg'); $themeIconPath = theme_path('icons/' . $name . '.svg');
if ($themeIconPath && file_exists($themeIconPath)) { if ($themeIconPath && file_exists($themeIconPath)) {
$iconPath = $themeIconPath; $iconPath = $themeIconPath;

View File

@ -11,8 +11,8 @@
| |
*/ */
$app = new \BookStack\Application( $app = new BookStack\Application(
realpath(__DIR__.'/../') dirname(__DIR__)
); );
/* /*

View File

@ -5,46 +5,46 @@
"license": "MIT", "license": "MIT",
"type": "project", "type": "project",
"require": { "require": {
"php": ">=7.0.5", "php": "^7.2",
"ext-json": "*",
"ext-tidy": "*",
"ext-dom": "*",
"ext-xml": "*",
"ext-mbstring": "*",
"ext-gd": "*",
"ext-curl": "*", "ext-curl": "*",
"laravel/framework": "~5.5.44", "ext-dom": "*",
"fideloper/proxy": "~3.3", "ext-gd": "*",
"intervention/image": "^2.4", "ext-json": "*",
"laravel/socialite": "3.0.x-dev", "ext-mbstring": "*",
"league/flysystem-aws-s3-v3": "^1.0", "ext-tidy": "*",
"barryvdh/laravel-dompdf": "^0.8.1", "ext-xml": "*",
"predis/predis": "^1.1", "barryvdh/laravel-dompdf": "^0.8.5",
"barryvdh/laravel-snappy": "^0.4.5",
"doctrine/dbal": "^2.9",
"fideloper/proxy": "^4.0",
"gathercontent/htmldiff": "^0.2.1", "gathercontent/htmldiff": "^0.2.1",
"barryvdh/laravel-snappy": "^0.4.0", "intervention/image": "^2.5",
"socialiteproviders/slack": "^3.0", "laravel/framework": "^6.0",
"laravel/socialite": "^4.2",
"league/flysystem-aws-s3-v3": "^1.0",
"predis/predis": "^1.1",
"socialiteproviders/discord": "^2.0",
"socialiteproviders/gitlab": "^3.0",
"socialiteproviders/microsoft-azure": "^3.0", "socialiteproviders/microsoft-azure": "^3.0",
"socialiteproviders/okta": "^1.0", "socialiteproviders/okta": "^1.0",
"socialiteproviders/gitlab": "^3.0", "socialiteproviders/slack": "^3.0",
"socialiteproviders/twitch": "^3.0", "socialiteproviders/twitch": "^3.0"
"socialiteproviders/discord": "^2.0",
"doctrine/dbal": "^2.5"
}, },
"require-dev": { "require-dev": {
"filp/whoops": "~2.0", "facade/ignition": "^1.4",
"fzaninotto/faker": "~1.4", "fzaninotto/faker": "^1.4",
"mockery/mockery": "~1.0", "mockery/mockery": "^1.0",
"phpunit/phpunit": "~6.0", "phpunit/phpunit": "^8.0",
"symfony/css-selector": "3.1.*", "nunomaduro/collision": "^3.0",
"symfony/dom-crawler": "3.1.*", "laravel/browser-kit-testing": "^5.1",
"laravel/browser-kit-testing": "^2.0", "barryvdh/laravel-ide-helper": "^2.6.4",
"barryvdh/laravel-ide-helper": "^2.4.1", "barryvdh/laravel-debugbar": "^3.2.8",
"barryvdh/laravel-debugbar": "^3.1.0", "squizlabs/php_codesniffer": "^3.4"
"squizlabs/php_codesniffer": "^3.2"
}, },
"autoload": { "autoload": {
"classmap": [ "classmap": [
"database" "database/seeds",
"database/factories"
], ],
"psr-4": { "psr-4": {
"BookStack\\": "app/" "BookStack\\": "app/"
@ -57,37 +57,45 @@
}, },
"scripts": { "scripts": {
"post-root-package-install": [ "post-root-package-install": [
"php -r \"file_exists('.env') || copy('.env.example', '.env');\"" "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
], ],
"post-create-project-cmd": [ "post-create-project-cmd": [
"php artisan key:generate" "@php artisan key:generate --ansi"
], ],
"pre-update-cmd": [ "pre-update-cmd": [
"php -r \"!file_exists('bootstrap/cache/services.php') || @unlink('bootstrap/cache/services.php');\"", "@php -r \"!file_exists('bootstrap/cache/services.php') || @unlink('bootstrap/cache/services.php');\"",
"php -r \"!file_exists('bootstrap/cache/compiled.php') || @unlink('bootstrap/cache/compiled.php');\"" "@php -r \"!file_exists('bootstrap/cache/compiled.php') || @unlink('bootstrap/cache/compiled.php');\""
], ],
"pre-install-cmd": [ "pre-install-cmd": [
"php -r \"!file_exists('bootstrap/cache/services.php') || @unlink('bootstrap/cache/services.php');\"", "@php -r \"!file_exists('bootstrap/cache/services.php') || @unlink('bootstrap/cache/services.php');\"",
"php -r \"!file_exists('bootstrap/cache/compiled.php') || @unlink('bootstrap/cache/compiled.php');\"" "@php -r \"!file_exists('bootstrap/cache/compiled.php') || @unlink('bootstrap/cache/compiled.php');\""
], ],
"post-install-cmd": [ "post-install-cmd": [
"php artisan cache:clear", "@php artisan cache:clear",
"php artisan view:clear" "@php artisan view:clear"
], ],
"post-autoload-dump": [ "post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover" "@php artisan package:discover --ansi"
], ],
"refresh-test-database": [ "refresh-test-database": [
"php artisan migrate:refresh --database=mysql_testing", "@php artisan migrate:refresh --database=mysql_testing",
"php artisan db:seed --class=DummyContentSeeder --database=mysql_testing" "@php artisan db:seed --class=DummyContentSeeder --database=mysql_testing"
] ]
}, },
"config": { "config": {
"optimize-autoloader": true, "optimize-autoloader": true,
"preferred-install": "dist", "preferred-install": "dist",
"sort-packages": true,
"platform": { "platform": {
"php": "7.0.5" "php": "7.2.0"
} }
} },
"extra": {
"laravel": {
"dont-discover": []
}
},
"minimum-stability": "dev",
"prefer-stable": true
} }

2974
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -15,8 +15,8 @@ $factory->define(\BookStack\Auth\User::class, function ($faker) {
return [ return [
'name' => $faker->name, 'name' => $faker->name,
'email' => $faker->email, 'email' => $faker->email,
'password' => str_random(10), 'password' => Str::random(10),
'remember_token' => str_random(10), 'remember_token' => Str::random(10),
'email_confirmed' => 1 'email_confirmed' => 1
]; ];
}); });
@ -24,7 +24,7 @@ $factory->define(\BookStack\Auth\User::class, function ($faker) {
$factory->define(\BookStack\Entities\Bookshelf::class, function ($faker) { $factory->define(\BookStack\Entities\Bookshelf::class, function ($faker) {
return [ return [
'name' => $faker->sentence, 'name' => $faker->sentence,
'slug' => str_random(10), 'slug' => Str::random(10),
'description' => $faker->paragraph 'description' => $faker->paragraph
]; ];
}); });
@ -32,7 +32,7 @@ $factory->define(\BookStack\Entities\Bookshelf::class, function ($faker) {
$factory->define(\BookStack\Entities\Book::class, function ($faker) { $factory->define(\BookStack\Entities\Book::class, function ($faker) {
return [ return [
'name' => $faker->sentence, 'name' => $faker->sentence,
'slug' => str_random(10), 'slug' => Str::random(10),
'description' => $faker->paragraph 'description' => $faker->paragraph
]; ];
}); });
@ -40,7 +40,7 @@ $factory->define(\BookStack\Entities\Book::class, function ($faker) {
$factory->define(\BookStack\Entities\Chapter::class, function ($faker) { $factory->define(\BookStack\Entities\Chapter::class, function ($faker) {
return [ return [
'name' => $faker->sentence, 'name' => $faker->sentence,
'slug' => str_random(10), 'slug' => Str::random(10),
'description' => $faker->paragraph 'description' => $faker->paragraph
]; ];
}); });
@ -49,7 +49,7 @@ $factory->define(\BookStack\Entities\Page::class, function ($faker) {
$html = '<p>' . implode('</p>', $faker->paragraphs(5)) . '</p>'; $html = '<p>' . implode('</p>', $faker->paragraphs(5)) . '</p>';
return [ return [
'name' => $faker->sentence, 'name' => $faker->sentence,
'slug' => str_random(10), 'slug' => Str::random(10),
'html' => $html, 'html' => $html,
'text' => strip_tags($html), 'text' => strip_tags($html),
'revision_count' => 1 'revision_count' => 1

View File

@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
class DatabaseSeeder extends Seeder class DatabaseSeeder extends Seeder
{ {
/** /**
* Run the database seeds. * Seed the application's database.
* *
* @return void * @return void
*/ */

View File

@ -1,6 +1,14 @@
<?php <?php
use BookStack\Auth\Permissions\PermissionService;
use BookStack\Auth\Role;
use BookStack\Auth\User;
use BookStack\Entities\Bookshelf;
use BookStack\Entities\Chapter;
use BookStack\Entities\Page;
use BookStack\Entities\SearchService;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
use Illuminate\Support\Str;
class DummyContentSeeder extends Seeder class DummyContentSeeder extends Seeder
{ {
@ -12,39 +20,39 @@ class DummyContentSeeder extends Seeder
public function run() public function run()
{ {
// Create an editor user // Create an editor user
$editorUser = factory(\BookStack\Auth\User::class)->create(); $editorUser = factory(User::class)->create();
$editorRole = \BookStack\Auth\Role::getRole('editor'); $editorRole = Role::getRole('editor');
$editorUser->attachRole($editorRole); $editorUser->attachRole($editorRole);
// Create a viewer user // Create a viewer user
$viewerUser = factory(\BookStack\Auth\User::class)->create(); $viewerUser = factory(User::class)->create();
$role = \BookStack\Auth\Role::getRole('viewer'); $role = Role::getRole('viewer');
$viewerUser->attachRole($role); $viewerUser->attachRole($role);
$byData = ['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]; $byData = ['created_by' => $editorUser->id, 'updated_by' => $editorUser->id];
factory(\BookStack\Entities\Book::class, 5)->create($byData) factory(\BookStack\Entities\Book::class, 5)->create($byData)
->each(function($book) use ($editorUser, $byData) { ->each(function($book) use ($editorUser, $byData) {
$chapters = factory(\BookStack\Entities\Chapter::class, 3)->create($byData) $chapters = factory(Chapter::class, 3)->create($byData)
->each(function($chapter) use ($editorUser, $book, $byData){ ->each(function($chapter) use ($editorUser, $book, $byData){
$pages = factory(\BookStack\Entities\Page::class, 3)->make(array_merge($byData, ['book_id' => $book->id])); $pages = factory(Page::class, 3)->make(array_merge($byData, ['book_id' => $book->id]));
$chapter->pages()->saveMany($pages); $chapter->pages()->saveMany($pages);
}); });
$pages = factory(\BookStack\Entities\Page::class, 3)->make($byData); $pages = factory(Page::class, 3)->make($byData);
$book->chapters()->saveMany($chapters); $book->chapters()->saveMany($chapters);
$book->pages()->saveMany($pages); $book->pages()->saveMany($pages);
}); });
$largeBook = factory(\BookStack\Entities\Book::class)->create(array_merge($byData, ['name' => 'Large book' . str_random(10)])); $largeBook = factory(\BookStack\Entities\Book::class)->create(array_merge($byData, ['name' => 'Large book' . Str::random(10)]));
$pages = factory(\BookStack\Entities\Page::class, 200)->make($byData); $pages = factory(Page::class, 200)->make($byData);
$chapters = factory(\BookStack\Entities\Chapter::class, 50)->make($byData); $chapters = factory(Chapter::class, 50)->make($byData);
$largeBook->pages()->saveMany($pages); $largeBook->pages()->saveMany($pages);
$largeBook->chapters()->saveMany($chapters); $largeBook->chapters()->saveMany($chapters);
$shelves = factory(\BookStack\Entities\Bookshelf::class, 10)->create($byData); $shelves = factory(Bookshelf::class, 10)->create($byData);
$largeBook->shelves()->attach($shelves->pluck('id')); $largeBook->shelves()->attach($shelves->pluck('id'));
app(\BookStack\Auth\Permissions\PermissionService::class)->buildJointPermissions(); app(PermissionService::class)->buildJointPermissions();
app(\BookStack\Entities\SearchService::class)->indexAllEntities(); app(SearchService::class)->indexAllEntities();
} }
} }

View File

@ -1,6 +1,13 @@
<?php <?php
use BookStack\Auth\Permissions\PermissionService;
use BookStack\Auth\Role;
use BookStack\Auth\User;
use BookStack\Entities\Chapter;
use BookStack\Entities\Page;
use BookStack\Entities\SearchService;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
use Illuminate\Support\Str;
class LargeContentSeeder extends Seeder class LargeContentSeeder extends Seeder
{ {
@ -12,16 +19,16 @@ class LargeContentSeeder extends Seeder
public function run() public function run()
{ {
// Create an editor user // Create an editor user
$editorUser = factory(\BookStack\Auth\User::class)->create(); $editorUser = factory(User::class)->create();
$editorRole = \BookStack\Auth\Role::getRole('editor'); $editorRole = Role::getRole('editor');
$editorUser->attachRole($editorRole); $editorUser->attachRole($editorRole);
$largeBook = factory(\BookStack\Entities\Book::class)->create(['name' => 'Large book' . str_random(10), 'created_by' => $editorUser->id, 'updated_by' => $editorUser->id]); $largeBook = factory(\BookStack\Entities\Book::class)->create(['name' => 'Large book' . Str::random(10), 'created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
$pages = factory(\BookStack\Entities\Page::class, 200)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]); $pages = factory(Page::class, 200)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
$chapters = factory(\BookStack\Entities\Chapter::class, 50)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]); $chapters = factory(Chapter::class, 50)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
$largeBook->pages()->saveMany($pages); $largeBook->pages()->saveMany($pages);
$largeBook->chapters()->saveMany($chapters); $largeBook->chapters()->saveMany($chapters);
app(\BookStack\Auth\Permissions\PermissionService::class)->buildJointPermissions(); app(PermissionService::class)->buildJointPermissions();
app(\BookStack\Entities\SearchService::class)->indexAllEntities(); app(SearchService::class)->indexAllEntities();
} }
} }

View File

@ -7,8 +7,7 @@
convertNoticesToExceptions="true" convertNoticesToExceptions="true"
convertWarningsToExceptions="true" convertWarningsToExceptions="true"
processIsolation="false" processIsolation="false"
stopOnFailure="false" stopOnFailure="false">
syntaxCheck="false">
<testsuites> <testsuites>
<testsuite name="Application Test Suite"> <testsuite name="Application Test Suite">
<directory>./tests/</directory> <directory>./tests/</directory>
@ -20,32 +19,34 @@
</whitelist> </whitelist>
</filter> </filter>
<php> <php>
<env name="APP_ENV" value="testing"/> <server name="APP_ENV" value="testing"/>
<env name="APP_DEBUG" value="false"/> <server name="APP_DEBUG" value="false"/>
<env name="APP_LANG" value="en"/> <server name="APP_LANG" value="en"/>
<env name="APP_AUTO_LANG_PUBLIC" value="true"/> <server name="APP_AUTO_LANG_PUBLIC" value="true"/>
<env name="CACHE_DRIVER" value="array"/> <server name="CACHE_DRIVER" value="array"/>
<env name="SESSION_DRIVER" value="array"/> <server name="SESSION_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/> <server name="QUEUE_CONNECTION" value="sync"/>
<env name="DB_CONNECTION" value="mysql_testing"/> <server name="DB_CONNECTION" value="mysql_testing"/>
<env name="MAIL_DRIVER" value="log"/> <server name="BCRYPT_ROUNDS" value="4"/>
<env name="AUTH_METHOD" value="standard"/> <server name="MAIL_DRIVER" value="array"/>
<env name="DISABLE_EXTERNAL_SERVICES" value="true"/> <server name="LOG_CHANNEL" value="null"/>
<env name="AVATAR_URL" value=""/> <server name="AUTH_METHOD" value="standard"/>
<env name="LDAP_VERSION" value="3"/> <server name="DISABLE_EXTERNAL_SERVICES" value="true"/>
<env name="STORAGE_TYPE" value="local"/> <server name="AVATAR_URL" value=""/>
<env name="STORAGE_ATTACHMENT_TYPE" value="local"/> <server name="LDAP_VERSION" value="3"/>
<env name="STORAGE_IMAGE_TYPE" value="local"/> <server name="STORAGE_TYPE" value="local"/>
<env name="GITHUB_APP_ID" value="aaaaaaaaaaaaaa"/> <server name="STORAGE_ATTACHMENT_TYPE" value="local"/>
<env name="GITHUB_APP_SECRET" value="aaaaaaaaaaaaaa"/> <server name="STORAGE_IMAGE_TYPE" value="local"/>
<env name="GITHUB_AUTO_REGISTER" value=""/> <server name="GITHUB_APP_ID" value="aaaaaaaaaaaaaa"/>
<env name="GITHUB_AUTO_CONFIRM_EMAIL" value=""/> <server name="GITHUB_APP_SECRET" value="aaaaaaaaaaaaaa"/>
<env name="GOOGLE_APP_ID" value="aaaaaaaaaaaaaa"/> <server name="GITHUB_AUTO_REGISTER" value=""/>
<env name="GOOGLE_APP_SECRET" value="aaaaaaaaaaaaaa"/> <server name="GITHUB_AUTO_CONFIRM_EMAIL" value=""/>
<env name="GOOGLE_AUTO_REGISTER" value=""/> <server name="GOOGLE_APP_ID" value="aaaaaaaaaaaaaa"/>
<env name="GOOGLE_AUTO_CONFIRM_EMAIL" value=""/> <server name="GOOGLE_APP_SECRET" value="aaaaaaaaaaaaaa"/>
<env name="GOOGLE_SELECT_ACCOUNT" value=""/> <server name="GOOGLE_AUTO_REGISTER" value=""/>
<env name="APP_URL" value="http://bookstack.dev"/> <server name="GOOGLE_AUTO_CONFIRM_EMAIL" value=""/>
<env name="DEBUGBAR_ENABLED" value="false"/> <server name="GOOGLE_SELECT_ACCOUNT" value=""/>
<server name="APP_URL" value="http://bookstack.dev"/>
<server name="DEBUGBAR_ENABLED" value="false"/>
</php> </php>
</phpunit> </phpunit>

28
public/web.config Normal file
View File

@ -0,0 +1,28 @@
<!--
Rewrites requires Microsoft URL Rewrite Module for IIS
Download: https://www.microsoft.com/en-us/download/details.aspx?id=47337
Debug Help: https://docs.microsoft.com/en-us/iis/extensions/url-rewrite-module/using-failed-request-tracing-to-trace-rewrite-rules
-->
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Imported Rule 1" stopProcessing="true">
<match url="^(.*)/$" ignoreCase="false" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
</conditions>
<action type="Redirect" redirectType="Permanent" url="/{R:1}" />
</rule>
<rule name="Imported Rule 2" stopProcessing="true">
<match url="^" ignoreCase="false" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
</conditions>
<action type="Rewrite" url="index.php" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

View File

Before

Width:  |  Height:  |  Size: 284 B

After

Width:  |  Height:  |  Size: 284 B

View File

Before

Width:  |  Height:  |  Size: 166 B

After

Width:  |  Height:  |  Size: 166 B

View File

Before

Width:  |  Height:  |  Size: 359 B

After

Width:  |  Height:  |  Size: 359 B

View File

Before

Width:  |  Height:  |  Size: 258 B

After

Width:  |  Height:  |  Size: 258 B

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 541 B

After

Width:  |  Height:  |  Size: 541 B

View File

Before

Width:  |  Height:  |  Size: 871 B

After

Width:  |  Height:  |  Size: 871 B

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 906 B

After

Width:  |  Height:  |  Size: 906 B

View File

Before

Width:  |  Height:  |  Size: 392 B

After

Width:  |  Height:  |  Size: 392 B

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 392 B

After

Width:  |  Height:  |  Size: 392 B

View File

Before

Width:  |  Height:  |  Size: 746 B

After

Width:  |  Height:  |  Size: 746 B

View File

Before

Width:  |  Height:  |  Size: 186 B

After

Width:  |  Height:  |  Size: 186 B

View File

Before

Width:  |  Height:  |  Size: 227 B

After

Width:  |  Height:  |  Size: 227 B

View File

Before

Width:  |  Height:  |  Size: 416 B

After

Width:  |  Height:  |  Size: 416 B

View File

Before

Width:  |  Height:  |  Size: 373 B

After

Width:  |  Height:  |  Size: 373 B

View File

Before

Width:  |  Height:  |  Size: 301 B

After

Width:  |  Height:  |  Size: 301 B

View File

Before

Width:  |  Height:  |  Size: 140 B

After

Width:  |  Height:  |  Size: 140 B

View File

Before

Width:  |  Height:  |  Size: 197 B

After

Width:  |  Height:  |  Size: 197 B

View File

Before

Width:  |  Height:  |  Size: 216 B

After

Width:  |  Height:  |  Size: 216 B

View File

Before

Width:  |  Height:  |  Size: 133 B

After

Width:  |  Height:  |  Size: 133 B

View File

Before

Width:  |  Height:  |  Size: 280 B

After

Width:  |  Height:  |  Size: 280 B

View File

Before

Width:  |  Height:  |  Size: 243 B

After

Width:  |  Height:  |  Size: 243 B

View File

Before

Width:  |  Height:  |  Size: 151 B

After

Width:  |  Height:  |  Size: 151 B

View File

Before

Width:  |  Height:  |  Size: 157 B

After

Width:  |  Height:  |  Size: 157 B

View File

Before

Width:  |  Height:  |  Size: 161 B

After

Width:  |  Height:  |  Size: 161 B

View File

Before

Width:  |  Height:  |  Size: 172 B

After

Width:  |  Height:  |  Size: 172 B

View File

Before

Width:  |  Height:  |  Size: 227 B

After

Width:  |  Height:  |  Size: 227 B

View File

Before

Width:  |  Height:  |  Size: 248 B

After

Width:  |  Height:  |  Size: 248 B

View File

Before

Width:  |  Height:  |  Size: 211 B

After

Width:  |  Height:  |  Size: 211 B

View File

Before

Width:  |  Height:  |  Size: 298 B

After

Width:  |  Height:  |  Size: 298 B

View File

Before

Width:  |  Height:  |  Size: 203 B

After

Width:  |  Height:  |  Size: 203 B

View File

Before

Width:  |  Height:  |  Size: 364 B

After

Width:  |  Height:  |  Size: 364 B

View File

Before

Width:  |  Height:  |  Size: 275 B

After

Width:  |  Height:  |  Size: 275 B

View File

Before

Width:  |  Height:  |  Size: 247 B

After

Width:  |  Height:  |  Size: 247 B

View File

Before

Width:  |  Height:  |  Size: 256 B

After

Width:  |  Height:  |  Size: 256 B

View File

Before

Width:  |  Height:  |  Size: 221 B

After

Width:  |  Height:  |  Size: 221 B

View File

Before

Width:  |  Height:  |  Size: 217 B

After

Width:  |  Height:  |  Size: 217 B

View File

Before

Width:  |  Height:  |  Size: 213 B

After

Width:  |  Height:  |  Size: 213 B

View File

Before

Width:  |  Height:  |  Size: 171 B

After

Width:  |  Height:  |  Size: 171 B

View File

Before

Width:  |  Height:  |  Size: 350 B

After

Width:  |  Height:  |  Size: 350 B

View File

Before

Width:  |  Height:  |  Size: 246 B

After

Width:  |  Height:  |  Size: 246 B

View File

Before

Width:  |  Height:  |  Size: 270 B

After

Width:  |  Height:  |  Size: 270 B

View File

Before

Width:  |  Height:  |  Size: 264 B

After

Width:  |  Height:  |  Size: 264 B

View File

Before

Width:  |  Height:  |  Size: 222 B

After

Width:  |  Height:  |  Size: 222 B

View File

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 282 B

View File

Before

Width:  |  Height:  |  Size: 295 B

After

Width:  |  Height:  |  Size: 295 B

View File

Before

Width:  |  Height:  |  Size: 213 B

After

Width:  |  Height:  |  Size: 213 B

View File

Before

Width:  |  Height:  |  Size: 357 B

After

Width:  |  Height:  |  Size: 357 B

View File

Before

Width:  |  Height:  |  Size: 537 B

After

Width:  |  Height:  |  Size: 537 B

View File

Before

Width:  |  Height:  |  Size: 271 B

After

Width:  |  Height:  |  Size: 271 B

View File

Before

Width:  |  Height:  |  Size: 270 B

After

Width:  |  Height:  |  Size: 270 B

View File

Before

Width:  |  Height:  |  Size: 271 B

After

Width:  |  Height:  |  Size: 271 B

View File

Before

Width:  |  Height:  |  Size: 267 B

After

Width:  |  Height:  |  Size: 267 B

View File

Before

Width:  |  Height:  |  Size: 690 B

After

Width:  |  Height:  |  Size: 690 B

View File

Before

Width:  |  Height:  |  Size: 252 B

After

Width:  |  Height:  |  Size: 252 B

View File

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 282 B

View File

Before

Width:  |  Height:  |  Size: 431 B

After

Width:  |  Height:  |  Size: 431 B

Some files were not shown because too many files have changed in this diff Show More