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-10-10 20:30:27 +0100
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Commit
ac0b29fb6d05d6e943419b91fdbc09a59e20c89f
ac0b29fb
1 parent
673c74dd
Added view, deletion and permissions for files
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
152 additions
and
20 deletions
app/File.php
app/Http/Controllers/FileController.php
app/Services/FileService.php
database/migrations/2016_10_09_142037_create_files_table.php
resources/assets/js/controllers.js
resources/views/pages/form-toolbox.blade.php
resources/views/pages/sidebar-tree-list.blade.php
resources/views/settings/roles/form.blade.php
routes/web.php
app/File.php
View file @
ac0b29f
...
...
@@ -7,12 +7,20 @@ class File extends Ownable
/**
* Get the page this file was uploaded to.
* @return
mixed
* @return
Page
*/
public
function
page
()
{
return
$this
->
belongsTo
(
Page
::
class
,
'uploaded_to'
);
}
/**
* Get the url of this file.
* @return string
*/
public
function
getUrl
()
{
return
'/files/'
.
$this
->
id
;
}
}
...
...
app/Http/Controllers/FileController.php
View file @
ac0b29f
<?php
namespace
BookStack\Http\Controllers
;
<?php
namespace
BookStack\Http\Controllers
;
use
BookStack\Exceptions\FileUploadException
;
use
BookStack\File
;
use
BookStack\Page
;
use
BookStack\Repos\PageRepo
;
use
BookStack\Services\FileService
;
use
Illuminate\Http\Request
;
...
...
@@ -37,16 +34,18 @@ class FileController extends Controller
*/
public
function
upload
(
Request
$request
)
{
// TODO - Add file upload permission check
// TODO - ensure user has permission to edit relevant page.
// TODO - ensure uploads are deleted on page delete.
$this
->
validate
(
$request
,
[
'uploaded_to'
=>
'required|integer|exists:pages,id'
]);
$uploadedFile
=
$request
->
file
(
'file'
);
$pageId
=
$request
->
get
(
'uploaded_to'
);
$page
=
$this
->
pageRepo
->
getById
(
$pageId
);
$this
->
checkPermission
(
'file-create-all'
);
$this
->
checkOwnablePermission
(
'page-update'
,
$page
);
$uploadedFile
=
$request
->
file
(
'file'
);
try
{
$file
=
$this
->
fileService
->
saveNewUpload
(
$uploadedFile
,
$pageId
);
...
...
@@ -62,10 +61,10 @@ class FileController extends Controller
* @param $pageId
* @return mixed
*/
public
function
getFiles
ForPage
(
$pageId
)
public
function
list
ForPage
(
$pageId
)
{
// TODO - check view permission on page?
$page
=
$this
->
pageRepo
->
getById
(
$pageId
);
$this
->
checkOwnablePermission
(
'page-view'
,
$page
);
return
response
()
->
json
(
$page
->
files
);
}
...
...
@@ -75,17 +74,47 @@ class FileController extends Controller
* @param Request $request
* @return mixed
*/
public
function
sortF
ilesF
orPage
(
$pageId
,
Request
$request
)
public
function
sortForPage
(
$pageId
,
Request
$request
)
{
$this
->
validate
(
$request
,
[
'files'
=>
'required|array'
,
'files.*.id'
=>
'required|integer'
,
]);
$page
=
$this
->
pageRepo
->
getById
(
$pageId
);
$this
->
checkOwnablePermission
(
'page-update'
,
$page
);
$files
=
$request
->
get
(
'files'
);
$this
->
fileService
->
updateFileOrderWithinPage
(
$files
,
$pageId
);
return
response
()
->
json
([
'message'
=>
'File order updated'
]);
}
/**
* Get a file from storage.
* @param $fileId
*/
public
function
get
(
$fileId
)
{
$file
=
$this
->
file
->
findOrFail
(
$fileId
);
$page
=
$this
->
pageRepo
->
getById
(
$file
->
uploaded_to
);
$this
->
checkOwnablePermission
(
'page-view'
,
$page
);
$fileContents
=
$this
->
fileService
->
getFile
(
$file
);
return
response
(
$fileContents
,
200
,
[
'Content-Type'
=>
'application/octet-stream'
,
'Content-Disposition'
=>
'attachment; filename="'
.
$file
->
name
.
'"'
]);
}
/**
* Delete a specific file in the system.
* @param $fileId
* @return mixed
*/
public
function
delete
(
$fileId
)
{
$file
=
$this
->
file
->
findOrFail
(
$fileId
);
$this
->
checkOwnablePermission
(
$file
,
'file-delete'
);
$this
->
fileService
->
deleteFile
(
$file
);
return
response
()
->
json
([
'message'
=>
'File deleted'
]);
}
}
...
...
app/Services/FileService.php
View file @
ac0b29f
...
...
@@ -4,6 +4,7 @@
use
BookStack\Exceptions\FileUploadException
;
use
BookStack\File
;
use
Exception
;
use
Illuminate\Contracts\Filesystem\FileNotFoundException
;
use
Illuminate\Support\Collection
;
use
Symfony\Component\HttpFoundation\File\UploadedFile
;
...
...
@@ -11,6 +12,17 @@ class FileService extends UploadService
{
/**
* Get a file from storage.
* @param File $file
* @return string
*/
public
function
getFile
(
File
$file
)
{
$filePath
=
$this
->
getStorageBasePath
()
.
$file
->
path
;
return
$this
->
getStorage
()
->
get
(
$filePath
);
}
/**
* Store a new file upon user upload.
* @param UploadedFile $uploadedFile
* @param int $page_id
...
...
@@ -76,4 +88,22 @@ class FileService extends UploadService
}
}
/**
* Delete a file and any empty folders the deletion leaves.
* @param File $file
*/
public
function
deleteFile
(
File
$file
)
{
$storedFilePath
=
$this
->
getStorageBasePath
()
.
$file
->
path
;
$storage
=
$this
->
getStorage
();
$dirPath
=
dirname
(
$storedFilePath
);
$storage
->
delete
(
$storedFilePath
);
if
(
count
(
$storage
->
allFiles
(
$dirPath
))
===
0
)
{
$storage
->
deleteDirectory
(
$dirPath
);
}
$file
->
delete
();
}
}
\ No newline at end of file
...
...
database/migrations/2016_10_09_142037_create_files_table.php
View file @
ac0b29f
...
...
@@ -28,6 +28,26 @@ class CreateFilesTable extends Migration
$table
->
index
(
'uploaded_to'
);
$table
->
timestamps
();
});
// Get roles with permissions we need to change
$adminRoleId
=
DB
::
table
(
'roles'
)
->
where
(
'system_name'
,
'='
,
'admin'
)
->
first
()
->
id
;
// Create & attach new entity permissions
$ops
=
[
'Create All'
,
'Create Own'
,
'Update All'
,
'Update Own'
,
'Delete All'
,
'Delete Own'
];
$entity
=
'File'
;
foreach
(
$ops
as
$op
)
{
$permissionId
=
DB
::
table
(
'role_permissions'
)
->
insertGetId
([
'name'
=>
strtolower
(
$entity
)
.
'-'
.
strtolower
(
str_replace
(
' '
,
'-'
,
$op
)),
'display_name'
=>
$op
.
' '
.
$entity
.
's'
,
'created_at'
=>
\Carbon\Carbon
::
now
()
->
toDateTimeString
(),
'updated_at'
=>
\Carbon\Carbon
::
now
()
->
toDateTimeString
()
]);
DB
::
table
(
'permission_role'
)
->
insert
([
'role_id'
=>
$adminRoleId
,
'permission_id'
=>
$permissionId
]);
}
}
/**
...
...
@@ -38,5 +58,17 @@ class CreateFilesTable extends Migration
public
function
down
()
{
Schema
::
dropIfExists
(
'files'
);
// Get roles with permissions we need to change
$adminRoleId
=
DB
::
table
(
'roles'
)
->
where
(
'system_name'
,
'='
,
'admin'
)
->
first
()
->
id
;
// Create & attach new entity permissions
$ops
=
[
'Create All'
,
'Create Own'
,
'Update All'
,
'Update Own'
,
'Delete All'
,
'Delete Own'
];
$entity
=
'File'
;
foreach
(
$ops
as
$op
)
{
$permName
=
strtolower
(
$entity
)
.
'-'
.
strtolower
(
str_replace
(
' '
,
'-'
,
$op
));
$permission
=
DB
::
table
(
'role_permissions'
)
->
where
(
'name'
,
'='
,
$permName
)
->
get
();
DB
::
table
(
'permission_role'
)
->
where
(
'permission_id'
,
'='
,
$permission
->
id
)
->
delete
();
}
}
}
...
...
resources/assets/js/controllers.js
View file @
ac0b29f
...
...
@@ -575,9 +575,9 @@ module.exports = function (ngApp, events) {
*/
function
getFiles
()
{
let
url
=
window
.
baseUrl
(
`/files/get/page/
${
pageId
}
`
)
$http
.
get
(
url
).
then
(
resp
onseData
=>
{
$scope
.
files
=
resp
onseData
.
data
;
currentOrder
=
resp
onseData
.
data
.
map
(
file
=>
{
return
file
.
id
}).
join
(
':'
);
$http
.
get
(
url
).
then
(
resp
=>
{
$scope
.
files
=
resp
.
data
;
currentOrder
=
resp
.
data
.
map
(
file
=>
{
return
file
.
id
}).
join
(
':'
);
});
}
getFiles
();
...
...
@@ -595,6 +595,17 @@ module.exports = function (ngApp, events) {
events
.
emit
(
'success'
,
'File uploaded'
);
};
/**
* Delete a file from the server and, on success, the local listing.
* @param file
*/
$scope
.
deleteFile
=
function
(
file
)
{
$http
.
delete
(
`/files/
${
file
.
id
}
`
).
then
(
resp
=>
{
events
.
emit
(
'success'
,
resp
.
data
.
message
);
$scope
.
files
.
splice
(
$scope
.
files
.
indexOf
(
file
),
1
);
});
};
}]);
};
...
...
resources/views/pages/form-toolbox.blade.php
View file @
ac0b29f
...
...
@@ -46,7 +46,7 @@
<tr
ng-repeat=
"file in files track by $index"
>
<td
width=
"20"
><i
class=
"handle zmdi zmdi-menu"
></i></td>
<td
ng-bind=
"file.name"
></td>
<td
width=
"10"
class=
"text-center text-neg"
style=
"padding: 0;"
><i
class=
"zmdi zmdi-close"
></i></td>
<td
width=
"10"
ng-click=
"deleteFile(file)"
class=
"text-center text-neg"
style=
"padding: 0;"
><i
class=
"zmdi zmdi-close"
></i></td>
</tr>
</tbody>
</table>
...
...
resources/views/pages/sidebar-tree-list.blade.php
View file @
ac0b29f
<div
class=
"book-tree"
ng-non-bindable
>
@if ($page->files->count() > 0)
<h6
class=
"text-muted"
>
Attachments
</h6>
@foreach($page->files as $file)
<div
class=
"attachment"
>
<a
href=
"{{ $file->getUrl() }}"
><i
class=
"zmdi zmdi-file"
></i>
{{ $file->name }}
</a>
</div>
@endforeach
@endif
@if (isset($pageNav)
&&
$pageNav)
<h6
class=
"text-muted"
>
Page Navigation
</h6>
<div
class=
"sidebar-page-nav menu"
>
...
...
@@ -10,8 +19,6 @@
</li>
@endforeach
</div>
@endif
<h6
class=
"text-muted"
>
Book Navigation
</h6>
...
...
resources/views/settings/roles/form.blade.php
View file @
ac0b29f
...
...
@@ -106,6 +106,19 @@
<label>
@include('settings/roles/checkbox', ['permission' => 'image-delete-all']) All
</label>
</td>
</tr>
<tr>
<td>
Attached
<br>
Files
</td>
<td>
@include('settings/roles/checkbox', ['permission' => 'file-create-all'])
</td>
<td
style=
"line-height:1.2;"
><small
class=
"faded"
>
Controlled by the asset they are uploaded to
</small></td>
<td>
<label>
@include('settings/roles/checkbox', ['permission' => 'file-update-own']) Own
</label>
<label>
@include('settings/roles/checkbox', ['permission' => 'file-update-all']) All
</label>
</td>
<td>
<label>
@include('settings/roles/checkbox', ['permission' => 'file-delete-own']) Own
</label>
<label>
@include('settings/roles/checkbox', ['permission' => 'file-delete-all']) All
</label>
</td>
</tr>
</table>
</div>
</div>
...
...
routes/web.php
View file @
ac0b29f
...
...
@@ -88,9 +88,11 @@ Route::group(['middleware' => 'auth'], function () {
});
// File routes
Route
::
get
(
'/files/{id}'
,
'FileController@get'
);
Route
::
post
(
'/files/upload'
,
'FileController@upload'
);
Route
::
get
(
'/files/get/page/{pageId}'
,
'FileController@getFilesForPage'
);
Route
::
put
(
'/files/sort/page/{pageId}'
,
'FileController@sortFilesForPage'
);
Route
::
get
(
'/files/get/page/{pageId}'
,
'FileController@listForPage'
);
Route
::
put
(
'/files/sort/page/{pageId}'
,
'FileController@sortForPage'
);
Route
::
delete
(
'/files/{id}'
,
'FileController@delete'
);
// AJAX routes
Route
::
put
(
'/ajax/page/{id}/save-draft'
,
'PageController@saveDraft'
);
...
...
Please
register
or
sign in
to post a comment