if ($matches) return true;
- if ($entity->isA('chapter') && $this->isA('book')) {
- return $entity->book_id === $this->id;
- }
-
- if ($entity->isA('page') && $this->isA('book')) {
+ if (($entity->isA('chapter') || $entity->isA('page')) && $this->isA('book')) {
return $entity->book_id === $this->id;
}
return $this->morphMany('BookStack\View', 'viewable');
}
- /**
- * Get just the views for the current user.
- * @return mixed
- */
- public function userViews()
- {
- return $this->views()->where('user_id', '=', auth()->user()->id);
- }
-
/**
* Allows checking of the exact class, Used to check entity type.
* Cleaner method for is_a.
return redirect()->back();
}
$searchTerm = $request->get('term');
- $whereTerm = [['book_id', '=', $bookId]];
- $pages = $this->pageRepo->getBySearch($searchTerm, $whereTerm);
- $chapters = $this->chapterRepo->getBySearch($searchTerm, $whereTerm);
+ $searchWhereTerms = [['book_id', '=', $bookId]];
+ $pages = $this->pageRepo->getBySearch($searchTerm, $searchWhereTerms);
+ $chapters = $this->chapterRepo->getBySearch($searchTerm, $searchWhereTerms);
return view('search/book', ['pages' => $pages, 'chapters' => $chapters, 'searchTerm' => $searchTerm]);
}
$this->validate($request, [
'name' => 'required',
'email' => 'required|email|unique:users,email,' . $id,
- 'password' => 'min:5',
- 'password-confirm' => 'same:password',
+ 'password' => 'min:5|required_with:password_confirm',
+ 'password-confirm' => 'same:password|required_with:password',
'role' => 'exists:roles,id'
+ ], [
+ 'password-confirm.required_with' => 'Password confirmation required'
]);
$user = $this->user->findOrFail($id);
$password = $request->get('password');
$user->password = bcrypt($password);
}
+
$user->save();
return redirect('/users');
}
*/
public static function getDefault()
{
- return static::where('name', '=', static::$default)->first();
+ return static::getRole(static::$default);
+ }
+
+ /**
+ * Get the role object for the specified role.
+ * @param $roleName
+ * @return mixed
+ */
+ public static function getRole($roleName)
+ {
+ return static::where('name', '=', $roleName)->first();
}
}
public function run()
{
$user = factory(BookStack\User::class, 1)->create();
- $role = \BookStack\Role::where('name', '=', 'admin')->first();
+ $role = \BookStack\Role::getDefault();
$user->attachRole($role);
<env name="QUEUE_DRIVER" value="sync"/>
<env name="DB_CONNECTION" value="mysql_testing"/>
<env name="MAIL_PRETEND" value="true"/>
- <env name="DISABLE_EXTERNAL_SERVICES" value="true"/>
+ <env name="DISABLE_EXTERNAL_SERVICES" value="false"/>
</php>
</phpunit>
}]);
- ngApp.controller('BookShowController', ['$scope', '$http', '$attrs', function ($scope, $http, $attrs) {
+ ngApp.controller('BookShowController', ['$scope', '$http', '$attrs', '$sce', function ($scope, $http, $attrs, $sce) {
$scope.searching = false;
$scope.searchTerm = '';
$scope.searchResults = '';
var searchUrl = '/search/book/' + $attrs.bookId;
searchUrl += '?term=' + encodeURIComponent(term);
$http.get(searchUrl).then((response) => {
- $scope.searchResults = response.data;
+ $scope.searchResults = $sce.trustAsHtml(response.data);
});
};
<div class="col-md-6"></div>
<div class="col-md-6 faded">
<div class="action-buttons">
- <a href="/users/{{$user->id}}/delete" class="text-neg text-button"><i class="zmdi zmdi-delete"></i>Delete user</a>
+ <a href="/users/{{$user->id}}/delete" class="text-neg text-button"><i class="zmdi zmdi-delete"></i>Delete User</a>
</div>
</div>
</div>
->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => true]);
}
- public function testUserControl()
+ public function testUserCreation()
{
$user = factory(\BookStack\User::class)->make();
- // Test creation
+
$this->asAdmin()
->visit('/users')
->click('Add new user')
->seeInDatabase('users', $user->toArray())
->seePageIs('/users')
->see($user->name);
- $user = $user->where('email', '=', $user->email)->first();
+ }
- // Test editing
+ public function testUserUpdating()
+ {
+ $user = \BookStack\User::all()->last();
+ $password = $user->password;
$this->asAdmin()
->visit('/users')
->click($user->name)
->type('Barry Scott', '#name')
->press('Save')
->seePageIs('/users')
- ->seeInDatabase('users', ['id' => $user->id, 'name' => 'Barry Scott'])
+ ->seeInDatabase('users', ['id' => $user->id, 'name' => 'Barry Scott', 'password' => $password])
->notSeeInDatabase('users', ['name' => $user->name]);
- $user = $user->find($user->id);
+ }
+
+ public function testUserPasswordUpdate()
+ {
+ $user = \BookStack\User::all()->last();
+ $userProfilePage = '/users/' . $user->id;
+ $this->asAdmin()
+ ->visit($userProfilePage)
+ ->type('newpassword', '#password')
+ ->press('Save')
+ ->seePageIs($userProfilePage)
+ ->see('Password confirmation required')
+
+ ->type('newpassword', '#password')
+ ->type('newpassword', '#password-confirm')
+ ->press('Save')
+ ->seePageIs('/users');
+
+ $userPassword = \BookStack\User::find($user->id)->password;
+ $this->assertTrue(Hash::check('newpassword', $userPassword));
+ }
+
+ public function testUserDeletion()
+ {
+ $userDetails = factory(\BookStack\User::class)->make();
+ $user = $this->getNewUser($userDetails->toArray());
- // Test Deletion
$this->asAdmin()
->visit('/users/' . $user->id)
- ->click('Delete user')
+ ->click('Delete User')
->see($user->name)
->press('Confirm')
->seePageIs('/users')
->notSeeInDatabase('users', ['name' => $user->name]);
}
+ public function testUserCannotBeDeletedIfLastAdmin()
+ {
+ $adminRole = \BookStack\Role::getRole('admin');
+ // Ensure we currently only have 1 admin user
+ $this->assertEquals(1, $adminRole->users()->count());
+ $user = $adminRole->users->first();
+
+ $this->asAdmin()->visit('/users/' . $user->id)
+ ->click('Delete User')
+ ->press('Confirm')
+ ->seePageIs('/users/' . $user->id)
+ ->see('You cannot delete the only admin');
+ }
+
public function testLogout()
{
$this->asAdmin()
->seePageIs('/');
}
+ public function testBookSearch()
+ {
+ $book = \BookStack\Book::all()->first();
+ $page = $book->pages->last();
+ $chapter = $book->chapters->last();
+
+ $this->asAdmin()
+ ->visit('/search/book/' . $book->id . '?term=' . urlencode($page->name))
+ ->see($page->name)
+
+ ->visit('/search/book/' . $book->id . '?term=' . urlencode($chapter->name))
+ ->see($chapter->name);
+ }
+
+ public function testEmptyBookSearchRedirectsBack()
+ {
+ $book = \BookStack\Book::all()->first();
+ $this->asAdmin()
+ ->visit('/books')
+ ->visit('/search/book/' . $book->id . '?term=')
+ ->seePageIs('/books');
+ }
+
public function testEntitiesViewableAfterCreatorDeletion()
{