Updated to laravel 5.5

Closes #590
This commit is contained in:
Dan Brown 2017-11-19 15:56:06 +00:00
parent 65579214e2
commit 873b1099f8
No known key found for this signature in database
GPG key ID: 46D9F943C24A2EF9
23 changed files with 3371 additions and 2697 deletions

7
.gitignore vendored
View file

@ -2,8 +2,10 @@
/node_modules
Homestead.yaml
.env
/public/dist
.idea
npm-debug.log
yarn-error.log
/public/dist
/public/plugins
/public/css
/public/js
@ -18,5 +20,4 @@ yarn.lock
nbproject
.buildpath
.project
.settings/org.eclipse.wst.common.project.facet.core.xml
.settings/org.eclipse.php.core.prefs
.settings/

View file

@ -3,6 +3,7 @@ sudo: false
language: php
php:
- 7.0.7
- 7.1.9
cache:
directories:

View file

@ -11,12 +11,7 @@ class Kernel extends ConsoleKernel
* @var array
*/
protected $commands = [
Commands\ClearViews::class,
Commands\ClearActivity::class,
Commands\ClearRevisions::class,
Commands\RegeneratePermissions::class,
Commands\RegenerateSearch::class,
Commands\UpgradeDatabaseEncoding::class
//
];
/**
@ -29,4 +24,14 @@ class Kernel extends ConsoleKernel
{
//
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
}
}

View file

@ -103,4 +103,16 @@ class Handler extends ExceptionHandler
return redirect()->guest('login');
}
/**
* Convert a validation exception into a JSON response.
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Validation\ValidationException $exception
* @return \Illuminate\Http\JsonResponse
*/
protected function invalidJson($request, ValidationException $exception)
{
return response()->json($exception->errors(), $exception->status);
}
}

View file

