| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | <?php | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | namespace Tests\Uploads; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | use BookStack\Entities\Models\Page; | 
					
						
							| 
									
										
										
										
											2020-11-06 20:54:39 +08:00
										 |  |  | use BookStack\Entities\Repos\PageRepo; | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | use BookStack\Entities\Tools\TrashCan; | 
					
						
							| 
									
										
										
										
											2018-09-25 19:30:50 +08:00
										 |  |  | use BookStack\Uploads\Attachment; | 
					
						
							| 
									
										
										
										
											2020-04-04 08:16:05 +08:00
										 |  |  | use Tests\TestCase; | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class AttachmentTest extends TestCase | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     public function test_file_upload() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-09-30 00:31:38 +08:00
										 |  |  |         $page = $this->entities->page(); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |         $this->asAdmin(); | 
					
						
							| 
									
										
										
										
											2023-01-21 19:08:34 +08:00
										 |  |  |         $admin = $this->users->admin(); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |         $fileName = 'upload_test_file.txt'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $expectedResp = [ | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |             'name'       => $fileName, | 
					
						
							| 
									
										
										
										
											2022-09-18 08:25:20 +08:00
										 |  |  |             'uploaded_to' => $page->id, | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |             'extension'  => 'txt', | 
					
						
							|  |  |  |             'order'      => 1, | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |             'created_by' => $admin->id, | 
					
						
							|  |  |  |             'updated_by' => $admin->id, | 
					
						
							|  |  |  |         ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $upload = $this->files->uploadAttachmentFile($this, $fileName, $page->id); | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  |         $upload->assertStatus(200); | 
					
						
							| 
									
										
										
										
											2019-03-25 03:07:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $attachment = Attachment::query()->orderBy('id', 'desc')->first(); | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  |         $upload->assertJson($expectedResp); | 
					
						
							| 
									
										
										
										
											2021-10-20 07:58:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $expectedResp['path'] = $attachment->path; | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  |         $this->assertDatabaseHas('attachments', $expectedResp); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $this->files->deleteAllAttachmentFiles(); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-25 03:07:18 +08:00
										 |  |  |     public function test_file_upload_does_not_use_filename() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-09-30 00:31:38 +08:00
										 |  |  |         $page = $this->entities->page(); | 
					
						
							| 
									
										
										
										
											2019-03-25 03:07:18 +08:00
										 |  |  |         $fileName = 'upload_test_file.txt'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $this->asAdmin(); | 
					
						
							|  |  |  |         $upload = $this->files->uploadAttachmentFile($this, $fileName, $page->id); | 
					
						
							| 
									
										
										
										
											2019-03-25 03:07:18 +08:00
										 |  |  |         $upload->assertStatus(200); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $attachment = Attachment::query()->orderBy('id', 'desc')->first(); | 
					
						
							| 
									
										
										
										
											2019-09-14 21:12:39 +08:00
										 |  |  |         $this->assertStringNotContainsString($fileName, $attachment->path); | 
					
						
							| 
									
										
										
										
											2021-11-01 19:32:00 +08:00
										 |  |  |         $this->assertStringEndsWith('-txt', $attachment->path); | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $this->files->deleteAllAttachmentFiles(); | 
					
						
							| 
									
										
										
										
											2019-03-25 03:07:18 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |     public function test_file_display_and_access() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-09-30 00:31:38 +08:00
										 |  |  |         $page = $this->entities->page(); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |         $this->asAdmin(); | 
					
						
							|  |  |  |         $fileName = 'upload_test_file.txt'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $upload = $this->files->uploadAttachmentFile($this, $fileName, $page->id); | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  |         $upload->assertStatus(200); | 
					
						
							|  |  |  |         $attachment = Attachment::orderBy('id', 'desc')->take(1)->first(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $pageGet = $this->get($page->getUrl()); | 
					
						
							|  |  |  |         $pageGet->assertSeeText($fileName); | 
					
						
							|  |  |  |         $pageGet->assertSee($attachment->getUrl()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $attachmentGet = $this->get($attachment->getUrl()); | 
					
						
							| 
									
										
										
										
											2022-04-03 23:22:31 +08:00
										 |  |  |         $content = $attachmentGet->streamedContent(); | 
					
						
							|  |  |  |         $this->assertStringContainsString('Hi, This is a test file for testing the upload process.', $content); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $this->files->deleteAllAttachmentFiles(); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function test_attaching_link_to_page() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-09-30 00:31:38 +08:00
										 |  |  |         $page = $this->entities->page(); | 
					
						
							| 
									
										
										
										
											2023-01-21 19:08:34 +08:00
										 |  |  |         $admin = $this->users->admin(); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |         $this->asAdmin(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  |         $linkReq = $this->call('POST', 'attachments/link', [ | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |             'attachment_link_url'         => 'https://example.com', | 
					
						
							|  |  |  |             'attachment_link_name'        => 'Example Attachment Link', | 
					
						
							| 
									
										
										
										
											2020-07-05 00:04:26 +08:00
										 |  |  |             'attachment_link_uploaded_to' => $page->id, | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |         ]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-05 00:04:26 +08:00
										 |  |  |         $expectedData = [ | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |             'path'        => 'https://example.com', | 
					
						
							|  |  |  |             'name'        => 'Example Attachment Link', | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |             'uploaded_to' => $page->id, | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |             'created_by'  => $admin->id, | 
					
						
							|  |  |  |             'updated_by'  => $admin->id, | 
					
						
							|  |  |  |             'external'    => true, | 
					
						
							|  |  |  |             'order'       => 1, | 
					
						
							|  |  |  |             'extension'   => '', | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |         ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  |         $linkReq->assertStatus(200); | 
					
						
							| 
									
										
										
										
											2020-07-05 00:04:26 +08:00
										 |  |  |         $this->assertDatabaseHas('attachments', $expectedData); | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  |         $attachment = Attachment::orderBy('id', 'desc')->take(1)->first(); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  |         $pageGet = $this->get($page->getUrl()); | 
					
						
							|  |  |  |         $pageGet->assertSeeText('Example Attachment Link'); | 
					
						
							|  |  |  |         $pageGet->assertSee($attachment->getUrl()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $attachmentGet = $this->get($attachment->getUrl()); | 
					
						
							|  |  |  |         $attachmentGet->assertRedirect('https://example.com'); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $this->files->deleteAllAttachmentFiles(); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-20 21:05:23 +08:00
										 |  |  |     public function test_attaching_long_links_to_a_page() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $page = $this->entities->page(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $link = 'https://example.com?query=' . str_repeat('catsIScool', 195); | 
					
						
							|  |  |  |         $linkReq = $this->asAdmin()->post('attachments/link', [ | 
					
						
							|  |  |  |             'attachment_link_url'         => $link, | 
					
						
							|  |  |  |             'attachment_link_name'        => 'Example Attachment Link', | 
					
						
							|  |  |  |             'attachment_link_uploaded_to' => $page->id, | 
					
						
							|  |  |  |         ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $linkReq->assertStatus(200); | 
					
						
							|  |  |  |         $this->assertDatabaseHas('attachments', [ | 
					
						
							|  |  |  |             'uploaded_to' => $page->id, | 
					
						
							|  |  |  |             'path' => $link, | 
					
						
							|  |  |  |             'external' => true, | 
					
						
							|  |  |  |         ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $attachment = $page->attachments()->where('external', '=', true)->first(); | 
					
						
							|  |  |  |         $resp = $this->get($attachment->getUrl()); | 
					
						
							|  |  |  |         $resp->assertRedirect($link); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |     public function test_attachment_updating() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-09-30 00:31:38 +08:00
										 |  |  |         $page = $this->entities->page(); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |         $this->asAdmin(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $attachment = Attachment::factory()->create(['uploaded_to' => $page->id]); | 
					
						
							| 
									
										
										
										
											2020-10-31 23:01:52 +08:00
										 |  |  |         $update = $this->call('PUT', 'attachments/' . $attachment->id, [ | 
					
						
							| 
									
										
										
										
											2020-07-05 00:04:26 +08:00
										 |  |  |             'attachment_edit_name' => 'My new attachment name', | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |             'attachment_edit_url'  => 'https://test.example.com', | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |         ]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-05 00:04:26 +08:00
										 |  |  |         $expectedData = [ | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |             'id'          => $attachment->id, | 
					
						
							|  |  |  |             'path'        => 'https://test.example.com', | 
					
						
							|  |  |  |             'name'        => 'My new attachment name', | 
					
						
							|  |  |  |             'uploaded_to' => $page->id, | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |         ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  |         $update->assertStatus(200); | 
					
						
							| 
									
										
										
										
											2020-07-05 00:04:26 +08:00
										 |  |  |         $this->assertDatabaseHas('attachments', $expectedData); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $this->files->deleteAllAttachmentFiles(); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function test_file_deletion() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-09-30 00:31:38 +08:00
										 |  |  |         $page = $this->entities->page(); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |         $this->asAdmin(); | 
					
						
							|  |  |  |         $fileName = 'deletion_test.txt'; | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $this->files->uploadAttachmentFile($this, $fileName, $page->id); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-25 03:07:18 +08:00
										 |  |  |         $attachment = Attachment::query()->orderBy('id', 'desc')->first(); | 
					
						
							|  |  |  |         $filePath = storage_path($attachment->path); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |         $this->assertTrue(file_exists($filePath), 'File at path ' . $filePath . ' does not exist'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-05 00:04:26 +08:00
										 |  |  |         $attachment = Attachment::first(); | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  |         $this->delete($attachment->getUrl()); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  |         $this->assertDatabaseMissing('attachments', [ | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |             'name' => $fileName, | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |         ]); | 
					
						
							|  |  |  |         $this->assertFalse(file_exists($filePath), 'File at path ' . $filePath . ' was not deleted as expected'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $this->files->deleteAllAttachmentFiles(); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function test_attachment_deletion_on_page_deletion() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-09-30 00:31:38 +08:00
										 |  |  |         $page = $this->entities->page(); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |         $this->asAdmin(); | 
					
						
							|  |  |  |         $fileName = 'deletion_test.txt'; | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $this->files->uploadAttachmentFile($this, $fileName, $page->id); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-25 03:07:18 +08:00
										 |  |  |         $attachment = Attachment::query()->orderBy('id', 'desc')->first(); | 
					
						
							|  |  |  |         $filePath = storage_path($attachment->path); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $this->assertTrue(file_exists($filePath), 'File at path ' . $filePath . ' does not exist'); | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  |         $this->assertDatabaseHas('attachments', [ | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |             'name' => $fileName, | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |         ]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 20:54:39 +08:00
										 |  |  |         app(PageRepo::class)->destroy($page); | 
					
						
							|  |  |  |         app(TrashCan::class)->empty(); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  |         $this->assertDatabaseMissing('attachments', [ | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |             'name' => $fileName, | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |         ]); | 
					
						
							|  |  |  |         $this->assertFalse(file_exists($filePath), 'File at path ' . $filePath . ' was not deleted as expected'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $this->files->deleteAllAttachmentFiles(); | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public function test_attachment_access_without_permission_shows_404() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-01-21 19:08:34 +08:00
										 |  |  |         $admin = $this->users->admin(); | 
					
						
							|  |  |  |         $viewer = $this->users->viewer(); | 
					
						
							| 
									
										
										
										
											2022-09-30 00:31:38 +08:00
										 |  |  |         $page = $this->entities->page(); /** @var Page $page */ | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  |         $this->actingAs($admin); | 
					
						
							|  |  |  |         $fileName = 'permission_test.txt'; | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $this->files->uploadAttachmentFile($this, $fileName, $page->id); | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  |         $attachment = Attachment::orderBy('id', 'desc')->take(1)->first(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-21 19:08:34 +08:00
										 |  |  |         $this->permissions->setEntityPermissions($page, [], []); | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $this->actingAs($viewer); | 
					
						
							|  |  |  |         $attachmentGet = $this->get($attachment->getUrl()); | 
					
						
							|  |  |  |         $attachmentGet->assertStatus(404); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |         $attachmentGet->assertSee('Attachment not found'); | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $this->files->deleteAllAttachmentFiles(); | 
					
						
							| 
									
										
										
										
											2018-02-11 20:37:02 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-10-31 23:01:52 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public function test_data_and_js_links_cannot_be_attached_to_a_page() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-09-30 00:31:38 +08:00
										 |  |  |         $page = $this->entities->page(); | 
					
						
							| 
									
										
										
										
											2020-10-31 23:01:52 +08:00
										 |  |  |         $this->asAdmin(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $badLinks = [ | 
					
						
							|  |  |  |             'javascript:alert("bunny")', | 
					
						
							|  |  |  |             ' javascript:alert("bunny")', | 
					
						
							|  |  |  |             'JavaScript:alert("bunny")', | 
					
						
							|  |  |  |             "\t\n\t\nJavaScript:alert(\"bunny\")", | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |             'data:text/html;<a></a>', | 
					
						
							|  |  |  |             'Data:text/html;<a></a>', | 
					
						
							|  |  |  |             'Data:text/html;<a></a>', | 
					
						
							| 
									
										
										
										
											2020-10-31 23:01:52 +08:00
										 |  |  |         ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($badLinks as $badLink) { | 
					
						
							|  |  |  |             $linkReq = $this->post('attachments/link', [ | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |                 'attachment_link_url'         => $badLink, | 
					
						
							|  |  |  |                 'attachment_link_name'        => 'Example Attachment Link', | 
					
						
							| 
									
										
										
										
											2020-10-31 23:01:52 +08:00
										 |  |  |                 'attachment_link_uploaded_to' => $page->id, | 
					
						
							|  |  |  |             ]); | 
					
						
							|  |  |  |             $linkReq->assertStatus(422); | 
					
						
							|  |  |  |             $this->assertDatabaseMissing('attachments', [ | 
					
						
							|  |  |  |                 'path' => $badLink, | 
					
						
							|  |  |  |             ]); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $attachment = Attachment::factory()->create(['uploaded_to' => $page->id]); | 
					
						
							| 
									
										
										
										
											2020-10-31 23:01:52 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         foreach ($badLinks as $badLink) { | 
					
						
							|  |  |  |             $linkReq = $this->put('attachments/' . $attachment->id, [ | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |                 'attachment_edit_url'  => $badLink, | 
					
						
							| 
									
										
										
										
											2020-10-31 23:01:52 +08:00
										 |  |  |                 'attachment_edit_name' => 'Example Attachment Link', | 
					
						
							|  |  |  |             ]); | 
					
						
							|  |  |  |             $linkReq->assertStatus(422); | 
					
						
							|  |  |  |             $this->assertDatabaseMissing('attachments', [ | 
					
						
							|  |  |  |                 'path' => $badLink, | 
					
						
							|  |  |  |             ]); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-06-06 20:55:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-12 04:38:30 +08:00
										 |  |  |     public function test_attachment_delete_only_shows_with_permission() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->asAdmin(); | 
					
						
							|  |  |  |         $page = $this->entities->page(); | 
					
						
							|  |  |  |         $this->files->uploadAttachmentFile($this, 'upload_test.txt', $page->id); | 
					
						
							|  |  |  |         $attachment = $page->attachments()->first(); | 
					
						
							|  |  |  |         $viewer = $this->users->viewer(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->permissions->grantUserRolePermissions($viewer, ['page-update-all', 'attachment-create-all']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $resp = $this->actingAs($viewer)->get($page->getUrl('/edit')); | 
					
						
							|  |  |  |         $html = $this->withHtml($resp); | 
					
						
							|  |  |  |         $html->assertElementExists(".card[data-id=\"{$attachment->id}\"]"); | 
					
						
							|  |  |  |         $html->assertElementNotExists(".card[data-id=\"{$attachment->id}\"] button[title=\"Delete\"]"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->permissions->grantUserRolePermissions($viewer, ['attachment-delete-all']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $resp = $this->actingAs($viewer)->get($page->getUrl('/edit')); | 
					
						
							|  |  |  |         $html = $this->withHtml($resp); | 
					
						
							|  |  |  |         $html->assertElementExists(".card[data-id=\"{$attachment->id}\"] button[title=\"Delete\"]"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function test_attachment_edit_only_shows_with_permission() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->asAdmin(); | 
					
						
							|  |  |  |         $page = $this->entities->page(); | 
					
						
							|  |  |  |         $this->files->uploadAttachmentFile($this, 'upload_test.txt', $page->id); | 
					
						
							|  |  |  |         $attachment = $page->attachments()->first(); | 
					
						
							|  |  |  |         $viewer = $this->users->viewer(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->permissions->grantUserRolePermissions($viewer, ['page-update-all', 'attachment-create-all']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $resp = $this->actingAs($viewer)->get($page->getUrl('/edit')); | 
					
						
							|  |  |  |         $html = $this->withHtml($resp); | 
					
						
							|  |  |  |         $html->assertElementExists(".card[data-id=\"{$attachment->id}\"]"); | 
					
						
							|  |  |  |         $html->assertElementNotExists(".card[data-id=\"{$attachment->id}\"] button[title=\"Edit\"]"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->permissions->grantUserRolePermissions($viewer, ['attachment-update-all']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $resp = $this->actingAs($viewer)->get($page->getUrl('/edit')); | 
					
						
							|  |  |  |         $html = $this->withHtml($resp); | 
					
						
							|  |  |  |         $html->assertElementExists(".card[data-id=\"{$attachment->id}\"] button[title=\"Edit\"]"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-06 20:55:56 +08:00
										 |  |  |     public function test_file_access_with_open_query_param_provides_inline_response_with_correct_content_type() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-09-30 00:31:38 +08:00
										 |  |  |         $page = $this->entities->page(); | 
					
						
							| 
									
										
										
										
											2021-06-06 20:55:56 +08:00
										 |  |  |         $this->asAdmin(); | 
					
						
							|  |  |  |         $fileName = 'upload_test_file.txt'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $upload = $this->files->uploadAttachmentFile($this, $fileName, $page->id); | 
					
						
							| 
									
										
										
										
											2021-06-06 20:55:56 +08:00
										 |  |  |         $upload->assertStatus(200); | 
					
						
							|  |  |  |         $attachment = Attachment::query()->orderBy('id', 'desc')->take(1)->first(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $attachmentGet = $this->get($attachment->getUrl(true)); | 
					
						
							|  |  |  |         // http-foundation/Response does some 'fixing' of responses to add charsets to text responses.
 | 
					
						
							|  |  |  |         $attachmentGet->assertHeader('Content-Type', 'text/plain; charset=UTF-8'); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |         $attachmentGet->assertHeader('Content-Disposition', 'inline; filename="upload_test_file.txt"'); | 
					
						
							| 
									
										
										
										
											2021-11-01 01:58:56 +08:00
										 |  |  |         $attachmentGet->assertHeader('X-Content-Type-Options', 'nosniff'); | 
					
						
							| 
									
										
										
										
											2021-06-06 20:55:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $this->files->deleteAllAttachmentFiles(); | 
					
						
							| 
									
										
										
										
											2021-06-06 20:55:56 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-11-01 01:58:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public function test_html_file_access_with_open_forces_plain_content_type() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-09-30 00:31:38 +08:00
										 |  |  |         $page = $this->entities->page(); | 
					
						
							| 
									
										
										
										
											2021-11-01 01:58:56 +08:00
										 |  |  |         $this->asAdmin(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $attachment = $this->files->uploadAttachmentDataToPage($this, $page, 'test_file.html', '<html></html><p>testing</p>', 'text/html'); | 
					
						
							| 
									
										
										
										
											2021-11-01 01:58:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $attachmentGet = $this->get($attachment->getUrl(true)); | 
					
						
							|  |  |  |         // http-foundation/Response does some 'fixing' of responses to add charsets to text responses.
 | 
					
						
							|  |  |  |         $attachmentGet->assertHeader('Content-Type', 'text/plain; charset=UTF-8'); | 
					
						
							|  |  |  |         $attachmentGet->assertHeader('Content-Disposition', 'inline; filename="test_file.html"'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $this->files->deleteAllAttachmentFiles(); | 
					
						
							| 
									
										
										
										
											2021-11-01 01:58:56 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-02 21:40:17 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public function test_file_upload_works_when_local_secure_restricted_is_in_use() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         config()->set('filesystems.attachments', 'local_secure_restricted'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 00:31:38 +08:00
										 |  |  |         $page = $this->entities->page(); | 
					
						
							| 
									
										
										
										
											2022-09-02 21:40:17 +08:00
										 |  |  |         $fileName = 'upload_test_file.txt'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $this->asAdmin(); | 
					
						
							|  |  |  |         $upload = $this->files->uploadAttachmentFile($this, $fileName, $page->id); | 
					
						
							| 
									
										
										
										
											2022-09-02 21:40:17 +08:00
										 |  |  |         $upload->assertStatus(200); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $attachment = Attachment::query()->orderBy('id', 'desc')->where('uploaded_to', '=', $page->id)->first(); | 
					
						
							|  |  |  |         $this->assertFileExists(storage_path($attachment->path)); | 
					
						
							| 
									
										
										
										
											2023-02-08 22:39:13 +08:00
										 |  |  |         $this->files->deleteAllAttachmentFiles(); | 
					
						
							| 
									
										
										
										
											2022-09-02 21:40:17 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-01-14 23:50:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public function test_file_get_range_access() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $page = $this->entities->page(); | 
					
						
							|  |  |  |         $this->asAdmin(); | 
					
						
							|  |  |  |         $attachment = $this->files->uploadAttachmentDataToPage($this, $page, 'my_text.txt', 'abc123456', 'text/plain'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Download access
 | 
					
						
							|  |  |  |         $resp = $this->get($attachment->getUrl(), ['Range' => 'bytes=3-5']); | 
					
						
							|  |  |  |         $resp->assertStatus(206); | 
					
						
							|  |  |  |         $resp->assertStreamedContent('123'); | 
					
						
							|  |  |  |         $resp->assertHeader('Content-Length', '3'); | 
					
						
							|  |  |  |         $resp->assertHeader('Content-Range', 'bytes 3-5/9'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Inline access
 | 
					
						
							|  |  |  |         $resp = $this->get($attachment->getUrl(true), ['Range' => 'bytes=5-7']); | 
					
						
							|  |  |  |         $resp->assertStatus(206); | 
					
						
							|  |  |  |         $resp->assertStreamedContent('345'); | 
					
						
							|  |  |  |         $resp->assertHeader('Content-Length', '3'); | 
					
						
							|  |  |  |         $resp->assertHeader('Content-Range', 'bytes 5-7/9'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->files->deleteAllAttachmentFiles(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function test_file_head_range_returns_no_content() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $page = $this->entities->page(); | 
					
						
							|  |  |  |         $this->asAdmin(); | 
					
						
							|  |  |  |         $attachment = $this->files->uploadAttachmentDataToPage($this, $page, 'my_text.txt', 'abc123456', 'text/plain'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $resp = $this->head($attachment->getUrl(), ['Range' => 'bytes=0-9']); | 
					
						
							|  |  |  |         $resp->assertStreamedContent(''); | 
					
						
							|  |  |  |         $resp->assertHeader('Content-Length', '9'); | 
					
						
							|  |  |  |         $resp->assertStatus(200); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->files->deleteAllAttachmentFiles(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function test_file_head_range_edge_cases() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $page = $this->entities->page(); | 
					
						
							|  |  |  |         $this->asAdmin(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Mime-type "sniffing" happens on first 2k bytes, hence this content (2005 bytes)
 | 
					
						
							|  |  |  |         $content = '01234' . str_repeat('a', 1990) . '0123456789'; | 
					
						
							|  |  |  |         $attachment = $this->files->uploadAttachmentDataToPage($this, $page, 'my_text.txt', $content, 'text/plain'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Test for both inline and download attachment serving
 | 
					
						
							|  |  |  |         foreach ([true, false] as $isInline) { | 
					
						
							|  |  |  |             // No end range
 | 
					
						
							|  |  |  |             $resp = $this->get($attachment->getUrl($isInline), ['Range' => 'bytes=5-']); | 
					
						
							|  |  |  |             $resp->assertStreamedContent(substr($content, 5)); | 
					
						
							|  |  |  |             $resp->assertHeader('Content-Length', '2000'); | 
					
						
							|  |  |  |             $resp->assertHeader('Content-Range', 'bytes 5-2004/2005'); | 
					
						
							|  |  |  |             $resp->assertStatus(206); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // End only range
 | 
					
						
							|  |  |  |             $resp = $this->get($attachment->getUrl($isInline), ['Range' => 'bytes=-10']); | 
					
						
							|  |  |  |             $resp->assertStreamedContent('0123456789'); | 
					
						
							|  |  |  |             $resp->assertHeader('Content-Length', '10'); | 
					
						
							|  |  |  |             $resp->assertHeader('Content-Range', 'bytes 1995-2004/2005'); | 
					
						
							|  |  |  |             $resp->assertStatus(206); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Range across sniff point
 | 
					
						
							|  |  |  |             $resp = $this->get($attachment->getUrl($isInline), ['Range' => 'bytes=1997-2002']); | 
					
						
							|  |  |  |             $resp->assertStreamedContent('234567'); | 
					
						
							|  |  |  |             $resp->assertHeader('Content-Length', '6'); | 
					
						
							|  |  |  |             $resp->assertHeader('Content-Range', 'bytes 1997-2002/2005'); | 
					
						
							|  |  |  |             $resp->assertStatus(206); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Range up to sniff point
 | 
					
						
							|  |  |  |             $resp = $this->get($attachment->getUrl($isInline), ['Range' => 'bytes=0-1997']); | 
					
						
							|  |  |  |             $resp->assertHeader('Content-Length', '1998'); | 
					
						
							|  |  |  |             $resp->assertHeader('Content-Range', 'bytes 0-1997/2005'); | 
					
						
							|  |  |  |             $resp->assertStreamedContent(substr($content, 0, 1998)); | 
					
						
							|  |  |  |             $resp->assertStatus(206); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Range beyond sniff point
 | 
					
						
							|  |  |  |             $resp = $this->get($attachment->getUrl($isInline), ['Range' => 'bytes=2001-2003']); | 
					
						
							|  |  |  |             $resp->assertStreamedContent('678'); | 
					
						
							|  |  |  |             $resp->assertHeader('Content-Length', '3'); | 
					
						
							|  |  |  |             $resp->assertHeader('Content-Range', 'bytes 2001-2003/2005'); | 
					
						
							|  |  |  |             $resp->assertStatus(206); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Range beyond content
 | 
					
						
							|  |  |  |             $resp = $this->get($attachment->getUrl($isInline), ['Range' => 'bytes=0-2010']); | 
					
						
							|  |  |  |             $resp->assertStreamedContent($content); | 
					
						
							|  |  |  |             $resp->assertHeader('Content-Length', '2005'); | 
					
						
							| 
									
										
										
										
											2024-11-29 21:19:55 +08:00
										 |  |  |             $resp->assertHeader('Content-Range', 'bytes 0-2004/2005'); | 
					
						
							|  |  |  |             $resp->assertStatus(206); | 
					
						
							| 
									
										
										
										
											2024-01-14 23:50:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // Range start before end
 | 
					
						
							|  |  |  |             $resp = $this->get($attachment->getUrl($isInline), ['Range' => 'bytes=50-10']); | 
					
						
							|  |  |  |             $resp->assertStreamedContent($content); | 
					
						
							|  |  |  |             $resp->assertHeader('Content-Length', '2005'); | 
					
						
							|  |  |  |             $resp->assertHeader('Content-Range', 'bytes */2005'); | 
					
						
							|  |  |  |             $resp->assertStatus(416); | 
					
						
							| 
									
										
										
										
											2024-11-29 21:19:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // Full range request
 | 
					
						
							|  |  |  |             $resp = $this->get($attachment->getUrl($isInline), ['Range' => 'bytes=0-']); | 
					
						
							|  |  |  |             $resp->assertStreamedContent($content); | 
					
						
							|  |  |  |             $resp->assertHeader('Content-Length', '2005'); | 
					
						
							|  |  |  |             $resp->assertHeader('Content-Range', 'bytes 0-2004/2005'); | 
					
						
							|  |  |  |             $resp->assertStatus(206); | 
					
						
							| 
									
										
										
										
											2024-01-14 23:50:00 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->files->deleteAllAttachmentFiles(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-10-23 22:25:04 +08:00
										 |  |  | } |