]> BookStack Code Mirror - bookstack/blob - tests/Uploads/AttachmentTest.php
Checked over recycle bin parent/child flows
[bookstack] / tests / Uploads / AttachmentTest.php
1 <?php namespace Tests\Uploads;
2
3 use BookStack\Entities\Managers\TrashCan;
4 use BookStack\Entities\Repos\PageRepo;
5 use BookStack\Uploads\Attachment;
6 use BookStack\Entities\Page;
7 use BookStack\Auth\Permissions\PermissionService;
8 use Tests\TestCase;
9
10 class AttachmentTest extends TestCase
11 {
12     /**
13      * Get a test file that can be uploaded
14      * @param $fileName
15      * @return \Illuminate\Http\UploadedFile
16      */
17     protected function getTestFile($fileName)
18     {
19         return new \Illuminate\Http\UploadedFile(base_path('tests/test-data/test-file.txt'), $fileName, 'text/plain', 55, null, true);
20     }
21
22     /**
23      * Uploads a file with the given name.
24      * @param $name
25      * @param int $uploadedTo
26      * @return \Illuminate\Foundation\Testing\TestResponse
27      */
28     protected function uploadFile($name, $uploadedTo = 0)
29     {
30         $file = $this->getTestFile($name);
31         return $this->call('POST', '/attachments/upload', ['uploaded_to' => $uploadedTo], [], ['file' => $file], []);
32     }
33
34     /**
35      * Delete all uploaded files.
36      * To assist with cleanup.
37      */
38     protected function deleteUploads()
39     {
40         $fileService = $this->app->make(\BookStack\Uploads\AttachmentService::class);
41         foreach (Attachment::all() as $file) {
42             $fileService->deleteFile($file);
43         }
44     }
45
46     public function test_file_upload()
47     {
48         $page = Page::first();
49         $this->asAdmin();
50         $admin = $this->getAdmin();
51         $fileName = 'upload_test_file.txt';
52
53         $expectedResp = [
54             'name' => $fileName,
55             'uploaded_to'=> $page->id,
56             'extension' => 'txt',
57             'order' => 1,
58             'created_by' => $admin->id,
59             'updated_by' => $admin->id,
60         ];
61
62         $upload = $this->uploadFile($fileName, $page->id);
63         $upload->assertStatus(200);
64
65         $attachment = Attachment::query()->orderBy('id', 'desc')->first();
66         $expectedResp['path'] = $attachment->path;
67
68         $upload->assertJson($expectedResp);
69         $this->assertDatabaseHas('attachments', $expectedResp);
70
71         $this->deleteUploads();
72     }
73
74     public function test_file_upload_does_not_use_filename()
75     {
76         $page = Page::first();
77         $fileName = 'upload_test_file.txt';
78
79
80         $upload = $this->asAdmin()->uploadFile($fileName, $page->id);
81         $upload->assertStatus(200);
82
83         $attachment = Attachment::query()->orderBy('id', 'desc')->first();
84         $this->assertStringNotContainsString($fileName, $attachment->path);
85         $this->assertStringEndsWith('.txt', $attachment->path);
86     }
87
88     public function test_file_display_and_access()
89     {
90         $page = Page::first();
91         $this->asAdmin();
92         $fileName = 'upload_test_file.txt';
93
94         $upload = $this->uploadFile($fileName, $page->id);
95         $upload->assertStatus(200);
96         $attachment = Attachment::orderBy('id', 'desc')->take(1)->first();
97
98         $pageGet = $this->get($page->getUrl());
99         $pageGet->assertSeeText($fileName);
100         $pageGet->assertSee($attachment->getUrl());
101
102         $attachmentGet = $this->get($attachment->getUrl());
103         $attachmentGet->assertSee('Hi, This is a test file for testing the upload process.');
104
105         $this->deleteUploads();
106     }
107
108     public function test_attaching_link_to_page()
109     {
110         $page = Page::first();
111         $admin = $this->getAdmin();
112         $this->asAdmin();
113
114         $linkReq = $this->call('POST', 'attachments/link', [
115             'attachment_link_url' => 'https://example.com',
116             'attachment_link_name' => 'Example Attachment Link',
117             'attachment_link_uploaded_to' => $page->id,
118         ]);
119
120         $expectedData = [
121             'path' => 'https://example.com',
122             'name' => 'Example Attachment Link',
123             'uploaded_to' => $page->id,
124             'created_by' => $admin->id,
125             'updated_by' => $admin->id,
126             'external' => true,
127             'order' => 1,
128             'extension' => ''
129         ];
130
131         $linkReq->assertStatus(200);
132         $this->assertDatabaseHas('attachments', $expectedData);
133         $attachment = Attachment::orderBy('id', 'desc')->take(1)->first();
134
135         $pageGet = $this->get($page->getUrl());
136         $pageGet->assertSeeText('Example Attachment Link');
137         $pageGet->assertSee($attachment->getUrl());
138
139         $attachmentGet = $this->get($attachment->getUrl());
140         $attachmentGet->assertRedirect('https://example.com');
141
142         $this->deleteUploads();
143     }
144
145     public function test_attachment_updating()
146     {
147         $page = Page::first();
148         $this->asAdmin();
149
150         $this->call('POST', 'attachments/link', [
151             'attachment_link_url' => 'https://example.com',
152             'attachment_link_name' => 'Example Attachment Link',
153             'attachment_link_uploaded_to' => $page->id,
154         ]);
155
156         $attachmentId = Attachment::first()->id;
157
158         $update = $this->call('PUT', 'attachments/' . $attachmentId, [
159             'attachment_edit_name' => 'My new attachment name',
160             'attachment_edit_url' => 'https://test.example.com'
161         ]);
162
163         $expectedData = [
164             'id' => $attachmentId,
165             'path' => 'https://test.example.com',
166             'name' => 'My new attachment name',
167             'uploaded_to' => $page->id
168         ];
169
170         $update->assertStatus(200);
171         $this->assertDatabaseHas('attachments', $expectedData);
172
173         $this->deleteUploads();
174     }
175
176     public function test_file_deletion()
177     {
178         $page = Page::first();
179         $this->asAdmin();
180         $fileName = 'deletion_test.txt';
181         $this->uploadFile($fileName, $page->id);
182
183         $attachment = Attachment::query()->orderBy('id', 'desc')->first();
184         $filePath = storage_path($attachment->path);
185         $this->assertTrue(file_exists($filePath), 'File at path ' . $filePath . ' does not exist');
186
187         $attachment = Attachment::first();
188         $this->delete($attachment->getUrl());
189
190         $this->assertDatabaseMissing('attachments', [
191             'name' => $fileName
192         ]);
193         $this->assertFalse(file_exists($filePath), 'File at path ' . $filePath . ' was not deleted as expected');
194
195         $this->deleteUploads();
196     }
197
198     public function test_attachment_deletion_on_page_deletion()
199     {
200         $page = Page::first();
201         $this->asAdmin();
202         $fileName = 'deletion_test.txt';
203         $this->uploadFile($fileName, $page->id);
204
205         $attachment = Attachment::query()->orderBy('id', 'desc')->first();
206         $filePath = storage_path($attachment->path);
207
208         $this->assertTrue(file_exists($filePath), 'File at path ' . $filePath . ' does not exist');
209         $this->assertDatabaseHas('attachments', [
210             'name' => $fileName
211         ]);
212
213         app(PageRepo::class)->destroy($page);
214         app(TrashCan::class)->empty();
215
216         $this->assertDatabaseMissing('attachments', [
217             'name' => $fileName
218         ]);
219         $this->assertFalse(file_exists($filePath), 'File at path ' . $filePath . ' was not deleted as expected');
220
221         $this->deleteUploads();
222     }
223
224     public function test_attachment_access_without_permission_shows_404()
225     {
226         $admin = $this->getAdmin();
227         $viewer = $this->getViewer();
228         $page = Page::first(); /** @var Page $page */
229
230         $this->actingAs($admin);
231         $fileName = 'permission_test.txt';
232         $this->uploadFile($fileName, $page->id);
233         $attachment = Attachment::orderBy('id', 'desc')->take(1)->first();
234
235         $page->restricted = true;
236         $page->permissions()->delete();
237         $page->save();
238         $page->rebuildPermissions();
239         $page->load('jointPermissions');
240
241         $this->actingAs($viewer);
242         $attachmentGet = $this->get($attachment->getUrl());
243         $attachmentGet->assertStatus(404);
244         $attachmentGet->assertSee("Attachment not found");
245
246         $this->deleteUploads();
247     }
248 }