@ -72,13 +72,13 @@ class LoginController extends Controller
// Explicitly log them out for now if they do no exist.
if (!$user->exists) auth()->logout($user);
if (!$user->exists && $user->email === null && !$request->has('email')) {
if (!$user->exists && $user->email === null && !$request->filled('email')) {
$request->flash();
session()->flash('request-email', true);
return redirect('/login');
}
if (!$user->exists && $user->email === null && $request->has('email')) {
if (!$user->exists && $user->email === null && $request->filled('email')) {
$user->email = $request->get('email');
}

View file

@ -183,7 +183,7 @@ class BookController extends Controller
$this->checkOwnablePermission('book-update', $book);
// Return if no map sent
if (!$request->has('sort-tree')) {
if (!$request->filled('sort-tree')) {
return redirect($book->getUrl());
}

View file

@ -107,7 +107,7 @@ class ImageController extends Controller
$imageUpload = $request->file('file');
try {
$uploadedTo = $request->has('uploaded_to') ? $request->get('uploaded_to') : 0;
$uploadedTo = $request->filled('uploaded_to') ? $request->get('uploaded_to') : 0;
$image = $this->imageRepo->saveNew($imageUpload, $type, $uploadedTo);
} catch (ImageUploadException $e) {
return response($e->getMessage(), 500);
@ -162,7 +162,7 @@ class ImageController extends Controller
$this->checkOwnablePermission('image-delete', $image);
// Check if this image is used on any pages
$isForced = ($request->has('force') && ($request->get('force') === 'true') || $request->get('force') === true);
$isForced = in_array($request->get('force', ''), [true, 'true']);
if (!$isForced) {
$pageSearch = $entityRepo->searchForImage($image->url);
if ($pageSearch !== false) {

View file

@ -36,7 +36,7 @@ class SearchController extends Controller
$searchTerm = $request->get('term');
$this->setPageTitle(trans('entities.search_for_term', ['term' => $searchTerm]));
$page = $request->has('page') && is_int(intval($request->get('page'))) ? intval($request->get('page')) : 1;
$page = intval($request->get('page', '0')) ?: 1;
$nextPageLink = baseUrl('/search?term=' . urlencode($searchTerm) . '&page=' . ($page+1));
$results = $this->searchService->searchEntities($searchTerm, 'all', $page, 20);
@ -88,8 +88,8 @@ class SearchController extends Controller
*/
public function searchEntitiesAjax(Request $request)
{
$entityTypes = $request->has('types') ? collect(explode(',', $request->get('types'))) : collect(['page', 'chapter', 'book']);
$searchTerm = ($request->has('term') && trim($request->get('term')) !== '') ? $request->get('term') : false;
$entityTypes = $request->filled('types') ? collect(explode(',', $request->get('types'))) : collect(['page', 'chapter', 'book']);
$searchTerm = $request->get('term', false);
// Search for entities otherwise show most popular
if ($searchTerm !== false) {

View file

@ -37,7 +37,7 @@ class TagController extends Controller
*/
public function getNameSuggestions(Request $request)
{
$searchTerm = $request->has('search') ? $request->get('search') : false;
$searchTerm = $request->get('search', false);
$suggestions = $this->tagRepo->getNameSuggestions($searchTerm);
return response()->json($suggestions);
}
@ -49,8 +49,8 @@ class TagController extends Controller
*/
public function getValueSuggestions(Request $request)
{
$searchTerm = $request->has('search') ? $request->get('search') : false;
$tagName = $request->has('name') ? $request->get('name') : false;
$searchTerm = $request->get('search', false);
$tagName = $request->get('name', false);
$suggestions = $this->tagRepo->getValueSuggestions($searchTerm, $tagName);
return response()->json($suggestions);
}

View file

@ -34,9 +34,9 @@ class UserController extends Controller
{
$this->checkPermission('users-manage');
$listDetails = [
'order' => $request->has('order') ? $request->get('order') : 'asc',
'search' => $request->has('search') ? $request->get('search') : '',
'sort' => $request->has('sort') ? $request->get('sort') : 'name',
'order' => $request->get('order', 'asc'),
'search' => $request->get('search', ''),
'sort' => $request->get('sort', 'name'),
];
$users = $this->userRepo->getAllUsersPaginatedAndSorted(20, $listDetails);
$this->setPageTitle(trans('settings.users'));
@ -88,7 +88,7 @@ class UserController extends Controller
$user->save();
if ($request->has('roles')) {
if ($request->filled('roles')) {
$roles = $request->get('roles');
$user->roles()->sync($roles);
}
@ -155,24 +155,24 @@ class UserController extends Controller
$user->fill($request->all());
// Role updates
if (userCan('users-manage') && $request->has('roles')) {
if (userCan('users-manage') && $request->filled('roles')) {
$roles = $request->get('roles');
$user->roles()->sync($roles);
}
// Password updates
if ($request->has('password') && $request->get('password') != '') {
if ($request->filled('password')) {
$password = $request->get('password');
$user->password = bcrypt($password);
}
// External auth id updates
if ($this->currentUser->can('users-manage') && $request->has('external_auth_id')) {
if ($this->currentUser->can('users-manage') && $request->filled('external_auth_id')) {
$user->external_auth_id = $request->get('external_auth_id');
}
// Save an user-specific settings
if ($request->has('setting')) {
if ($request->filled('setting')) {
foreach ($request->get('setting') as $key => $value) {
setting()->putUser($user, $key, $value);
}

View file

@ -15,6 +15,7 @@ class Kernel extends HttpKernel
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\BookStack\Http\Middleware\TrimStrings::class,
\BookStack\Http\Middleware\TrustProxies::class,
];
/**
@ -44,10 +45,11 @@ class Kernel extends HttpKernel
* @var array
*/
protected $routeMiddleware = [
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'auth' => \BookStack\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \BookStack\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'perm' => \BookStack\Http\Middleware\PermissionMiddleware::class
];
}

View file

@ -2,9 +2,9 @@
namespace BookStack\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as BaseEncrypter;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
class EncryptCookies extends BaseEncrypter
class EncryptCookies extends Middleware
{
/**
* The names of the cookies that should not be encrypted.

View file

@ -2,9 +2,9 @@
namespace BookStack\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\TrimStrings as BaseTrimmer;
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
class TrimStrings extends BaseTrimmer
class TrimStrings extends Middleware
{
/**
* The names of the attributes that should not be trimmed.

View file

@ -0,0 +1,29 @@
<?php
namespace BookStack\Http\Middleware;
use Illuminate\Http\Request;
use Fideloper\Proxy\TrustProxies as Middleware;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array
*/
protected $proxies;
/**
* The current proxy header mappings.
*
* @var array
*/
protected $headers = [
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',
];
}

View file

@ -2,9 +2,9 @@
namespace BookStack\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends BaseVerifier
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.

View file

@ -442,9 +442,10 @@ class EntityRepo
*/
public function updateEntityPermissionsFromRequest($request, Entity $entity)
{
$entity->restricted = $request->has('restricted') && $request->get('restricted') === 'true';
$entity->restricted = $request->get('restricted', '') === 'true';
$entity->permissions()->delete();
if ($request->has('restrictions')) {
if ($request->filled('restrictions')) {
foreach ($request->get('restrictions') as $roleId => $restrictions) {
foreach ($restrictions as $action => $value) {
$entity->permissions()->create([
@ -454,6 +455,7 @@ class EntityRepo
}
}
}
$entity->save();
$this->permissionService->buildJointPermissionsForEntity($entity);
}

View file

@ -205,12 +205,17 @@ class PermissionService
}
$entities[] = $entity->book;
if ($entity->isA('page') && $entity->chapter_id) $entities[] = $entity->chapter;
if ($entity->isA('page') && $entity->chapter_id) {
$entities[] = $entity->chapter;
}
if ($entity->isA('chapter')) {
foreach ($entity->pages as $page) {
$entities[] = $page;
}
}
$this->deleteManyJointPermissionsForEntities($entities);
$this->buildJointPermissionsForEntities(collect($entities));
}

View file

@ -1,32 +1,34 @@
{
"name": "ssddanbrown/bookstack",
"name": "bookstackapp/bookstack",
"description": "BookStack documentation platform",
"keywords": ["BookStack", "Documentation"],
"license": "MIT",
"type": "project",
"require": {
"php": ">=5.6.4",
"laravel/framework": "5.4.*",
"php": ">=7.0.0",
"laravel/framework": "5.5.*",
"fideloper/proxy": "~3.3",
"ext-tidy": "*",
"intervention/image": "^2.3",
"intervention/image": "^2.4",
"laravel/socialite": "^3.0",
"barryvdh/laravel-ide-helper": "^2.2.3",
"barryvdh/laravel-debugbar": "^2.3.2",
"league/flysystem-aws-s3-v3": "^1.0",
"barryvdh/laravel-dompdf": "^0.8",
"barryvdh/laravel-dompdf": "^0.8.1",
"predis/predis": "^1.1",
"gathercontent/htmldiff": "^0.2.1",
"barryvdh/laravel-snappy": "^0.3.1",
"laravel/browser-kit-testing": "^1.0",
"barryvdh/laravel-snappy": "^0.4.0",
"socialiteproviders/slack": "^3.0",
"socialiteproviders/microsoft-azure": "^3.0"
},
"require-dev": {
"filp/whoops": "~2.0",
"fzaninotto/faker": "~1.4",
"mockery/mockery": "0.9.*",
"phpunit/phpunit": "~5.0",
"mockery/mockery": "~1.0",
"phpunit/phpunit": "~6.0",
"symfony/css-selector": "3.1.*",
"symfony/dom-crawler": "3.1.*"
"symfony/dom-crawler": "3.1.*",
"laravel/browser-kit-testing": "^2.0",
"barryvdh/laravel-ide-helper": "^2.4.1",
"barryvdh/laravel-debugbar": "^3.1.0"
},
"autoload": {
"classmap": [
@ -58,13 +60,15 @@
],
"post-install-cmd": [
"Illuminate\\Foundation\\ComposerScripts::postInstall",
"php artisan optimize",
"php artisan cache:clear",
"php artisan view:clear"
],
"post-update-cmd": [
"Illuminate\\Foundation\\ComposerScripts::postUpdate",
"php artisan optimize"
"Illuminate\\Foundation\\ComposerScripts::postUpdate"
],
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover"
],
"refresh-test-database": [
"php artisan migrate:refresh --database=mysql_testing",
@ -72,6 +76,7 @@
]
},
"config": {
"preferred-install": "dist"
"preferred-install": "dist",
"php": "7.0"
}
}

5777
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -11,25 +11,31 @@ class DummyContentSeeder extends Seeder
*/
public function run()
{
$user = factory(\BookStack\User::class)->create();
$role = \BookStack\Role::getRole('editor');
$user->attachRole($role);
// Create an editor user
$editorUser = factory(\BookStack\User::class)->create();
$editorRole = \BookStack\Role::getRole('editor');
$editorUser->attachRole($editorRole);
factory(\BookStack\Book::class, 20)->create(['created_by' => $user->id, 'updated_by' => $user->id])
->each(function($book) use ($user) {
$chapters = factory(\BookStack\Chapter::class, 5)->create(['created_by' => $user->id, 'updated_by' => $user->id])
->each(function($chapter) use ($user, $book){
$pages = factory(\BookStack\Page::class, 5)->make(['created_by' => $user->id, 'updated_by' => $user->id, 'book_id' => $book->id]);
// Create a viewer user
$viewerUser = factory(\BookStack\User::class)->create();
$role = \BookStack\Role::getRole('viewer');
$viewerUser->attachRole($role);
factory(\BookStack\Book::class, 20)->create(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id])
->each(function($book) use ($editorUser) {
$chapters = factory(\BookStack\Chapter::class, 5)->create(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id])
->each(function($chapter) use ($editorUser, $book){
$pages = factory(\BookStack\Page::class, 5)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id, 'book_id' => $book->id]);
$chapter->pages()->saveMany($pages);
});
$pages = factory(\BookStack\Page::class, 3)->make(['created_by' => $user->id, 'updated_by' => $user->id]);
$pages = factory(\BookStack\Page::class, 3)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
$book->chapters()->saveMany($chapters);
$book->pages()->saveMany($pages);
});
$largeBook = factory(\BookStack\Book::class)->create(['name' => 'Large book' . str_random(10), 'created_by' => $user->id, 'updated_by' => $user->id]);
$pages = factory(\BookStack\Page::class, 200)->make(['created_by' => $user->id, 'updated_by' => $user->id]);
$chapters = factory(\BookStack\Chapter::class, 50)->make(['created_by' => $user->id, 'updated_by' => $user->id]);
$largeBook = factory(\BookStack\Book::class)->create(['name' => 'Large book' . str_random(10), 'created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
$pages = factory(\BookStack\Page::class, 200)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
$chapters = factory(\BookStack\Chapter::class, 50)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
$largeBook->pages()->saveMany($pages);
$largeBook->chapters()->saveMany($chapters);
app(\BookStack\Services\PermissionService::class)->buildJointPermissions();

View file

@ -3,6 +3,7 @@
use BookStack\Entity;
use BookStack\Role;
use BookStack\Services\PermissionService;
use BookStack\User;
use Illuminate\Contracts\Console\Kernel;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Laravel\BrowserKitTesting\TestCase;
@ -129,15 +130,25 @@ abstract class BrowserKitTest extends TestCase
}
/**
* Quick way to create a new user
* Get an instance of a user with 'editor' permissions
* @param array $attributes
* @return mixed
*/
protected function getEditor($attributes = [])
{
$user = factory(\BookStack\User::class)->create($attributes);
$role = Role::getRole('editor');
$user->attachRole($role);;
$user = \BookStack\Role::getRole('editor')->users()->first();
if (!empty($attributes)) $user->forceFill($attributes)->save();
return $user;
}
/**
* Get an instance of a user with 'viewer' permissions
* @return mixed
*/
protected function getViewer()
{
$user = \BookStack\Role::getRole('viewer')->users()->first();
if (!empty($attributes)) $user->forceFill($attributes)->save();
return $user;
}

View file

@ -1,25 +1,33 @@
<?php namespace Tests;
use BookStack\Book;
use BookStack\Services\PermissionService;
use BookStack\User;
class RestrictionsTest extends BrowserKitTest
{
/**
* @var User
*/
protected $user;
/**
* @var User
*/
protected $viewer;
protected $restrictionService;
/**
* @var PermissionService
*/
protected $permissionService;
public function setUp()
{
parent::setUp();
$this->user = $this->getEditor();
$this->viewer = $this->getViewer();
$this->restrictionService = $this->app[\BookStack\Services\PermissionService::class];
}
protected function getViewer()
{
$role = \BookStack\Role::getRole('viewer');
$viewer = $this->getNewBlankUser();
$viewer->attachRole($role);;
return $viewer;
$this->permissionService = $this->app[PermissionService::class];
}
/**
@ -31,27 +39,32 @@ class RestrictionsTest extends BrowserKitTest
{
$entity->restricted = true;
$entity->permissions()->delete();
$role = $this->user->roles->first();
$viewerRole = $this->viewer->roles->first();
$permissions = [];
foreach ($actions as $action) {
$entity->permissions()->create([
$permissions[] = [
'role_id' => $role->id,
'action' => strtolower($action)
]);
$entity->permissions()->create([
];
$permissions[] = [
'role_id' => $viewerRole->id,
'action' => strtolower($action)
]);
];
}
$entity->permissions()->createMany($permissions);
$entity->save();
$entity->load('permissions');
$this->restrictionService->buildJointPermissionsForEntity($entity);
$this->permissionService->buildJointPermissionsForEntity($entity);
$entity->load('jointPermissions');
}
public function test_book_view_restriction()
{
$book = \BookStack\Book::first();
$book = Book::first();
$bookPage = $book->pages->first();
$bookChapter = $book->chapters->first();
@ -81,7 +94,7 @@ class RestrictionsTest extends BrowserKitTest
public function test_book_create_restriction()
{
$book = \BookStack\Book::first();
$book = Book::first();
$bookUrl = $book->getUrl();
$this->actingAs($this->viewer)
@ -120,7 +133,7 @@ class RestrictionsTest extends BrowserKitTest
public function test_book_update_restriction()
{
$book = \BookStack\Book::first();
$book = Book::first();
$bookPage = $book->pages->first();
$bookChapter = $book->chapters->first();
@ -150,7 +163,7 @@ class RestrictionsTest extends BrowserKitTest
public function test_book_delete_restriction()
{
$book = \BookStack\Book::first();
$book = Book::first();
$bookPage = $book->pages->first();
$bookChapter = $book->chapters->first();
@ -342,7 +355,7 @@ class RestrictionsTest extends BrowserKitTest
public function test_book_restriction_form()
{
$book = \BookStack\Book::first();
$book = Book::first();
$this->asAdmin()->visit($book->getUrl() . '/permissions')
->see('Book Permissions')
->check('restricted')
@ -430,7 +443,7 @@ class RestrictionsTest extends BrowserKitTest
public function test_book_create_restriction_override()
{
$book = \BookStack\Book::first();
$book = Book::first();
$bookUrl = $book->getUrl();
$this->actingAs($this->viewer)
@ -465,7 +478,7 @@ class RestrictionsTest extends BrowserKitTest
public function test_book_update_restriction_override()
{
$book = \BookStack\Book::first();
$book = Book::first();
$bookPage = $book->pages->first();
$bookChapter = $book->chapters->first();
@ -495,7 +508,7 @@ class RestrictionsTest extends BrowserKitTest
public function test_book_delete_restriction_override()
{
$book = \BookStack\Book::first();
$book = Book::first();
$bookPage = $book->pages->first();
$bookChapter = $book->chapters->first();
@ -525,11 +538,12 @@ class RestrictionsTest extends BrowserKitTest
public function test_page_visible_if_has_permissions_when_book_not_visible()
{
$book = \BookStack\Book::first();
$bookChapter = $book->chapters->first();
$bookPage = $bookChapter->pages->first();
$book = Book::first();
$this->setEntityRestrictions($book, []);
$bookChapter = $book->chapters->first();
$bookPage = $bookChapter->pages->first();
$this->setEntityRestrictions($bookPage, ['view']);
$this->actingAs($this->viewer);

View file

@ -33,7 +33,7 @@ class UserProfileTest extends BrowserKitTest
public function test_profile_page_shows_created_content_counts()
{
$newUser = $this->getEditor();
$newUser = $this->getNewBlankUser();
$this->asAdmin()->visit('/user/' . $newUser->id)
->see($newUser->name)
@ -52,7 +52,7 @@ class UserProfileTest extends BrowserKitTest
public function test_profile_page_shows_recent_activity()
{
$newUser = $this->getEditor();
$newUser = $this->getNewBlankUser();
$this->actingAs($newUser);
$entities = $this->createEntityChainBelongingToUser($newUser, $newUser);
\Activity::add($entities['book'], 'book_update', $entities['book']->id);
@ -66,7 +66,7 @@ class UserProfileTest extends BrowserKitTest
public function test_clicking_user_name_in_activity_leads_to_profile_page()
{
$newUser = $this->getEditor();
$newUser = $this->getNewBlankUser();
$this->actingAs($newUser);
$entities = $this->createEntityChainBelongingToUser($newUser, $newUser);
\Activity::add($entities['book'], 'book_update', $entities['book']->id);