mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-06-06 02:24:33 +08:00
Added attachment creation from link/name
This commit is contained in:
@ -71,8 +71,13 @@ abstract class Controller extends BaseController
|
|||||||
*/
|
*/
|
||||||
protected function showPermissionError()
|
protected function showPermissionError()
|
||||||
{
|
{
|
||||||
Session::flash('error', trans('errors.permission'));
|
if (request()->wantsJson()) {
|
||||||
$response = request()->wantsJson() ? response()->json(['error' => trans('errors.permissionJson')], 403) : redirect('/');
|
$response = response()->json(['error' => trans('errors.permissionJson')], 403);
|
||||||
|
} else {
|
||||||
|
$response = redirect('/');
|
||||||
|
session()->flash('error', trans('errors.permission'));
|
||||||
|
}
|
||||||
|
|
||||||
throw new HttpResponseException($response);
|
throw new HttpResponseException($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +88,7 @@ abstract class Controller extends BaseController
|
|||||||
*/
|
*/
|
||||||
protected function checkPermission($permissionName)
|
protected function checkPermission($permissionName)
|
||||||
{
|
{
|
||||||
if (!$this->currentUser || !$this->currentUser->can($permissionName)) {
|
if (!user() || !user()->can($permissionName)) {
|
||||||
$this->showPermissionError();
|
$this->showPermissionError();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -36,7 +36,8 @@ class FileController extends Controller
|
|||||||
{
|
{
|
||||||
// TODO - ensure uploads are deleted on page delete.
|
// TODO - ensure uploads are deleted on page delete.
|
||||||
$this->validate($request, [
|
$this->validate($request, [
|
||||||
'uploaded_to' => 'required|integer|exists:pages,id'
|
'uploaded_to' => 'required|integer|exists:pages,id',
|
||||||
|
'file' => 'required|file'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$pageId = $request->get('uploaded_to');
|
$pageId = $request->get('uploaded_to');
|
||||||
@ -56,6 +57,32 @@ class FileController extends Controller
|
|||||||
return response()->json($file);
|
return response()->json($file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach a link to a page as a file.
|
||||||
|
* @param Request $request
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function attachLink(Request $request)
|
||||||
|
{
|
||||||
|
$this->validate($request, [
|
||||||
|
'uploaded_to' => 'required|integer|exists:pages,id',
|
||||||
|
'name' => 'string',
|
||||||
|
'link' => 'url'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$pageId = $request->get('uploaded_to');
|
||||||
|
$page = $this->pageRepo->getById($pageId);
|
||||||
|
|
||||||
|
$this->checkPermission('file-create-all');
|
||||||
|
$this->checkOwnablePermission('page-update', $page);
|
||||||
|
|
||||||
|
$fileName = $request->get('name');
|
||||||
|
$link = $request->get('link');
|
||||||
|
$file = $this->fileService->saveNewFromLink($fileName, $link, $pageId);
|
||||||
|
|
||||||
|
return response()->json($file);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the files for a specific page.
|
* Get the files for a specific page.
|
||||||
* @param $pageId
|
* @param $pageId
|
||||||
@ -85,7 +112,7 @@ class FileController extends Controller
|
|||||||
|
|
||||||
$files = $request->get('files');
|
$files = $request->get('files');
|
||||||
$this->fileService->updateFileOrderWithinPage($files, $pageId);
|
$this->fileService->updateFileOrderWithinPage($files, $pageId);
|
||||||
return response()->json(['message' => 'File order updated']);
|
return response()->json(['message' => 'Attachment order updated']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,6 +125,10 @@ class FileController extends Controller
|
|||||||
$page = $this->pageRepo->getById($file->uploaded_to);
|
$page = $this->pageRepo->getById($file->uploaded_to);
|
||||||
$this->checkOwnablePermission('page-view', $page);
|
$this->checkOwnablePermission('page-view', $page);
|
||||||
|
|
||||||
|
if ($file->external) {
|
||||||
|
return redirect($file->path);
|
||||||
|
}
|
||||||
|
|
||||||
$fileContents = $this->fileService->getFile($file);
|
$fileContents = $this->fileService->getFile($file);
|
||||||
return response($fileContents, 200, [
|
return response($fileContents, 200, [
|
||||||
'Content-Type' => 'application/octet-stream',
|
'Content-Type' => 'application/octet-stream',
|
||||||
@ -113,8 +144,8 @@ class FileController extends Controller
|
|||||||
public function delete($fileId)
|
public function delete($fileId)
|
||||||
{
|
{
|
||||||
$file = $this->file->findOrFail($fileId);
|
$file = $this->file->findOrFail($fileId);
|
||||||
$this->checkOwnablePermission($file, 'file-delete');
|
$this->checkOwnablePermission('file-delete', $file);
|
||||||
$this->fileService->deleteFile($file);
|
$this->fileService->deleteFile($file);
|
||||||
return response()->json(['message' => 'File deleted']);
|
return response()->json(['message' => 'Attachment deleted']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,27 @@ class FileService extends UploadService
|
|||||||
return $file;
|
return $file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save a new File attachment from a given link and name.
|
||||||
|
* @param string $name
|
||||||
|
* @param string $link
|
||||||
|
* @param int $page_id
|
||||||
|
* @return File
|
||||||
|
*/
|
||||||
|
public function saveNewFromLink($name, $link, $page_id)
|
||||||
|
{
|
||||||
|
$largestExistingOrder = File::where('uploaded_to', '=', $page_id)->max('order');
|
||||||
|
return File::forceCreate([
|
||||||
|
'name' => $name,
|
||||||
|
'path' => $link,
|
||||||
|
'external' => true,
|
||||||
|
'uploaded_to' => $page_id,
|
||||||
|
'created_by' => user()->id,
|
||||||
|
'updated_by' => user()->id,
|
||||||
|
'order' => $largestExistingOrder + 1
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the file storage base path, amended for storage type.
|
* Get the file storage base path, amended for storage type.
|
||||||
* This allows us to keep a generic path in the database.
|
* This allows us to keep a generic path in the database.
|
||||||
@ -94,6 +115,11 @@ class FileService extends UploadService
|
|||||||
*/
|
*/
|
||||||
public function deleteFile(File $file)
|
public function deleteFile(File $file)
|
||||||
{
|
{
|
||||||
|
if ($file->external) {
|
||||||
|
$file->delete();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$storedFilePath = $this->getStorageBasePath() . $file->path;
|
$storedFilePath = $this->getStorageBasePath() . $file->path;
|
||||||
$storage = $this->getStorage();
|
$storage = $this->getStorage();
|
||||||
$dirPath = dirname($storedFilePath);
|
$dirPath = dirname($storedFilePath);
|
||||||
|
@ -606,6 +606,18 @@ module.exports = function (ngApp, events) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.attachLinkSubmit = function(fileName, fileLink) {
|
||||||
|
$http.post('/files/link', {
|
||||||
|
uploaded_to: pageId,
|
||||||
|
name: fileName,
|
||||||
|
link: fileLink
|
||||||
|
}).then(resp => {
|
||||||
|
$scope.files.unshift(resp.data);
|
||||||
|
events.emit('success', 'Link attached');
|
||||||
|
});
|
||||||
|
$scope.fileName = $scope.fileLink = '';
|
||||||
|
};
|
||||||
|
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -41,6 +41,19 @@
|
|||||||
<p class="muted small">Upload some files to display on your page. This are visible in the page sidebar.</p>
|
<p class="muted small">Upload some files to display on your page. This are visible in the page sidebar.</p>
|
||||||
<drop-zone upload-url="@{{getUploadUrl()}}" uploaded-to="@{{uploadedTo}}" event-success="uploadSuccess"></drop-zone>
|
<drop-zone upload-url="@{{getUploadUrl()}}" uploaded-to="@{{uploadedTo}}" event-success="uploadSuccess"></drop-zone>
|
||||||
|
|
||||||
|
<hr class="even">
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="attachment-via-link">File Name</label>
|
||||||
|
<input type="text" placeholder="File name" ng-model="fileName">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="attachment-via-link">Link to file</label>
|
||||||
|
<input type="text" placeholder="File url" ng-model="fileLink">
|
||||||
|
</div>
|
||||||
|
<button type="button" ng-click="attachLinkSubmit(fileName, fileLink)" class="button pos">Attach</button>
|
||||||
|
|
||||||
|
|
||||||
<table class="no-style" tag-autosuggestions style="width: 100%;">
|
<table class="no-style" tag-autosuggestions style="width: 100%;">
|
||||||
<tbody ui-sortable="sortOptions" ng-model="files" >
|
<tbody ui-sortable="sortOptions" ng-model="files" >
|
||||||
<tr ng-repeat="file in files track by $index">
|
<tr ng-repeat="file in files track by $index">
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<h6 class="text-muted">Attachments</h6>
|
<h6 class="text-muted">Attachments</h6>
|
||||||
@foreach($page->files as $file)
|
@foreach($page->files as $file)
|
||||||
<div class="attachment">
|
<div class="attachment">
|
||||||
<a href="{{ $file->getUrl() }}"><i class="zmdi zmdi-file"></i> {{ $file->name }}</a>
|
<a href="{{ $file->getUrl() }}" @if($file->external) target="_blank" @endif><i class="zmdi zmdi-file"></i> {{ $file->name }}</a>
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
@endif
|
@endif
|
||||||
|
@ -90,6 +90,7 @@ Route::group(['middleware' => 'auth'], function () {
|
|||||||
// File routes
|
// File routes
|
||||||
Route::get('/files/{id}', 'FileController@get');
|
Route::get('/files/{id}', 'FileController@get');
|
||||||
Route::post('/files/upload', 'FileController@upload');
|
Route::post('/files/upload', 'FileController@upload');
|
||||||
|
Route::post('/files/link', 'FileController@attachLink');
|
||||||
Route::get('/files/get/page/{pageId}', 'FileController@listForPage');
|
Route::get('/files/get/page/{pageId}', 'FileController@listForPage');
|
||||||
Route::put('/files/sort/page/{pageId}', 'FileController@sortForPage');
|
Route::put('/files/sort/page/{pageId}', 'FileController@sortForPage');
|
||||||
Route::delete('/files/{id}', 'FileController@delete');
|
Route::delete('/files/{id}', 'FileController@delete');
|
||||||
|
Reference in New Issue
Block a user