]> BookStack Code Mirror - bookstack/blob - app/Http/Controllers/AttachmentController.php
Updated php dependancies for minor release
[bookstack] / app / Http / Controllers / AttachmentController.php
1 <?php namespace BookStack\Http\Controllers;
2
3 use BookStack\Entities\Repos\PageRepo;
4 use BookStack\Exceptions\FileUploadException;
5 use BookStack\Exceptions\NotFoundException;
6 use BookStack\Uploads\Attachment;
7 use BookStack\Uploads\AttachmentService;
8 use Exception;
9 use Illuminate\Contracts\Filesystem\FileNotFoundException;
10 use Illuminate\Http\Request;
11 use Illuminate\Support\MessageBag;
12 use Illuminate\Validation\ValidationException;
13
14 class AttachmentController extends Controller
15 {
16     protected $attachmentService;
17     protected $pageRepo;
18
19     /**
20      * AttachmentController constructor.
21      */
22     public function __construct(AttachmentService $attachmentService, PageRepo $pageRepo)
23     {
24         $this->attachmentService = $attachmentService;
25         $this->pageRepo = $pageRepo;
26     }
27
28
29     /**
30      * Endpoint at which attachments are uploaded to.
31      * @throws ValidationException
32      * @throws NotFoundException
33      */
34     public function upload(Request $request)
35     {
36         $this->validate($request, [
37             'uploaded_to' => 'required|integer|exists:pages,id',
38             'file' => 'required|file'
39         ]);
40
41         $pageId = $request->get('uploaded_to');
42         $page = $this->pageRepo->getById($pageId);
43
44         $this->checkPermission('attachment-create-all');
45         $this->checkOwnablePermission('page-update', $page);
46
47         $uploadedFile = $request->file('file');
48
49         try {
50             $attachment = $this->attachmentService->saveNewUpload($uploadedFile, $pageId);
51         } catch (FileUploadException $e) {
52             return response($e->getMessage(), 500);
53         }
54
55         return response()->json($attachment);
56     }
57
58     /**
59      * Update an uploaded attachment.
60      * @throws ValidationException
61      */
62     public function uploadUpdate(Request $request, $attachmentId)
63     {
64         $this->validate($request, [
65             'file' => 'required|file'
66         ]);
67
68         $attachment = Attachment::query()->findOrFail($attachmentId);
69         $this->checkOwnablePermission('view', $attachment->page);
70         $this->checkOwnablePermission('page-update', $attachment->page);
71         $this->checkOwnablePermission('attachment-create', $attachment);
72
73         $uploadedFile = $request->file('file');
74
75         try {
76             $attachment = $this->attachmentService->saveUpdatedUpload($uploadedFile, $attachment);
77         } catch (FileUploadException $e) {
78             return response($e->getMessage(), 500);
79         }
80
81         return response()->json($attachment);
82     }
83
84     /**
85      * Get the update form for an attachment.
86      * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
87      */
88     public function getUpdateForm(string $attachmentId)
89     {
90         $attachment = Attachment::query()->findOrFail($attachmentId);
91
92         $this->checkOwnablePermission('page-update', $attachment->page);
93         $this->checkOwnablePermission('attachment-create', $attachment);
94
95         return view('attachments.manager-edit-form', [
96             'attachment' => $attachment,
97         ]);
98     }
99
100     /**
101      * Update the details of an existing file.
102      */
103     public function update(Request $request, string $attachmentId)
104     {
105         /** @var Attachment $attachment */
106         $attachment = Attachment::query()->findOrFail($attachmentId);
107         try {
108             $this->validate($request, [
109                 'attachment_edit_name' => 'required|string|min:1|max:255',
110                 'attachment_edit_url' =>  'string|min:1|max:255|safe_url'
111             ]);
112         } catch (ValidationException $exception) {
113             return response()->view('attachments.manager-edit-form', array_merge($request->only(['attachment_edit_name', 'attachment_edit_url']), [
114                 'attachment' => $attachment,
115                 'errors' => new MessageBag($exception->errors()),
116             ]), 422);
117         }
118
119         $this->checkOwnablePermission('view', $attachment->page);
120         $this->checkOwnablePermission('page-update', $attachment->page);
121         $this->checkOwnablePermission('attachment-create', $attachment);
122
123         $attachment = $this->attachmentService->updateFile($attachment, [
124             'name' => $request->get('attachment_edit_name'),
125             'link' => $request->get('attachment_edit_url'),
126         ]);
127
128         return view('attachments.manager-edit-form', [
129             'attachment' => $attachment,
130         ]);
131     }
132
133     /**
134      * Attach a link to a page.
135      * @throws NotFoundException
136      */
137     public function attachLink(Request $request)
138     {
139         $pageId = $request->get('attachment_link_uploaded_to');
140
141         try {
142             $this->validate($request, [
143                 'attachment_link_uploaded_to' => 'required|integer|exists:pages,id',
144                 'attachment_link_name' => 'required|string|min:1|max:255',
145                 'attachment_link_url' =>  'required|string|min:1|max:255|safe_url'
146             ]);
147         } catch (ValidationException $exception) {
148             return response()->view('attachments.manager-link-form', array_merge($request->only(['attachment_link_name', 'attachment_link_url']), [
149                 'pageId' => $pageId,
150                 'errors' => new MessageBag($exception->errors()),
151             ]), 422);
152         }
153
154         $page = $this->pageRepo->getById($pageId);
155
156         $this->checkPermission('attachment-create-all');
157         $this->checkOwnablePermission('page-update', $page);
158
159         $attachmentName = $request->get('attachment_link_name');
160         $link = $request->get('attachment_link_url');
161         $this->attachmentService->saveNewFromLink($attachmentName, $link, intval($pageId));
162
163         return view('attachments.manager-link-form', [
164             'pageId' => $pageId,
165         ]);
166     }
167
168     /**
169      * Get the attachments for a specific page.
170      */
171     public function listForPage(int $pageId)
172     {
173         $page = $this->pageRepo->getById($pageId);
174         $this->checkOwnablePermission('page-view', $page);
175         return view('attachments.manager-list', [
176             'attachments' => $page->attachments->all(),
177         ]);
178     }
179
180     /**
181      * Update the attachment sorting.
182      * @throws ValidationException
183      * @throws NotFoundException
184      */
185     public function sortForPage(Request $request, int $pageId)
186     {
187         $this->validate($request, [
188             'order' => 'required|array',
189         ]);
190         $page = $this->pageRepo->getById($pageId);
191         $this->checkOwnablePermission('page-update', $page);
192
193         $attachmentOrder = $request->get('order');
194         $this->attachmentService->updateFileOrderWithinPage($attachmentOrder, $pageId);
195         return response()->json(['message' => trans('entities.attachments_order_updated')]);
196     }
197
198     /**
199      * Get an attachment from storage.
200      * @throws FileNotFoundException
201      * @throws NotFoundException
202      */
203     public function get(Request $request, string $attachmentId)
204     {
205         /** @var Attachment $attachment */
206         $attachment = Attachment::query()->findOrFail($attachmentId);
207         try {
208             $page = $this->pageRepo->getById($attachment->uploaded_to);
209         } catch (NotFoundException $exception) {
210             throw new NotFoundException(trans('errors.attachment_not_found'));
211         }
212
213         $this->checkOwnablePermission('page-view', $page);
214
215         if ($attachment->external) {
216             return redirect($attachment->path);
217         }
218
219         $fileName = $attachment->getFileName();
220         $attachmentContents = $this->attachmentService->getAttachmentFromStorage($attachment);
221
222         if ($request->get('open') === 'true') {
223             return $this->inlineDownloadResponse($attachmentContents, $fileName);
224         }
225         return $this->downloadResponse($attachmentContents, $fileName);
226     }
227
228     /**
229      * Delete a specific attachment in the system.
230      * @throws Exception
231      */
232     public function delete(string $attachmentId)
233     {
234         /** @var Attachment $attachment */
235         $attachment = Attachment::query()->findOrFail($attachmentId);
236         $this->checkOwnablePermission('attachment-delete', $attachment);
237         $this->attachmentService->deleteFile($attachment);
238         return response()->json(['message' => trans('entities.attachments_deleted')]);
239     }
240 }