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