Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Зуев Егор
/
wiki.dev
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
Authored by
Dan Brown
2016-01-02 14:49:05 +0000
Browse Files
Options
Browse Files
Tag
Download
Plain Diff
Commit
4fc75beed4663abd2ca077cc8aa26f36e9b793c9
4fc75bee
2 parents
3b3bc0c4
d3709de0
Merge branch 'master' into release
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
150 additions
and
44 deletions
app/Entity.php
app/Http/Controllers/Controller.php
app/Http/Controllers/SearchController.php
app/Http/Controllers/SettingController.php
app/Http/Controllers/UserController.php
app/Role.php
app/Services/ActivityService.php
database/seeds/DummyContentSeeder.php
phpunit.xml
public/build/.gitignore
readme.md
resources/assets/js/controllers.js
resources/views/base.blade.php
resources/views/errors/404.blade.php
resources/views/users/edit.blade.php
tests/AuthTest.php
tests/EntityTest.php
app/Entity.php
View file @
4fc75be
...
...
@@ -31,11 +31,7 @@ abstract class Entity extends Model
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
;
}
...
...
@@ -65,15 +61,6 @@ abstract class Entity extends Model
}
/**
* 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.
* @param $type
...
...
app/Http/Controllers/Controller.php
View file @
4fc75be
...
...
@@ -43,6 +43,15 @@ abstract class Controller extends BaseController
}
/**
* Stops the application and shows a permission error if
* the application is in demo mode.
*/
protected
function
preventAccessForDemoUsers
()
{
if
(
env
(
'APP_ENV'
,
'production'
)
===
'demo'
)
$this
->
showPermissionError
();
}
/**
* Adds the page title into the view.
* @param $title
*/
...
...
@@ -52,6 +61,18 @@ abstract class Controller extends BaseController
}
/**
* On a permission error redirect to home and display
* the error as a notification.
*/
protected
function
showPermissionError
()
{
Session
::
flash
(
'error'
,
trans
(
'errors.permission'
));
throw
new
HttpResponseException
(
redirect
(
'/'
)
);
}
/**
* Checks for a permission.
*
* @param $permissionName
...
...
@@ -60,15 +81,18 @@ abstract class Controller extends BaseController
protected
function
checkPermission
(
$permissionName
)
{
if
(
!
$this
->
currentUser
||
!
$this
->
currentUser
->
can
(
$permissionName
))
{
Session
::
flash
(
'error'
,
trans
(
'errors.permission'
));
throw
new
HttpResponseException
(
redirect
(
'/'
)
);
$this
->
showPermissionError
();
}
return
true
;
}
/**
* Check if a user has a permission or bypass if the callback is true.
* @param $permissionName
* @param $callback
* @return bool
*/
protected
function
checkPermissionOr
(
$permissionName
,
$callback
)
{
$callbackResult
=
$callback
();
...
...
app/Http/Controllers/SearchController.php
View file @
4fc75be
...
...
@@ -62,9 +62,9 @@ class SearchController extends Controller
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
]);
}
...
...
app/Http/Controllers/SettingController.php
View file @
4fc75be
...
...
@@ -31,13 +31,16 @@ class SettingController extends Controller
*/
public
function
update
(
Request
$request
)
{
$this
->
preventAccessForDemoUsers
();
$this
->
checkPermission
(
'settings-update'
);
// Cycles through posted settings and update them
foreach
(
$request
->
all
()
as
$name
=>
$value
)
{
if
(
strpos
(
$name
,
'setting-'
)
!==
0
)
continue
;
$key
=
str_replace
(
'setting-'
,
''
,
trim
(
$name
));
Setting
::
put
(
$key
,
$value
);
}
session
()
->
flash
(
'success'
,
'Settings Saved'
);
return
redirect
(
'/settings'
);
}
...
...
app/Http/Controllers/UserController.php
View file @
4fc75be
...
...
@@ -108,15 +108,19 @@ class UserController extends Controller
*/
public
function
update
(
Request
$request
,
$id
)
{
$this
->
preventAccessForDemoUsers
();
$this
->
checkPermissionOr
(
'user-update'
,
function
()
use
(
$id
)
{
return
$this
->
currentUser
->
id
==
$id
;
});
$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
);
...
...
@@ -130,6 +134,7 @@ class UserController extends Controller
$password
=
$request
->
get
(
'password'
);
$user
->
password
=
bcrypt
(
$password
);
}
$user
->
save
();
return
redirect
(
'/users'
);
}
...
...
@@ -144,6 +149,7 @@ class UserController extends Controller
$this
->
checkPermissionOr
(
'user-delete'
,
function
()
use
(
$id
)
{
return
$this
->
currentUser
->
id
==
$id
;
});
$user
=
$this
->
user
->
findOrFail
(
$id
);
$this
->
setPageTitle
(
'Delete User '
.
$user
->
name
);
return
view
(
'users/delete'
,
[
'user'
=>
$user
]);
...
...
@@ -156,6 +162,7 @@ class UserController extends Controller
*/
public
function
destroy
(
$id
)
{
$this
->
preventAccessForDemoUsers
();
$this
->
checkPermissionOr
(
'user-delete'
,
function
()
use
(
$id
)
{
return
$this
->
currentUser
->
id
==
$id
;
});
...
...
app/Role.php
View file @
4fc75be
...
...
@@ -43,6 +43,16 @@ class Role extends Model
*/
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
();
}
}
...
...
app/Services/ActivityService.php
View file @
4fc75be
...
...
@@ -107,7 +107,7 @@ class ActivityService
}
/**
* Filters out similar ac
i
tivity.
* Filters out similar activity.
* @param Activity[] $activity
* @return array
*/
...
...
database/seeds/DummyContentSeeder.php
View file @
4fc75be
...
...
@@ -12,7 +12,7 @@ class DummyContentSeeder extends Seeder
public
function
run
()
{
$user
=
factory
(
BookStack\User
::
class
,
1
)
->
create
();
$role
=
\BookStack\Role
::
where
(
'name'
,
'='
,
'admin'
)
->
firs
t
();
$role
=
\BookStack\Role
::
getDefaul
t
();
$user
->
attachRole
(
$role
);
...
...
phpunit.xml
View file @
4fc75be
...
...
@@ -26,6 +26,6 @@
<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=
"
tru
e"
/>
<env
name=
"DISABLE_EXTERNAL_SERVICES"
value=
"
fals
e"
/>
</php>
</phpunit>
...
...
public/build/.gitignore
0 → 100644
View file @
4fc75be
*
!.gitignore
readme.md
View file @
4fc75be
...
...
@@ -82,7 +82,7 @@ BookStack is provided under the MIT License.
These are the great projects used to help build BookStack:
*
[
Laravel
](
http://laravel.com/
)
*
[
VueJS
](
http://vue
js.org/
)
*
[
AngularJS
](
https://angular
js.org/
)
*
[
jQuery
](
https://jquery.com/
)
*
[
TinyMCE
](
https://www.tinymce.com/
)
*
[
highlight.js
](
https://highlightjs.org/
)
...
...
resources/assets/js/controllers.js
View file @
4fc75be
...
...
@@ -127,7 +127,7 @@ module.exports = function (ngApp) {
}]);
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
=
''
;
...
...
@@ -141,7 +141,7 @@ module.exports = function (ngApp) {
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
)
;
});
};
...
...
resources/views/base.blade.php
View file @
4fc75be
...
...
@@ -43,14 +43,14 @@
<div
class=
"float right"
>
<div
class=
"links text-center"
>
<a
href=
"/books"
><i
class=
"zmdi zmdi-book"
></i>
Books
</a>
@if($currentUser->can('settings-update'))
@if(
isset($currentUser)
&&
$currentUser->can('settings-update'))
<a
href=
"/settings"
><i
class=
"zmdi zmdi-settings"
></i>
Settings
</a>
@endif
@if(!$signedIn)
@if(!
isset($signedIn) || !
$signedIn)
<a
href=
"/login"
><i
class=
"zmdi zmdi-sign-in"
></i>
Sign In
</a>
@endif
</div>
@if($signedIn)
@if(
isset($signedIn)
&&
$signedIn)
<div
class=
"dropdown-container"
dropdown
>
<span
class=
"user-name"
dropdown-toggle
>
<img
class=
"avatar"
src=
"{{$currentUser->getAvatar(30)}}"
alt=
"{{ $currentUser->name }}"
>
...
...
resources/views/errors/404.blade.php
View file @
4fc75be
...
...
@@ -4,8 +4,9 @@
<div
class=
"container"
>
<h1>
Page Not Found
</h1>
<p>
The page you were looking for could not be found.
</p>
<h1
class=
"text-muted"
>
Page Not Found
</h1>
<p>
Sorry, The page you were looking for could not be found.
</p>
<a
href=
"/"
class=
"button"
>
Return To Home
</a>
</div>
@stop
\ No newline at end of file
...
...
resources/views/users/edit.blade.php
View file @
4fc75be
...
...
@@ -9,7 +9,7 @@
<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
u
ser
</a>
<a
href=
"/users/{{$user->id}}/delete"
class=
"text-neg text-button"
><i
class=
"zmdi zmdi-delete"
></i>
Delete
U
ser
</a>
</div>
</div>
</div>
...
...
tests/AuthTest.php
View file @
4fc75be
...
...
@@ -102,10 +102,10 @@ class AuthTest extends TestCase
->
seeInDatabase
(
'users'
,
[
'name'
=>
$user
->
name
,
'email'
=>
$user
->
email
,
'email_confirmed'
=>
true
]);
}
public
function
testUserC
ontrol
()
public
function
testUserC
reation
()
{
$user
=
factory
(
\BookStack\User
::
class
)
->
make
();
// Test creation
$this
->
asAdmin
()
->
visit
(
'/users'
)
->
click
(
'Add new user'
)
...
...
@@ -118,9 +118,12 @@ class AuthTest extends TestCase
->
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
)
...
...
@@ -129,20 +132,58 @@ class AuthTest extends TestCase
->
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
u
ser'
)
->
click
(
'Delete
U
ser'
)
->
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
()
...
...
tests/EntityTest.php
View file @
4fc75be
...
...
@@ -180,6 +180,37 @@ class EntityTest extends TestCase
->
seeStatusCode
(
200
);
}
public
function
testEmptySearchRedirectsBack
()
{
$this
->
asAdmin
()
->
visit
(
'/'
)
->
visit
(
'/search/all'
)
->
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
()
{
...
...
Please
register
or
sign in
to post a comment