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-02-27 19:24:42 +0000
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Commit
473261be35ab50e6c9bc5914c899a34cd6cccf57
473261be
1 parent
a54be851
Finished initial implementation of custom role system
Show whitespace changes
Inline
Side-by-side
Showing
37 changed files
with
636 additions
and
205 deletions
app/Entity.php
app/Http/Controllers/BookController.php
app/Http/Controllers/ChapterController.php
app/Http/Controllers/Controller.php
app/Http/Controllers/ImageController.php
app/Http/Controllers/PageController.php
app/Http/Controllers/PermissionController.php
app/Http/Controllers/SettingController.php
app/Http/Controllers/UserController.php
app/Http/routes.php
app/Image.php
app/Ownable.php
app/Permission.php
app/Repos/UserRepo.php
app/Role.php
app/User.php
app/helpers.php
database/migrations/2016_02_27_120329_update_permissions_and_roles.php
resources/views/base.blade.php
resources/views/books/index.blade.php
resources/views/books/show.blade.php
resources/views/chapters/show.blade.php
resources/views/form/role-checkboxes.blade.php
resources/views/pages/show.blade.php
resources/views/settings/index.blade.php
resources/views/settings/roles/checkbox.blade.php
resources/views/settings/roles/create.blade.php
resources/views/settings/roles/delete.blade.php
resources/views/settings/roles/edit.blade.php
resources/views/settings/roles/form.blade.php
resources/views/settings/roles/index.blade.php
resources/views/users/forms/ldap.blade.php
resources/views/users/forms/standard.blade.php
resources/views/users/index.blade.php
tests/Auth/AuthTest.php
tests/RolesTest.php
tests/TestCase.php
app/Entity.php
View file @
473261b
<?php
<?php
namespace
BookStack
;
namespace
BookStack
;
use
Illuminate\Database\Eloquent\Model
;
abstract
class
Entity
extends
Model
abstract
class
Entity
extends
Ownable
{
use
Ownable
;
/**
* Compares this entity to another given entity.
* Matches by comparing class and id.
...
...
@@ -72,16 +67,7 @@ abstract class Entity extends Model
}
/**
* Gets the class name.
* @return string
*/
public
static
function
getClassName
()
{
return
strtolower
(
array_slice
(
explode
(
'\\'
,
static
::
class
),
-
1
,
1
)[
0
]);
}
/**
*Gets a limited-length version of the entities name.
* Gets a limited-length version of the entities name.
* @param int $length
* @return string
*/
...
...
app/Http/Controllers/BookController.php
View file @
473261b
...
...
@@ -55,7 +55,7 @@ class BookController extends Controller
*/
public
function
create
()
{
$this
->
checkPermission
(
'book-create'
);
$this
->
checkPermission
(
'book-create
-all
'
);
$this
->
setPageTitle
(
'Create New Book'
);
return
view
(
'books/create'
);
}
...
...
@@ -68,7 +68,7 @@ class BookController extends Controller
*/
public
function
store
(
Request
$request
)
{
$this
->
checkPermission
(
'book-create'
);
$this
->
checkPermission
(
'book-create
-all
'
);
$this
->
validate
(
$request
,
[
'name'
=>
'required|string|max:255'
,
'description'
=>
'string|max:1000'
...
...
@@ -105,8 +105,8 @@ class BookController extends Controller
*/
public
function
edit
(
$slug
)
{
$this
->
checkPermission
(
'book-update'
);
$book
=
$this
->
bookRepo
->
getBySlug
(
$slug
);
$this
->
checkOwnablePermission
(
'book-update'
,
$book
);
$this
->
setPageTitle
(
'Edit Book '
.
$book
->
getShortName
());
return
view
(
'books/edit'
,
[
'book'
=>
$book
,
'current'
=>
$book
]);
}
...
...
@@ -120,8 +120,8 @@ class BookController extends Controller
*/
public
function
update
(
Request
$request
,
$slug
)
{
$this
->
checkPermission
(
'book-update'
);
$book
=
$this
->
bookRepo
->
getBySlug
(
$slug
);
$this
->
checkOwnablePermission
(
'book-update'
,
$book
);
$this
->
validate
(
$request
,
[
'name'
=>
'required|string|max:255'
,
'description'
=>
'string|max:1000'
...
...
@@ -141,8 +141,8 @@ class BookController extends Controller
*/
public
function
showDelete
(
$bookSlug
)
{
$this
->
checkPermission
(
'book-delete'
);
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$this
->
checkOwnablePermission
(
'book-delete'
,
$book
);
$this
->
setPageTitle
(
'Delete Book '
.
$book
->
getShortName
());
return
view
(
'books/delete'
,
[
'book'
=>
$book
,
'current'
=>
$book
]);
}
...
...
@@ -154,8 +154,8 @@ class BookController extends Controller
*/
public
function
sort
(
$bookSlug
)
{
$this
->
checkPermission
(
'book-update'
);
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$this
->
checkOwnablePermission
(
'book-update'
,
$book
);
$bookChildren
=
$this
->
bookRepo
->
getChildren
(
$book
);
$books
=
$this
->
bookRepo
->
getAll
(
false
);
$this
->
setPageTitle
(
'Sort Book '
.
$book
->
getShortName
());
...
...
@@ -184,8 +184,8 @@ class BookController extends Controller
*/
public
function
saveSort
(
$bookSlug
,
Request
$request
)
{
$this
->
checkPermission
(
'book-update'
);
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$this
->
checkOwnablePermission
(
'book-update'
,
$book
);
// Return if no map sent
if
(
!
$request
->
has
(
'sort-tree'
))
{
...
...
@@ -229,8 +229,8 @@ class BookController extends Controller
*/
public
function
destroy
(
$bookSlug
)
{
$this
->
checkPermission
(
'book-delete'
);
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$this
->
checkOwnablePermission
(
'book-delete'
,
$book
);
Activity
::
addMessage
(
'book_delete'
,
0
,
$book
->
name
);
Activity
::
removeEntity
(
$book
);
$this
->
bookRepo
->
destroyBySlug
(
$bookSlug
);
...
...
app/Http/Controllers/ChapterController.php
View file @
473261b
<?php
namespace
BookStack\Http\Controllers
;
<?php
namespace
BookStack\Http\Controllers
;
use
Activity
;
use
Illuminate\Http\Request
;
use
Illuminate\Support\Facades\Auth
;
use
BookStack\Http\Requests
;
use
BookStack\Http\Controllers\Controller
;
use
BookStack\Repos\BookRepo
;
use
BookStack\Repos\ChapterRepo
;
use
Views
;
...
...
@@ -30,7 +25,6 @@ class ChapterController extends Controller
parent
::
__construct
();
}
/**
* Show the form for creating a new chapter.
* @param $bookSlug
...
...
@@ -38,8 +32,8 @@ class ChapterController extends Controller
*/
public
function
create
(
$bookSlug
)
{
$this
->
checkPermission
(
'chapter-create'
);
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$this
->
checkOwnablePermission
(
'chapter-create'
,
$book
);
$this
->
setPageTitle
(
'Create New Chapter'
);
return
view
(
'chapters/create'
,
[
'book'
=>
$book
,
'current'
=>
$book
]);
}
...
...
@@ -52,12 +46,13 @@ class ChapterController extends Controller
*/
public
function
store
(
$bookSlug
,
Request
$request
)
{
$this
->
checkPermission
(
'chapter-create'
);
$this
->
validate
(
$request
,
[
'name'
=>
'required|string|max:255'
]);
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$this
->
checkOwnablePermission
(
'chapter-create'
,
$book
);
$chapter
=
$this
->
chapterRepo
->
newFromInput
(
$request
->
all
());
$chapter
->
slug
=
$this
->
chapterRepo
->
findSuitableSlug
(
$chapter
->
name
,
$book
->
id
);
$chapter
->
priority
=
$this
->
bookRepo
->
getNewPriority
(
$book
);
...
...
@@ -92,9 +87,9 @@ class ChapterController extends Controller
*/
public
function
edit
(
$bookSlug
,
$chapterSlug
)
{
$this
->
checkPermission
(
'chapter-update'
);
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$chapter
=
$this
->
chapterRepo
->
getBySlug
(
$chapterSlug
,
$book
->
id
);
$this
->
checkOwnablePermission
(
'chapter-update'
,
$chapter
);
$this
->
setPageTitle
(
'Edit Chapter'
.
$chapter
->
getShortName
());
return
view
(
'chapters/edit'
,
[
'book'
=>
$book
,
'chapter'
=>
$chapter
,
'current'
=>
$chapter
]);
}
...
...
@@ -108,9 +103,9 @@ class ChapterController extends Controller
*/
public
function
update
(
Request
$request
,
$bookSlug
,
$chapterSlug
)
{
$this
->
checkPermission
(
'chapter-update'
);
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$chapter
=
$this
->
chapterRepo
->
getBySlug
(
$chapterSlug
,
$book
->
id
);
$this
->
checkOwnablePermission
(
'chapter-update'
,
$chapter
);
$chapter
->
fill
(
$request
->
all
());
$chapter
->
slug
=
$this
->
chapterRepo
->
findSuitableSlug
(
$chapter
->
name
,
$book
->
id
,
$chapter
->
id
);
$chapter
->
updated_by
=
auth
()
->
user
()
->
id
;
...
...
@@ -127,9 +122,9 @@ class ChapterController extends Controller
*/
public
function
showDelete
(
$bookSlug
,
$chapterSlug
)
{
$this
->
checkPermission
(
'chapter-delete'
);
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$chapter
=
$this
->
chapterRepo
->
getBySlug
(
$chapterSlug
,
$book
->
id
);
$this
->
checkOwnablePermission
(
'chapter-delete'
,
$chapter
);
$this
->
setPageTitle
(
'Delete Chapter'
.
$chapter
->
getShortName
());
return
view
(
'chapters/delete'
,
[
'book'
=>
$book
,
'chapter'
=>
$chapter
,
'current'
=>
$chapter
]);
}
...
...
@@ -142,9 +137,9 @@ class ChapterController extends Controller
*/
public
function
destroy
(
$bookSlug
,
$chapterSlug
)
{
$this
->
checkPermission
(
'chapter-delete'
);
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$chapter
=
$this
->
chapterRepo
->
getBySlug
(
$chapterSlug
,
$book
->
id
);
$this
->
checkOwnablePermission
(
'chapter-delete'
,
$chapter
);
Activity
::
addMessage
(
'chapter_delete'
,
$book
->
id
,
$chapter
->
name
);
$this
->
chapterRepo
->
destroy
(
$chapter
);
return
redirect
(
$book
->
getUrl
());
...
...
app/Http/Controllers/Controller.php
View file @
473261b
...
...
@@ -2,6 +2,7 @@
namespace
BookStack\Http\Controllers
;
use
BookStack\Ownable
;
use
HttpRequestException
;
use
Illuminate\Foundation\Bus\DispatchesJobs
;
use
Illuminate\Http\Exception\HttpResponseException
;
...
...
@@ -61,7 +62,7 @@ abstract class Controller extends BaseController
}
/**
* On a permission error redirect to home and display
* On a permission error redirect to home and display
.
* the error as a notification.
*/
protected
function
showPermissionError
()
...
...
@@ -74,21 +75,32 @@ abstract class Controller extends BaseController
/**
* Checks for a permission.
*
* @param $permissionName
* @param string $permissionName
* @return bool|\Illuminate\Http\RedirectResponse
*/
protected
function
checkPermission
(
$permissionName
)
{
if
(
!
$this
->
currentUser
||
!
$this
->
currentUser
->
can
(
$permissionName
))
{
dd
(
$this
->
currentUser
);
$this
->
showPermissionError
();
}
return
true
;
}
/**
* Check the current user's permissions against an ownable item.
* @param $permission
* @param Ownable $ownable
* @return bool
*/
protected
function
checkOwnablePermission
(
$permission
,
Ownable
$ownable
)
{
$permissionBaseName
=
strtolower
(
$permission
)
.
'-'
;
if
(
userCan
(
$permissionBaseName
.
'all'
))
return
true
;
if
(
userCan
(
$permissionBaseName
.
'own'
)
&&
$ownable
->
createdBy
->
id
===
$this
->
currentUser
->
id
)
return
true
;
$this
->
showPermissionError
();
}
/**
* Check if a user has a permission or bypass if the callback is true.
* @param $permissionName
* @param $callback
...
...
app/Http/Controllers/ImageController.php
View file @
473261b
...
...
@@ -64,7 +64,7 @@ class ImageController extends Controller
*/
public
function
uploadByType
(
$type
,
Request
$request
)
{
$this
->
checkPermission
(
'image-create'
);
$this
->
checkPermission
(
'image-create
-all
'
);
$this
->
validate
(
$request
,
[
'file'
=>
'image|mimes:jpeg,gif,png'
]);
...
...
@@ -90,7 +90,7 @@ class ImageController extends Controller
*/
public
function
getThumbnail
(
$id
,
$width
,
$height
,
$crop
)
{
$this
->
checkPermission
(
'image-create'
);
$this
->
checkPermission
(
'image-create
-all
'
);
$image
=
$this
->
imageRepo
->
getById
(
$id
);
$thumbnailUrl
=
$this
->
imageRepo
->
getThumbnail
(
$image
,
$width
,
$height
,
$crop
==
'false'
);
return
response
()
->
json
([
'url'
=>
$thumbnailUrl
]);
...
...
@@ -104,11 +104,11 @@ class ImageController extends Controller
*/
public
function
update
(
$imageId
,
Request
$request
)
{
$this
->
checkPermission
(
'image-update'
);
$this
->
validate
(
$request
,
[
'name'
=>
'required|min:2|string'
]);
$image
=
$this
->
imageRepo
->
getById
(
$imageId
);
$this
->
checkOwnablePermission
(
'image-update'
,
$image
);
$image
=
$this
->
imageRepo
->
updateImageDetails
(
$image
,
$request
->
all
());
return
response
()
->
json
(
$image
);
}
...
...
@@ -123,8 +123,8 @@ class ImageController extends Controller
*/
public
function
destroy
(
PageRepo
$pageRepo
,
Request
$request
,
$id
)
{
$this
->
checkPermission
(
'image-delete'
);
$image
=
$this
->
imageRepo
->
getById
(
$id
);
$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
);
...
...
app/Http/Controllers/PageController.php
View file @
473261b
<?php
namespace
BookStack\Http\Controllers
;
<?php
namespace
BookStack\Http\Controllers
;
use
Activity
;
use
BookStack\Services\ExportService
;
use
Illuminate\Http\Request
;
use
Illuminate\Support\Facades\Auth
;
use
BookStack\Http\Requests
;
use
BookStack\Repos\BookRepo
;
use
BookStack\Repos\ChapterRepo
;
...
...
@@ -40,7 +36,6 @@ class PageController extends Controller
/**
* Show the form for creating a new page.
*
* @param $bookSlug
* @param bool $chapterSlug
* @return Response
...
...
@@ -48,23 +43,22 @@ class PageController extends Controller
*/
public
function
create
(
$bookSlug
,
$chapterSlug
=
false
)
{
$this
->
checkPermission
(
'page-create'
);
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$chapter
=
$chapterSlug
?
$this
->
chapterRepo
->
getBySlug
(
$chapterSlug
,
$book
->
id
)
:
false
;
$parent
=
$chapter
?
$chapter
:
$book
;
$this
->
checkOwnablePermission
(
'page-create'
,
$parent
);
$this
->
setPageTitle
(
'Create New Page'
);
return
view
(
'pages/create'
,
[
'book'
=>
$book
,
'chapter'
=>
$chapter
]);
}
/**
* Store a newly created page in storage.
*
* @param Request $request
* @param $bookSlug
* @return Response
*/
public
function
store
(
Request
$request
,
$bookSlug
)
{
$this
->
checkPermission
(
'page-create'
);
$this
->
validate
(
$request
,
[
'name'
=>
'required|string|max:255'
]);
...
...
@@ -72,6 +66,8 @@ class PageController extends Controller
$input
=
$request
->
all
();
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$chapterId
=
(
$request
->
has
(
'chapter'
)
&&
$this
->
chapterRepo
->
idExists
(
$request
->
get
(
'chapter'
)))
?
$request
->
get
(
'chapter'
)
:
null
;
$parent
=
$chapterId
!==
null
?
$this
->
chapterRepo
->
getById
(
$chapterId
)
:
$book
;
$this
->
checkOwnablePermission
(
'page-create'
,
$parent
);
$input
[
'priority'
]
=
$this
->
bookRepo
->
getNewPriority
(
$book
);
$page
=
$this
->
pageRepo
->
saveNew
(
$input
,
$book
,
$chapterId
);
...
...
@@ -84,7 +80,6 @@ class PageController extends Controller
* Display the specified page.
* If the page is not found via the slug the
* revisions are searched for a match.
*
* @param $bookSlug
* @param $pageSlug
* @return Response
...
...
@@ -109,23 +104,21 @@ class PageController extends Controller
/**
* Show the form for editing the specified page.
*
* @param $bookSlug
* @param $pageSlug
* @return Response
*/
public
function
edit
(
$bookSlug
,
$pageSlug
)
{
$this
->
checkPermission
(
'page-update'
);
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$page
=
$this
->
pageRepo
->
getBySlug
(
$pageSlug
,
$book
->
id
);
$this
->
checkOwnablePermission
(
'page-update'
,
$page
);
$this
->
setPageTitle
(
'Editing Page '
.
$page
->
getShortName
());
return
view
(
'pages/edit'
,
[
'page'
=>
$page
,
'book'
=>
$book
,
'current'
=>
$page
]);
}
/**
* Update the specified page in storage.
*
* @param Request $request
* @param $bookSlug
* @param $pageSlug
...
...
@@ -133,12 +126,12 @@ class PageController extends Controller
*/
public
function
update
(
Request
$request
,
$bookSlug
,
$pageSlug
)
{
$this
->
checkPermission
(
'page-update'
);
$this
->
validate
(
$request
,
[
'name'
=>
'required|string|max:255'
]);
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$page
=
$this
->
pageRepo
->
getBySlug
(
$pageSlug
,
$book
->
id
);
$this
->
checkOwnablePermission
(
'page-update'
,
$page
);
$this
->
pageRepo
->
updatePage
(
$page
,
$book
->
id
,
$request
->
all
());
Activity
::
add
(
$page
,
'page_update'
,
$book
->
id
);
return
redirect
(
$page
->
getUrl
());
...
...
@@ -164,9 +157,9 @@ class PageController extends Controller
*/
public
function
showDelete
(
$bookSlug
,
$pageSlug
)
{
$this
->
checkPermission
(
'page-delete'
);
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$page
=
$this
->
pageRepo
->
getBySlug
(
$pageSlug
,
$book
->
id
);
$this
->
checkOwnablePermission
(
'page-delete'
,
$page
);
$this
->
setPageTitle
(
'Delete Page '
.
$page
->
getShortName
());
return
view
(
'pages/delete'
,
[
'book'
=>
$book
,
'page'
=>
$page
,
'current'
=>
$page
]);
}
...
...
@@ -181,9 +174,9 @@ class PageController extends Controller
*/
public
function
destroy
(
$bookSlug
,
$pageSlug
)
{
$this
->
checkPermission
(
'page-delete'
);
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$page
=
$this
->
pageRepo
->
getBySlug
(
$pageSlug
,
$book
->
id
);
$this
->
checkOwnablePermission
(
'page-delete'
,
$page
);
Activity
::
addMessage
(
'page_delete'
,
$book
->
id
,
$page
->
name
);
$this
->
pageRepo
->
destroy
(
$page
);
return
redirect
(
$book
->
getUrl
());
...
...
@@ -229,9 +222,9 @@ class PageController extends Controller
*/
public
function
restoreRevision
(
$bookSlug
,
$pageSlug
,
$revisionId
)
{
$this
->
checkPermission
(
'page-update'
);
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$page
=
$this
->
pageRepo
->
getBySlug
(
$pageSlug
,
$book
->
id
);
$this
->
checkOwnablePermission
(
'page-update'
,
$page
);
$page
=
$this
->
pageRepo
->
restoreRevision
(
$page
,
$book
,
$revisionId
);
Activity
::
add
(
$page
,
'page_restore'
,
$book
->
id
);
return
redirect
(
$page
->
getUrl
());
...
...
app/Http/Controllers/PermissionController.php
View file @
473261b
...
...
@@ -2,26 +2,27 @@
namespace
BookStack\Http\Controllers
;
use
BookStack\Permission
;
use
BookStack\Role
;
use
BookStack\User
;
use
Illuminate\Http\Request
;
use
BookStack\Http\Requests
;
use
BookStack\Http\Controllers\Controller
;
class
PermissionController
extends
Controller
{
protected
$role
;
protected
$permission
;
/**
* PermissionController constructor.
* @param $role
* @param $user
* @param Role $role
* @param Permission $permission
* @internal param $user
*/
public
function
__construct
(
Role
$role
)
public
function
__construct
(
Role
$role
,
Permission
$permission
)
{
$this
->
role
=
$role
;
$this
->
permission
=
$permission
;
parent
::
__construct
();
}
...
...
@@ -30,20 +31,152 @@ class PermissionController extends Controller
*/
public
function
listRoles
()
{
$this
->
checkPermission
(
'
settings-updat
e'
);
$this
->
checkPermission
(
'
user-roles-manag
e'
);
$roles
=
$this
->
role
->
all
();
return
view
(
'settings/roles/index'
,
[
'roles'
=>
$roles
]);
}
/**
* Show the form to create a new role
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public
function
createRole
()
{
$this
->
checkPermission
(
'user-roles-manage'
);
return
view
(
'settings/roles/create'
);
}
/**
* Store a new role in the system.
* @param Request $request
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public
function
storeRole
(
Request
$request
)
{
$this
->
checkPermission
(
'user-roles-manage'
);
$this
->
validate
(
$request
,
[
'display_name'
=>
'required|min:3|max:200'
,
'description'
=>
'max:250'
]);
$role
=
$this
->
role
->
newInstance
(
$request
->
all
());
$role
->
name
=
str_replace
(
' '
,
'-'
,
strtolower
(
$request
->
get
(
'display_name'
)));
// Prevent duplicate names
while
(
$this
->
role
->
where
(
'name'
,
'='
,
$role
->
name
)
->
count
()
>
0
)
{
$role
->
name
.=
strtolower
(
str_random
(
2
));
}
$role
->
save
();
if
(
$request
->
has
(
'permissions'
))
{
$permissionsNames
=
array_keys
(
$request
->
get
(
'permissions'
));
$permissions
=
$this
->
permission
->
whereIn
(
'name'
,
$permissionsNames
)
->
pluck
(
'id'
)
->
toArray
();
$role
->
permissions
()
->
sync
(
$permissions
);
}
else
{
$role
->
permissions
()
->
sync
([]);
}
session
()
->
flash
(
'success'
,
'Role successfully created'
);
return
redirect
(
'/settings/roles'
);
}
/**
* Show the form for editing a user role.
* @param $id
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public
function
editRole
(
$id
)
{
$this
->
checkPermission
(
'
settings-updat
e'
);
$this
->
checkPermission
(
'
user-roles-manag
e'
);
$role
=
$this
->
role
->
findOrFail
(
$id
);
return
view
(
'settings/roles/edit'
,
[
'role'
=>
$role
]);
}
/**
* Updates a user role.
* @param $id
* @param Request $request
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public
function
updateRole
(
$id
,
Request
$request
)
{
$this
->
checkPermission
(
'user-roles-manage'
);
$this
->
validate
(
$request
,
[
'display_name'
=>
'required|min:3|max:200'
,
'description'
=>
'max:250'
]);
$role
=
$this
->
role
->
findOrFail
(
$id
);
if
(
$request
->
has
(
'permissions'
))
{
$permissionsNames
=
array_keys
(
$request
->
get
(
'permissions'
));
$permissions
=
$this
->
permission
->
whereIn
(
'name'
,
$permissionsNames
)
->
pluck
(
'id'
)
->
toArray
();
$role
->
permissions
()
->
sync
(
$permissions
);
}
else
{
$role
->
permissions
()
->
sync
([]);
}
// Ensure admin account always has all permissions
if
(
$role
->
name
===
'admin'
)
{
$permissions
=
$this
->
permission
->
all
()
->
pluck
(
'id'
)
->
toArray
();
$role
->
permissions
()
->
sync
(
$permissions
);
}
$role
->
fill
(
$request
->
all
());
$role
->
save
();
session
()
->
flash
(
'success'
,
'Role successfully updated'
);
return
redirect
(
'/settings/roles'
);
}
/**
* Show the view to delete a role.
* Offers the chance to migrate users.
* @param $id
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public
function
showDeleteRole
(
$id
)
{
$this
->
checkPermission
(
'user-roles-manage'
);
$role
=
$this
->
role
->
findOrFail
(
$id
);
$roles
=
$this
->
role
->
where
(
'id'
,
'!='
,
$id
)
->
get
();
$blankRole
=
$this
->
role
->
newInstance
([
'display_name'
=>
'Don\'t migrate users'
]);
$roles
->
prepend
(
$blankRole
);
return
view
(
'settings/roles/delete'
,
[
'role'
=>
$role
,
'roles'
=>
$roles
]);
}
/**
* Delete a role from the system,
* Migrate from a previous role if set.
* @param $id
* @param Request $request
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public
function
deleteRole
(
$id
,
Request
$request
)
{
$this
->
checkPermission
(
'user-roles-manage'
);
$role
=
$this
->
role
->
findOrFail
(
$id
);
// Prevent deleting admin role
if
(
$role
->
name
===
'admin'
)
{
session
()
->
flash
(
'error'
,
'The admin role cannot be deleted'
);
return
redirect
()
->
back
();
}
if
(
$role
->
id
==
\Setting
::
get
(
'registration-role'
))
{
session
()
->
flash
(
'error'
,
'This role cannot be deleted while set as the default registration role.'
);
return
redirect
()
->
back
();
}
if
(
$request
->
has
(
'migration_role_id'
))
{
$newRole
=
$this
->
role
->
find
(
$request
->
get
(
'migration_role_id'
));
if
(
$newRole
)
{
$users
=
$role
->
users
->
pluck
(
'id'
)
->
toArray
();
$newRole
->
users
()
->
sync
(
$users
);
}
}
$role
->
delete
();
session
()
->
flash
(
'success'
,
'Role successfully deleted'
);
return
redirect
(
'/settings/roles'
);
}
}
...
...
app/Http/Controllers/SettingController.php
View file @
473261b
...
...
@@ -17,7 +17,7 @@ class SettingController extends Controller
*/
public
function
index
()
{
$this
->
checkPermission
(
'settings-
updat
e'
);
$this
->
checkPermission
(
'settings-
manag
e'
);
$this
->
setPageTitle
(
'Settings'
);
return
view
(
'settings/index'
);
}
...
...
@@ -32,7 +32,7 @@ class SettingController extends Controller
public
function
update
(
Request
$request
)
{
$this
->
preventAccessForDemoUsers
();
$this
->
checkPermission
(
'settings-
updat
e'
);
$this
->
checkPermission
(
'settings-
manag
e'
);
// Cycles through posted settings and update them
foreach
(
$request
->
all
()
as
$name
=>
$value
)
{
...
...
app/Http/Controllers/UserController.php
View file @
473261b
...
...
@@ -35,7 +35,7 @@ class UserController extends Controller
*/
public
function
index
()
{
$users
=
$this
->
user
->
all
();
$users
=
$this
->
user
Repo
->
getAllUsers
();
$this
->
setPageTitle
(
'Users'
);
return
view
(
'users/index'
,
[
'users'
=>
$users
]);
}
...
...
@@ -46,7 +46,7 @@ class UserController extends Controller
*/
public
function
create
()
{
$this
->
checkPermission
(
'user
-creat
e'
);
$this
->
checkPermission
(
'user
s-manag
e'
);
$authMethod
=
config
(
'auth.method'
);
return
view
(
'users/create'
,
[
'authMethod'
=>
$authMethod
]);
}
...
...
@@ -58,11 +58,10 @@ class UserController extends Controller
*/
public
function
store
(
Request
$request
)
{
$this
->
checkPermission
(
'user
-creat
e'
);
$this
->
checkPermission
(
'user
s-manag
e'
);
$validationRules
=
[
'name'
=>
'required'
,
'email'
=>
'required|email|unique:users,email'
,
'role'
=>
'required|exists:roles,id'
'email'
=>
'required|email|unique:users,email'
];
$authMethod
=
config
(
'auth.method'
);
...
...
@@ -84,7 +83,11 @@ class UserController extends Controller
}
$user
->
save
();
$user
->
attachRoleId
(
$request
->
get
(
'role'
));
if
(
$request
->
has
(
'roles'
))
{
$roles
=
$request
->
get
(
'roles'
);
$user
->
roles
()
->
sync
(
$roles
);
}
// Get avatar from gravatar and save
if
(
!
config
(
'services.disable_services'
))
{
...
...
@@ -104,7 +107,7 @@ class UserController extends Controller
*/
public
function
edit
(
$id
,
SocialAuthService
$socialAuthService
)
{
$this
->
checkPermissionOr
(
'user
-updat
e'
,
function
()
use
(
$id
)
{
$this
->
checkPermissionOr
(
'user
s-manag
e'
,
function
()
use
(
$id
)
{
return
$this
->
currentUser
->
id
==
$id
;
});
...
...
@@ -125,7 +128,7 @@ class UserController extends Controller
public
function
update
(
Request
$request
,
$id
)
{
$this
->
preventAccessForDemoUsers
();
$this
->
checkPermissionOr
(
'user
-updat
e'
,
function
()
use
(
$id
)
{
$this
->
checkPermissionOr
(
'user
s-manag
e'
,
function
()
use
(
$id
)
{
return
$this
->
currentUser
->
id
==
$id
;
});
...
...
@@ -133,8 +136,7 @@ class UserController extends Controller
'name'
=>
'min:2'
,
'email'
=>
'min:2|email|unique:users,email,'
.
$id
,
'password'
=>
'min:5|required_with:password_confirm'
,
'password-confirm'
=>
'same:password|required_with:password'
,
'role'
=>
'exists:roles,id'
'password-confirm'
=>
'same:password|required_with:password'
],
[
'password-confirm.required_with'
=>
'Password confirmation required'
]);
...
...
@@ -143,8 +145,9 @@ class UserController extends Controller
$user
->
fill
(
$request
->
all
());
// Role updates
if
(
$this
->
currentUser
->
can
(
'user-update'
)
&&
$request
->
has
(
'role'
))
{
$user
->
attachRoleId
(
$request
->
get
(
'role'
));
if
(
userCan
(
'users-manage'
)
&&
$request
->
has
(
'roles'
))
{
$roles
=
$request
->
get
(
'roles'
);
$user
->
roles
()
->
sync
(
$roles
);
}
// Password updates
...
...
@@ -154,11 +157,12 @@ class UserController extends Controller
}
// External auth id updates
if
(
$this
->
currentUser
->
can
(
'user
-updat
e'
)
&&
$request
->
has
(
'external_auth_id'
))
{
if
(
$this
->
currentUser
->
can
(
'user
s-manag
e'
)
&&
$request
->
has
(
'external_auth_id'
))
{
$user
->
external_auth_id
=
$request
->
get
(
'external_auth_id'
);
}
$user
->
save
();
session
()
->
flash
(
'success'
,
'User successfully updated'
);
return
redirect
(
'/settings/users'
);
}
...
...
@@ -169,7 +173,7 @@ class UserController extends Controller
*/
public
function
delete
(
$id
)
{
$this
->
checkPermissionOr
(
'user
-delet
e'
,
function
()
use
(
$id
)
{
$this
->
checkPermissionOr
(
'user
s-manag
e'
,
function
()
use
(
$id
)
{
return
$this
->
currentUser
->
id
==
$id
;
});
...
...
@@ -186,7 +190,7 @@ class UserController extends Controller
public
function
destroy
(
$id
)
{
$this
->
preventAccessForDemoUsers
();
$this
->
checkPermissionOr
(
'user
-delet
e'
,
function
()
use
(
$id
)
{
$this
->
checkPermissionOr
(
'user
s-manag
e'
,
function
()
use
(
$id
)
{
return
$this
->
currentUser
->
id
==
$id
;
});
...
...
app/Http/routes.php
View file @
473261b
...
...
@@ -99,7 +99,12 @@ Route::group(['middleware' => 'auth'], function () {
// Roles
Route
::
get
(
'/roles'
,
'PermissionController@listRoles'
);
Route
::
get
(
'/roles/new'
,
'PermissionController@createRole'
);
Route
::
post
(
'/roles/new'
,
'PermissionController@storeRole'
);
Route
::
get
(
'/roles/delete/{id}'
,
'PermissionController@showDeleteRole'
);
Route
::
delete
(
'/roles/delete/{id}'
,
'PermissionController@deleteRole'
);
Route
::
get
(
'/roles/{id}'
,
'PermissionController@editRole'
);
Route
::
put
(
'/roles/{id}'
,
'PermissionController@updateRole'
);
});
});
...
...
app/Image.php
View file @
473261b
<?php
<?php
namespace
BookStack
;
namespace
BookStack
;
use
Illuminate\Database\Eloquent\Model
;
use
Images
;
class
Image
extends
Model
class
Image
extends
Ownable
{
use
Ownable
;
protected
$fillable
=
[
'name'
];
...
...
app/Ownable.php
View file @
473261b
<?php
namespace
BookStack
;
use
Illuminate\Database\Eloquent\Model
;
trait
Ownable
abstract
class
Ownable
extends
Model
{
/**
* Relation for the user that created this entity.
...
...
@@ -20,4 +21,14 @@ trait Ownable
{
return
$this
->
belongsTo
(
'BookStack\User'
,
'updated_by'
);
}
/**
* Gets the class name.
* @return string
*/
public
static
function
getClassName
()
{
return
strtolower
(
array_slice
(
explode
(
'\\'
,
static
::
class
),
-
1
,
1
)[
0
]);
}
}
\ No newline at end of file
...
...
app/Permission.php
View file @
473261b
...
...
@@ -13,4 +13,14 @@ class Permission extends Model
{
return
$this
->
belongsToMany
(
'BookStack\Permissions'
);
}
/**
* Get the permission object by name.
* @param $roleName
* @return mixed
*/
public
static
function
getByName
(
$name
)
{
return
static
::
where
(
'name'
,
'='
,
$name
)
->
first
();
}
}
...
...
app/Repos/UserRepo.php
View file @
473261b
...
...
@@ -43,6 +43,15 @@ class UserRepo
}
/**
* Get all the users with their permissions.
* @return \Illuminate\Database\Eloquent\Builder|static
*/
public
function
getAllUsers
()
{
return
$this
->
user
->
with
(
'roles'
,
'avatar'
)
->
orderBy
(
'name'
,
'asc'
)
->
get
();
}
/**
* Creates a new user and attaches a role to them.
* @param array $data
* @return User
...
...
@@ -69,7 +78,7 @@ class UserRepo
public
function
attachDefaultRole
(
$user
)
{
$roleId
=
Setting
::
get
(
'registration-role'
);
if
(
$roleId
===
false
)
$roleId
=
$this
->
role
->
getDefaul
t
()
->
id
;
if
(
$roleId
===
false
)
$roleId
=
$this
->
role
->
firs
t
()
->
id
;
$user
->
attachRoleId
(
$roleId
);
}
...
...
@@ -80,15 +89,10 @@ class UserRepo
*/
public
function
isOnlyAdmin
(
User
$user
)
{
if
(
$user
->
role
->
name
!=
'admin'
)
{
return
false
;
}
$adminRole
=
$this
->
role
->
where
(
'name'
,
'='
,
'admin'
)
->
first
();
if
(
count
(
$adminRole
->
users
)
>
1
)
{
return
false
;
}
if
(
!
$user
->
roles
->
pluck
(
'name'
)
->
contains
(
'admin'
))
return
false
;
$adminRole
=
$this
->
role
->
getRole
(
'admin'
);
if
(
$adminRole
->
users
->
count
()
>
1
)
return
false
;
return
true
;
}
...
...
app/Role.php
View file @
473261b
...
...
@@ -6,6 +6,8 @@ use Illuminate\Database\Eloquent\Model;
class
Role
extends
Model
{
protected
$fillable
=
[
'display_name'
,
'description'
];
/**
* Sets the default role name for newly registered users.
* @var string
...
...
@@ -29,6 +31,15 @@ class Role extends Model
}
/**
* Check if this role has a permission.
* @param $permission
*/
public
function
hasPermission
(
$permission
)
{
return
$this
->
permissions
->
pluck
(
'name'
)
->
contains
(
$permission
);
}
/**
* Add a permission to this role.
* @param Permission $permission
*/
...
...
app/User.php
View file @
473261b
...
...
@@ -14,21 +14,18 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
/**
* The database table used by the model.
*
* @var string
*/
protected
$table
=
'users'
;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected
$fillable
=
[
'name'
,
'email'
,
'image_id'
];
/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
protected
$hidden
=
[
'password'
,
'remember_token'
];
...
...
@@ -51,10 +48,6 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
}
/**
* Permissions and roles
*/
/**
* The roles that belong to the user.
*/
public
function
roles
()
...
...
@@ -62,21 +55,29 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
return
$this
->
belongsToMany
(
'BookStack\Role'
);
}
public
function
getRoleAttribute
()
/**
* Check if the user has a role.
* @param $role
* @return mixed
*/
public
function
hasRole
(
$role
)
{
return
$this
->
roles
()
->
with
(
'permissions'
)
->
first
(
);
return
$this
->
roles
->
pluck
(
'name'
)
->
contains
(
$role
);
}
/**
* Loads the user's permissions from their role.
* Get all permissions belonging to a the current user.
* @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
*/
p
rivate
function
loadP
ermissions
()
p
ublic
function
p
ermissions
()
{
if
(
isset
(
$this
->
permissions
))
return
;
if
(
isset
(
$this
->
permissions
))
return
$this
->
permissions
;
$this
->
load
(
'roles.permissions'
);
$permissions
=
$this
->
roles
[
0
]
->
permissions
;
$permissionsArray
=
$permissions
->
pluck
(
'name'
)
->
all
();
$this
->
permissions
=
$permissionsArray
;
$permissions
=
$this
->
roles
->
map
(
function
(
$role
)
{
return
$role
->
permissions
;
})
->
flatten
()
->
unique
();
$this
->
permissions
=
$permissions
;
return
$permissions
;
}
/**
...
...
@@ -86,11 +87,8 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
*/
public
function
can
(
$permissionName
)
{
if
(
$this
->
email
==
'guest'
)
{
return
false
;
}
$this
->
loadPermissions
();
return
array_search
(
$permissionName
,
$this
->
permissions
)
!==
false
;
if
(
$this
->
email
===
'guest'
)
return
false
;
return
$this
->
permissions
()
->
pluck
(
'name'
)
->
contains
(
$permissionName
);
}
/**
...
...
@@ -113,7 +111,6 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
/**
* Get the social account associated with this user.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public
function
socialAccounts
()
...
...
@@ -138,8 +135,6 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
/**
* Returns the user's avatar,
* Uses Gravatar as the avatar service.
*
* @param int $size
* @return string
*/
...
...
app/helpers.php
View file @
473261b
...
...
@@ -28,3 +28,23 @@ if (! function_exists('versioned_asset')) {
throw
new
InvalidArgumentException
(
"File
{
$file
}
not defined in asset manifest."
);
}
}
/**
* Check if the current user has a permission.
* If an ownable element is passed in the permissions are checked against
* that particular item.
* @param $permission
* @param \BookStack\Ownable $ownable
* @return mixed
*/
function
userCan
(
$permission
,
\BookStack\Ownable
$ownable
=
null
)
{
if
(
$ownable
===
null
)
{
return
auth
()
->
user
()
&&
auth
()
->
user
()
->
can
(
$permission
);
}
$permissionBaseName
=
strtolower
(
$permission
)
.
'-'
;
if
(
userCan
(
$permissionBaseName
.
'all'
))
return
true
;
if
(
userCan
(
$permissionBaseName
.
'own'
)
&&
$ownable
->
createdBy
->
id
===
auth
()
->
user
()
->
id
)
return
true
;
return
false
;
}
\ No newline at end of file
...
...
database/migrations/2016_02_27_120329_update_permissions_and_roles.php
0 → 100644
View file @
473261b
<?php
use
Illuminate\Database\Schema\Blueprint
;
use
Illuminate\Database\Migrations\Migration
;
class
UpdatePermissionsAndRoles
extends
Migration
{
/**
* Run the migrations.
*
* @return void
*/
public
function
up
()
{
// Get roles with permissions we need to change
$adminRole
=
\BookStack\Role
::
getRole
(
'admin'
);
$editorRole
=
\BookStack\Role
::
getRole
(
'editor'
);
// Delete old permissions
$permissions
=
\BookStack\Permission
::
all
();
$permissions
->
each
(
function
(
$permission
)
{
$permission
->
delete
();
});
// Create & attach new admin permissions
$permissionsToCreate
=
[
'settings-manage'
=>
'Manage Settings'
,
'users-manage'
=>
'Manage Users'
,
'user-roles-manage'
=>
'Manage Roles & Permissions'
];
foreach
(
$permissionsToCreate
as
$name
=>
$displayName
)
{
$newPermission
=
new
\BookStack\Permission
();
$newPermission
->
name
=
$name
;
$newPermission
->
display_name
=
$displayName
;
$newPermission
->
save
();
$adminRole
->
attachPermission
(
$newPermission
);
}
// Create & attach new entity permissions
$entities
=
[
'Book'
,
'Page'
,
'Chapter'
,
'Image'
];
$ops
=
[
'Create All'
,
'Create Own'
,
'Update All'
,
'Update Own'
,
'Delete All'
,
'Delete Own'
];
foreach
(
$entities
as
$entity
)
{
foreach
(
$ops
as
$op
)
{
$newPermission
=
new
\BookStack\Permission
();
$newPermission
->
name
=
strtolower
(
$entity
)
.
'-'
.
strtolower
(
str_replace
(
' '
,
'-'
,
$op
));
$newPermission
->
display_name
=
$op
.
' '
.
$entity
.
's'
;
$newPermission
->
save
();
$adminRole
->
attachPermission
(
$newPermission
);
if
(
$editorRole
!==
null
)
$editorRole
->
attachPermission
(
$newPermission
);
}
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public
function
down
()
{
// Get roles with permissions we need to change
$adminRole
=
\BookStack\Role
::
getRole
(
'admin'
);
// Delete old permissions
$permissions
=
\BookStack\Permission
::
all
();
$permissions
->
each
(
function
(
$permission
)
{
$permission
->
delete
();
});
// Create default CRUD permissions and allocate to admins and editors
$entities
=
[
'Book'
,
'Page'
,
'Chapter'
,
'Image'
];
$ops
=
[
'Create'
,
'Update'
,
'Delete'
];
foreach
(
$entities
as
$entity
)
{
foreach
(
$ops
as
$op
)
{
$newPermission
=
new
\BookStack\Permission
();
$newPermission
->
name
=
strtolower
(
$entity
)
.
'-'
.
strtolower
(
$op
);
$newPermission
->
display_name
=
$op
.
' '
.
$entity
.
's'
;
$newPermission
->
save
();
$adminRole
->
attachPermission
(
$newPermission
);
}
}
// Create admin permissions
$entities
=
[
'Settings'
,
'User'
];
$ops
=
[
'Create'
,
'Update'
,
'Delete'
];
foreach
(
$entities
as
$entity
)
{
foreach
(
$ops
as
$op
)
{
$newPermission
=
new
\BookStack\Permission
();
$newPermission
->
name
=
strtolower
(
$entity
)
.
'-'
.
strtolower
(
$op
);
$newPermission
->
display_name
=
$op
.
' '
.
$entity
;
$newPermission
->
save
();
$adminRole
->
attachPermission
(
$newPermission
);
}
}
}
}
resources/views/base.blade.php
View file @
473261b
...
...
@@ -43,7 +43,7 @@
<div
class=
"float right"
>
<div
class=
"links text-center"
>
<a
href=
"/books"
><i
class=
"zmdi zmdi-book"
></i>
Books
</a>
@if(isset($currentUser)
&&
$currentUser->can('settings-
updat
e'))
@if(isset($currentUser)
&&
$currentUser->can('settings-
manag
e'))
<a
href=
"/settings"
><i
class=
"zmdi zmdi-settings"
></i>
Settings
</a>
@endif
@if(!isset($signedIn) || !$signedIn)
...
...
resources/views/books/index.blade.php
View file @
473261b
...
...
@@ -8,7 +8,7 @@
<div
class=
"col-xs-1"
></div>
<div
class=
"col-xs-11 faded"
>
<div
class=
"action-buttons"
>
@if($currentUser->can('book-create'))
@if($currentUser->can('book-create
-all
'))
<a
href=
"/books/create"
class=
"text-pos text-button"
><i
class=
"zmdi zmdi-plus"
></i>
Add new book
</a>
@endif
</div>
...
...
resources/views/books/show.blade.php
View file @
473261b
...
...
@@ -7,17 +7,17 @@
<div
class=
"row"
>
<div
class=
"col-md-12"
>
<div
class=
"action-buttons faded"
>
@if(
$currentUser->can('page-create'
))
@if(
userCan('page-create', $book
))
<a
href=
"{{$book->getUrl() . '/page/create'}}"
class=
"text-pos text-button"
><i
class=
"zmdi zmdi-plus"
></i>
New Page
</a>
@endif
@if(
$currentUser->can('chapter-create'
))
@if(
userCan('chapter-create', $book
))
<a
href=
"{{$book->getUrl() . '/chapter/create'}}"
class=
"text-pos text-button"
><i
class=
"zmdi zmdi-plus"
></i>
New Chapter
</a>
@endif
@if(
$currentUser->can('book-update'
))
@if(
userCan('book-update', $book
))
<a
href=
"{{$book->getEditUrl()}}"
class=
"text-primary text-button"
><i
class=
"zmdi zmdi-edit"
></i>
Edit
</a>
<a
href=
"{{ $book->getUrl() }}/sort"
class=
"text-primary text-button"
><i
class=
"zmdi zmdi-sort"
></i>
Sort
</a>
@endif
@if(
$currentUser->can('book-delete'
))
@if(
userCan('book-delete', $book
))
<a
href=
"{{ $book->getUrl() }}/delete"
class=
"text-neg text-button"
><i
class=
"zmdi zmdi-delete"
></i>
Delete
</a>
@endif
</div>
...
...
resources/views/chapters/show.blade.php
View file @
473261b
...
...
@@ -12,13 +12,13 @@
</div>
<div
class=
"col-md-8 faded"
>
<div
class=
"action-buttons"
>
@if(
$currentUser->can('chapter-create'
))
@if(
userCan('page-create', $chapter
))
<a
href=
"{{$chapter->getUrl() . '/create-page'}}"
class=
"text-pos text-button"
><i
class=
"zmdi zmdi-plus"
></i>
New Page
</a>
@endif
@if(
$currentUser->can('chapter-update'
))
@if(
userCan('chapter-update', $chapter
))
<a
href=
"{{$chapter->getUrl() . '/edit'}}"
class=
"text-primary text-button"
><i
class=
"zmdi zmdi-edit"
></i>
Edit
</a>
@endif
@if(
$currentUser->can('chapter-delete'
))
@if(
userCan('chapter-delete', $chapter
))
<a
href=
"{{$chapter->getUrl() . '/delete'}}"
class=
"text-neg text-button"
><i
class=
"zmdi zmdi-delete"
></i>
Delete
</a>
@endif
</div>
...
...
resources/views/form/role-checkboxes.blade.php
0 → 100644
View file @
473261b
@foreach($roles as $role)
<label>
<input
value=
"{{ $role->id }}"
id=
"{{$name}}-{{$role->name}}"
type=
"checkbox"
name=
"{{$name}}[{{$role->name}}]"
@
if
($
errors-
>
has($name)) class="neg" @endif
@if(old($name . '.' . $role->name) || (!old('name')
&&
isset($model)
&&
$model->hasRole($role->name))) checked="checked" @endif
>
{{ $role->display_name }}
</label>
@endforeach
@if($errors->has($name))
<div
class=
"text-neg text-small"
>
{{ $errors->first($name) }}
</div>
@endif
\ No newline at end of file
resources/views/pages/show.blade.php
View file @
473261b
...
...
@@ -27,11 +27,11 @@
<li><a
href=
"{{$page->getUrl() . '/export/plaintext'}}"
target=
"_blank"
>
Plain Text File
<span
class=
"text-muted float right"
>
.txt
</span></a></li>
</ul>
</span>
@if(
$currentUser->can('page-update'
))
@if(
userCan('page-update', $page
))
<a
href=
"{{$page->getUrl() . '/revisions'}}"
class=
"text-primary text-button"
><i
class=
"zmdi zmdi-replay"
></i>
Revisions
</a>
<a
href=
"{{$page->getUrl() . '/edit'}}"
class=
"text-primary text-button"
><i
class=
"zmdi zmdi-edit"
></i>
Edit
</a>
@endif
@if(
$currentUser->can('page-delete'
))
@if(
userCan('page-delete', $page
))
<a
href=
"{{$page->getUrl() . '/delete'}}"
class=
"text-neg text-button"
><i
class=
"zmdi zmdi-delete"
></i>
Delete
</a>
@endif
</div>
...
...
resources/views/settings/index.blade.php
View file @
473261b
...
...
@@ -54,7 +54,7 @@
<select
id=
"setting-registration-role"
name=
"setting-registration-role"
@
if
($
errors-
>
has('setting-registration-role')) class="neg" @endif>
@foreach(\BookStack\Role::all() as $role)
<option
value=
"{{$role->id}}"
@
if
(\
Setting::get
('
registration-role
',
\
BookStack
\
Role::
getDefaul
t
()
-
>
id) == $role->id) selected @endif
@
if
(\
Setting::get
('
registration-role
',
\
BookStack
\
Role::
firs
t
()
-
>
id) == $role->id) selected @endif
>
{{ $role->display_name }}
</option>
...
...
resources/views/settings/roles/checkbox.blade.php
0 → 100644
View file @
473261b
<input
type=
"checkbox"
name=
"permissions[{{ $permission }}]"
@
if
(
old
('
permissions
.'.$
permission
,
false
)||
(!
old
('
display_name
',
false
)
&&
(
isset
($
role
)
&&
$
role-
>
hasPermission($permission)))) checked="checked" @endif
value="true">
\ No newline at end of file
resources/views/settings/roles/create.blade.php
0 → 100644
View file @
473261b
@extends('base')
@section('content')
@include('settings/navbar', ['selected' => 'roles'])
<div
class=
"container"
>
<h1>
Create New Role
</h1>
<form
action=
"/settings/roles/new"
method=
"POST"
>
@include('settings/roles/form')
</form>
</div>
@stop
resources/views/settings/roles/delete.blade.php
0 → 100644
View file @
473261b
@extends('base')
@section('content')
@include('settings/navbar', ['selected' => 'roles'])
<div
class=
"container small"
ng-non-bindable
>
<h1>
Delete Role
</h1>
<p>
This will delete the role with the name '{{$role->display_name}}'.
</p>
<form
action=
"/settings/roles/delete/{{$role->id}}"
method=
"POST"
>
{!! csrf_field() !!}
<input
type=
"hidden"
name=
"_method"
value=
"DELETE"
>
@if($role->users->count() > 0)
<div
class=
"form-group"
>
<p>
This role has {{$role->users->count()}} users assigned to it. If you would like to migrate the users from this role select a new role below.
</p>
@include('form/role-select', ['options' => $roles, 'name' => 'migration_role_id'])
</div>
@endif
<p
class=
"text-neg"
>
Are you sure you want to delete this role?
</p>
<a
href=
"/settings/roles/{{ $role->id }}"
class=
"button"
>
Cancel
</a>
<button
type=
"submit"
class=
"button neg"
>
Confirm
</button>
</form>
</div>
@stop
resources/views/settings/roles/edit.blade.php
View file @
473261b
...
...
@@ -5,59 +5,19 @@
@include('settings/navbar', ['selected' => 'roles'])
<div
class=
"container"
>
<h1>
Edit Role
<small>
{{ $role->display_name }}
</small></h1>
<form
action=
""
>
<div
class=
"row"
>
<div
class=
"col-md-6"
>
<table
class=
"table"
>
<tr>
<th></th>
<th>
Create
</th>
<th>
Edit
</th>
<th>
Delete
</th>
</tr>
<tr>
<td>
Books
</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>
Chapters
</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>
Pages
</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>
Images
</td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
<div
class=
"col-sm-6"
>
<h1>
Edit Role
<small>
{{ $role->display_name }}
</small></h1>
</div>
<div
class=
"col-md-6"
>
<div
class=
"form-group"
>
<label
for=
""
>
Can only edit own content
</label>
<hr
class=
"even"
>
<label
for=
""
>
Manage users
</label>
<hr
class=
"even"
>
<label
for=
""
>
Manage user roles
</label>
<hr
class=
"even"
>
<label
for=
""
>
Manage app settings
</label>
<div
class=
"col-sm-6"
>
<p></p>
<a
href=
"/settings/roles/delete/{{ $role->id }}"
class=
"button neg float right"
>
Delete Role
</a>
</div>
</div>
</div>
<button
type=
"submit"
class=
"button pos"
>
Save Role
</button>
<form
action=
"/settings/roles/{{ $role->id }}"
method=
"POST"
>
<input
type=
"hidden"
name=
"_method"
value=
"PUT"
>
@include('settings/roles/form', ['model' => $role])
</form>
</div>
...
...
resources/views/settings/roles/form.blade.php
0 → 100644
View file @
473261b
{!! csrf_field() !!}
<div
class=
"row"
>
<div
class=
"col-md-6"
>
<div
class=
"form-group"
>
<label
for=
"name"
>
Role Name
</label>
@include('form/text', ['name' => 'display_name'])
</div>
<div
class=
"form-group"
>
<label
for=
"name"
>
Short Role Description
</label>
@include('form/text', ['name' => 'description'])
</div>
<hr
class=
"even"
>
<div
class=
"form-group"
>
<label>
Manage users @include('settings/roles/checkbox', ['permission' => 'users-manage'])
</label>
<hr
class=
"even"
>
<label>
Manage user roles
&
Permissions @include('settings/roles/checkbox', ['permission' => 'user-roles-manage'])
</label>
<hr
class=
"even"
>
<label>
Manage app settings @include('settings/roles/checkbox', ['permission' => 'settings-manage'])
</label>
</div>
</div>
<div
class=
"col-md-6"
>
<table
class=
"table"
>
<tr>
<th></th>
<th>
Create
</th>
<th>
Edit
</th>
<th>
Delete
</th>
</tr>
<tr>
<td>
Books
</td>
<td>
@include('settings/roles/checkbox', ['permission' => 'book-create-all'])
</td>
<td>
<label>
@include('settings/roles/checkbox', ['permission' => 'book-update-own']) Own
</label>
<label>
@include('settings/roles/checkbox', ['permission' => 'book-update-all']) All
</label>
</td>
<td>
<label>
@include('settings/roles/checkbox', ['permission' => 'book-delete-own']) Own
</label>
<label>
@include('settings/roles/checkbox', ['permission' => 'book-delete-all']) All
</label>
</td>
</tr>
<tr>
<td>
Chapters
</td>
<td>
@include('settings/roles/checkbox', ['permission' => 'chapter-create-all'])
</td>
<td>
<label>
@include('settings/roles/checkbox', ['permission' => 'chapter-update-own']) Own
</label>
<label>
@include('settings/roles/checkbox', ['permission' => 'chapter-update-all']) All
</label>
</td>
<td>
<label>
@include('settings/roles/checkbox', ['permission' => 'chapter-delete-own']) Own
</label>
<label>
@include('settings/roles/checkbox', ['permission' => 'chapter-delete-all']) All
</label>
</td>
</tr>
<tr>
<td>
Pages
</td>
<td>
@include('settings/roles/checkbox', ['permission' => 'page-create-all'])
</td>
<td>
<label>
@include('settings/roles/checkbox', ['permission' => 'page-update-own']) Own
</label>
<label>
@include('settings/roles/checkbox', ['permission' => 'page-update-all']) All
</label>
</td>
<td>
<label>
@include('settings/roles/checkbox', ['permission' => 'page-delete-own']) Own
</label>
<label>
@include('settings/roles/checkbox', ['permission' => 'page-delete-all']) All
</label>
</td>
</tr>
<tr>
<td>
Images
</td>
<td>
@include('settings/roles/checkbox', ['permission' => 'image-create-all'])
</td>
<td>
<label>
@include('settings/roles/checkbox', ['permission' => 'image-update-own']) Own
</label>
<label>
@include('settings/roles/checkbox', ['permission' => 'image-update-all']) All
</label>
</td>
<td>
<label>
@include('settings/roles/checkbox', ['permission' => 'image-delete-own']) Own
</label>
<label>
@include('settings/roles/checkbox', ['permission' => 'image-delete-all']) All
</label>
</td>
</tr>
</table>
</div>
</div>
<button
type=
"submit"
class=
"button pos"
>
Save Role
</button>
\ No newline at end of file
resources/views/settings/roles/index.blade.php
View file @
473261b
...
...
@@ -7,6 +7,11 @@
<div
class=
"container"
>
<h1>
User Roles
</h1>
<p>
<a
href=
"/settings/roles/new"
class=
"text-pos"
><i
class=
"zmdi zmdi-lock-open"
></i>
Add new role
</a>
</p>
<table
class=
"table"
>
<tr>
<th>
Role Name
</th>
...
...
resources/views/users/forms/ldap.blade.php
View file @
473261b
...
...
@@ -3,21 +3,21 @@
@include('form.text', ['name' => 'name'])
</div>
@if(
$currentUser->can('user-updat
e'))
@if(
userCan('users-manag
e'))
<div
class=
"form-group"
>
<label
for=
"email"
>
Email
</label>
@include('form.text', ['name' => 'email'])
</div>
@endif
@if(
$currentUser->can('user-updat
e'))
@if(
userCan('users-manag
e'))
<div
class=
"form-group"
>
<label
for=
"role"
>
User Role
</label>
@include('form
.role-select', ['name' => 'role', 'options' => \BookStack\Role::all(), 'displayKey' => 'display_name'
])
@include('form
/role-checkboxes', ['name' => 'roles', 'roles' => \BookStack\Role::all()
])
</div>
@endif
@if(
$currentUser->can('user-updat
e'))
@if(
userCan('users-manag
e'))
<div
class=
"form-group"
>
<label
for=
"external_auth_id"
>
External Authentication ID
</label>
@include('form.text', ['name' => 'external_auth_id'])
...
...
resources/views/users/forms/standard.blade.php
View file @
473261b
...
...
@@ -8,10 +8,10 @@
@include('form.text', ['name' => 'email'])
</div>
@if(
$currentUser->can('user-updat
e'))
@if(
userCan('users-manag
e'))
<div
class=
"form-group"
>
<label
for=
"role"
>
User Role
</label>
@include('form
.role-select', ['name' => 'role', 'options' => \BookStack\Role::all(), 'displayKey' => 'display_name'
])
@include('form
/role-checkboxes', ['name' => 'roles', 'roles' => \BookStack\Role::all()
])
</div>
@endif
...
...
resources/views/users/index.blade.php
View file @
473261b
...
...
@@ -8,7 +8,7 @@
<div
class=
"container small"
ng-non-bindable
>
<h1>
Users
</h1>
@if(
$currentUser->can('user-creat
e'))
@if(
userCan('users-manag
e'))
<p>
<a
href=
"/settings/users/create"
class=
"text-pos"
><i
class=
"zmdi zmdi-account-add"
></i>
Add new user
</a>
</p>
...
...
@@ -18,30 +18,32 @@
<th></th>
<th>
Name
</th>
<th>
Email
</th>
<th>
User
Type
</th>
<th>
User
Roles
</th>
</tr>
@foreach($users as $user)
<tr>
<td
style=
"line-height: 0;"
><img
class=
"avatar med"
src=
"{{$user->getAvatar(40)}}"
alt=
"{{$user->name}}"
></td>
<td>
@if(
$currentUser->can('user-updat
e') || $currentUser->id == $user->id)
@if(
userCan('users-manag
e') || $currentUser->id == $user->id)
<a
href=
"/settings/users/{{$user->id}}"
>
@endif
{{ $user->name }}
@if(
$currentUser->can('user-updat
e') || $currentUser->id == $user->id)
@if(
userCan('users-manag
e') || $currentUser->id == $user->id)
</a>
@endif
</td>
<td>
@if(
$currentUser->can('user-updat
e') || $currentUser->id == $user->id)
@if(
userCan('users-manag
e') || $currentUser->id == $user->id)
<a
href=
"/settings/users/{{$user->id}}"
>
@endif
{{ $user->email }}
@if(
$currentUser->can('user-updat
e') || $currentUser->id == $user->id)
@if(
userCan('users-manag
e') || $currentUser->id == $user->id)
</a>
@endif
</td>
<td>
{{ $user->role->display_name }}
</td>
<td>
<small>
{{ $user->roles->implode('display_name', ', ') }}
</small>
</td>
</tr>
@endforeach
</table>
...
...
tests/Auth/AuthTest.php
View file @
473261b
...
...
@@ -133,12 +133,12 @@ class AuthTest extends TestCase
->
click
(
'Add new user'
)
->
type
(
$user
->
name
,
'#name'
)
->
type
(
$user
->
email
,
'#email'
)
->
select
(
2
,
'#role
'
)
->
check
(
'roles[admin]
'
)
->
type
(
$user
->
password
,
'#password'
)
->
type
(
$user
->
password
,
'#password-confirm'
)
->
press
(
'Save'
)
->
seeInDatabase
(
'users'
,
$user
->
toArray
())
->
seePageIs
(
'/settings/users'
)
->
seeInDatabase
(
'users'
,
$user
->
toArray
())
->
see
(
$user
->
name
);
}
...
...
tests/RolesTest.php
0 → 100644
View file @
473261b
<?php
class
RolesTest
extends
TestCase
{
protected
$user
;
public
function
setUp
()
{
parent
::
setUp
();
}
protected
function
createNewRole
()
{
return
\BookStack\Role
::
forceCreate
([
'name'
=>
'test-role'
,
'display_name'
=>
'Test Role'
,
'description'
=>
'This is a role for testing'
]);
}
public
function
test_admin_can_see_settings
()
{
$this
->
asAdmin
()
->
visit
(
'/settings'
)
->
see
(
'Settings'
);
}
public
function
test_cannot_delete_admin_role
()
{
$adminRole
=
\BookStack\Role
::
getRole
(
'admin'
);
$deletePageUrl
=
'/settings/roles/delete/'
.
$adminRole
->
id
;
$this
->
asAdmin
()
->
visit
(
$deletePageUrl
)
->
press
(
'Confirm'
)
->
seePageIs
(
$deletePageUrl
)
->
see
(
'cannot be deleted'
);
}
public
function
test_role_cannot_be_deleted_if_default
()
{
$newRole
=
$this
->
createNewRole
();
$this
->
setSettings
([
'registration-role'
=>
$newRole
->
id
]);
$deletePageUrl
=
'/settings/roles/delete/'
.
$newRole
->
id
;
$this
->
asAdmin
()
->
visit
(
$deletePageUrl
)
->
press
(
'Confirm'
)
->
seePageIs
(
$deletePageUrl
)
->
see
(
'cannot be deleted'
);
}
}
tests/TestCase.php
View file @
473261b
...
...
@@ -32,7 +32,8 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase
public
function
asAdmin
()
{
if
(
$this
->
admin
===
null
)
{
$this
->
admin
=
\BookStack\User
::
find
(
1
);
$adminRole
=
\BookStack\Role
::
getRole
(
'admin'
);
$this
->
admin
=
$adminRole
->
users
->
first
();
}
return
$this
->
actingAs
(
$this
->
admin
);
}
...
...
Please
register
or
sign in
to post a comment