X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/7bbcaa7cbc96d1da4758d9eee2ffc156cb64545b..refs/pull/3698/head:/tests/Api/AttachmentsApiTest.php diff --git a/tests/Api/AttachmentsApiTest.php b/tests/Api/AttachmentsApiTest.php index 88b5b9ddd..6077868b2 100644 --- a/tests/Api/AttachmentsApiTest.php +++ b/tests/Api/AttachmentsApiTest.php @@ -5,6 +5,7 @@ namespace Tests\Api; use BookStack\Entities\Models\Page; use BookStack\Uploads\Attachment; use Illuminate\Http\UploadedFile; +use Illuminate\Testing\AssertableJsonString; use Tests\TestCase; class AttachmentsApiTest extends TestCase @@ -18,17 +19,17 @@ class AttachmentsApiTest extends TestCase $this->actingAsApiEditor(); $page = Page::query()->first(); $attachment = $this->createAttachmentForPage($page, [ - 'name' => 'My test attachment', + 'name' => 'My test attachment', 'external' => true, ]); $resp = $this->getJson($this->baseEndpoint . '?count=1&sort=+id'); $resp->assertJson(['data' => [ [ - 'id' => $attachment->id, - 'name' => 'My test attachment', + 'id' => $attachment->id, + 'name' => 'My test attachment', 'uploaded_to' => $page->id, - 'external' => true, + 'external' => true, ], ]]); } @@ -39,7 +40,7 @@ class AttachmentsApiTest extends TestCase /** @var Page $page */ $page = Page::query()->first(); $attachment = $this->createAttachmentForPage($page, [ - 'name' => 'My test attachment', + 'name' => 'My test attachment', 'external' => true, ]); @@ -69,9 +70,9 @@ class AttachmentsApiTest extends TestCase $page = Page::query()->first(); $details = [ - 'name' => 'My attachment', + 'name' => 'My attachment', 'uploaded_to' => $page->id, - 'link' => 'https://cats.example.com', + 'link' => 'https://cats.example.com', ]; $resp = $this->postJson($this->baseEndpoint, $details); @@ -89,7 +90,7 @@ class AttachmentsApiTest extends TestCase $file = $this->getTestFile('textfile.txt'); $details = [ - 'name' => 'My attachment', + 'name' => 'My attachment', 'uploaded_to' => $page->id, ]; @@ -102,6 +103,30 @@ class AttachmentsApiTest extends TestCase unlink(storage_path($newItem->path)); } + public function test_upload_limit_restricts_attachment_uploads() + { + $this->actingAsApiAdmin(); + /** @var Page $page */ + $page = Page::query()->first(); + + config()->set('app.upload_limit', 1); + + $file = tmpfile(); + $filePath = stream_get_meta_data($file)['uri']; + fwrite($file, str_repeat('a', 1200000)); + $file = new UploadedFile($filePath, 'test.txt', 'text/plain', null, true); + + $details = [ + 'name' => 'My attachment', + 'uploaded_to' => $page->id, + ]; + $resp = $this->call('POST', $this->baseEndpoint, $details, [], ['file' => $file]); + $resp->assertStatus(422); + $resp->assertJson($this->validationResponse([ + 'file' => ['The file may not be greater than 1000 kilobytes.'], + ])); + } + public function test_name_needed_to_create() { $this->actingAsApiAdmin(); @@ -110,20 +135,12 @@ class AttachmentsApiTest extends TestCase $details = [ 'uploaded_to' => $page->id, - 'link' => 'https://example.com', + 'link' => 'https://example.com', ]; $resp = $this->postJson($this->baseEndpoint, $details); $resp->assertStatus(422); - $resp->assertJson([ - 'error' => [ - 'message' => 'The given data was invalid.', - 'validation' => [ - 'name' => ['The name field is required.'], - ], - 'code' => 422, - ], - ]); + $resp->assertJson($this->validationResponse(['name' => ['The name field is required.']])); } public function test_link_or_file_needed_to_create() @@ -133,22 +150,33 @@ class AttachmentsApiTest extends TestCase $page = Page::query()->first(); $details = [ - 'name' => 'my attachment', + 'name' => 'my attachment', 'uploaded_to' => $page->id, ]; $resp = $this->postJson($this->baseEndpoint, $details); $resp->assertStatus(422); - $resp->assertJson([ - 'error' => [ - 'message' => 'The given data was invalid.', - 'validation' => [ - "file" => ["The file field is required when link is not present."], - "link" => ["The link field is required when file is not present."], - ], - 'code' => 422, - ], - ]); + $resp->assertJson($this->validationResponse([ + 'file' => ['The file field is required when link is not present.'], + 'link' => ['The link field is required when file is not present.'], + ])); + } + + public function test_message_shown_if_file_is_not_a_valid_file() + { + $this->actingAsApiAdmin(); + /** @var Page $page */ + $page = Page::query()->first(); + + $details = [ + 'name' => 'my attachment', + 'uploaded_to' => $page->id, + 'file' => 'cat', + ]; + + $resp = $this->postJson($this->baseEndpoint, $details); + $resp->assertStatus(422); + $resp->assertJson($this->validationResponse(['file' => ['The file must be provided as a valid file.']])); } public function test_read_endpoint_for_link_attachment() @@ -158,8 +186,8 @@ class AttachmentsApiTest extends TestCase $page = Page::query()->first(); $attachment = $this->createAttachmentForPage($page, [ - 'name' => 'my attachment', - 'path' => 'https://example.com', + 'name' => 'my attachment', + 'path' => 'https://example.com', 'order' => 1, ]); @@ -167,20 +195,20 @@ class AttachmentsApiTest extends TestCase $resp->assertStatus(200); $resp->assertJson([ - 'id' => $attachment->id, - 'content' => 'https://example.com', - 'external' => true, + 'id' => $attachment->id, + 'content' => 'https://example.com', + 'external' => true, 'uploaded_to' => $page->id, - 'order' => 1, - 'created_by' => [ + 'order' => 1, + 'created_by' => [ 'name' => $attachment->createdBy->name, ], 'updated_by' => [ 'name' => $attachment->createdBy->name, ], 'links' => [ - "html" => "id}\">my attachment", - "markdown" => "[my attachment](http://localhost/attachments/{$attachment->id})" + 'html' => "id}\">my attachment", + 'markdown' => "[my attachment](http://localhost/attachments/{$attachment->id})", ], ]); } @@ -193,7 +221,7 @@ class AttachmentsApiTest extends TestCase $file = $this->getTestFile('textfile.txt'); $details = [ - 'name' => 'My file attachment', + 'name' => 'My file attachment', 'uploaded_to' => $page->id, ]; $this->call('POST', $this->baseEndpoint, $details, [], ['file' => $file]); @@ -201,29 +229,54 @@ class AttachmentsApiTest extends TestCase $attachment = Attachment::query()->orderByDesc('id')->where('name', '=', $details['name'])->firstOrFail(); $resp = $this->getJson("{$this->baseEndpoint}/{$attachment->id}"); - $resp->assertStatus(200); - $resp->assertJson([ - 'id' => $attachment->id, - 'content' => base64_encode(file_get_contents(storage_path($attachment->path))), - 'external' => false, + $resp->assertHeader('Content-Type', 'application/json'); + + $json = new AssertableJsonString($resp->streamedContent()); + $json->assertSubset([ + 'id' => $attachment->id, + 'content' => base64_encode(file_get_contents(storage_path($attachment->path))), + 'external' => false, 'uploaded_to' => $page->id, - 'order' => 1, - 'created_by' => [ + 'order' => 1, + 'created_by' => [ 'name' => $attachment->createdBy->name, ], 'updated_by' => [ 'name' => $attachment->updatedBy->name, ], 'links' => [ - "html" => "id}\">My file attachment", - "markdown" => "[My file attachment](http://localhost/attachments/{$attachment->id})" + 'html' => "id}\">My file attachment", + 'markdown' => "[My file attachment](http://localhost/attachments/{$attachment->id})", ], ]); unlink(storage_path($attachment->path)); } + public function test_attachment_not_visible_on_other_users_draft() + { + $this->actingAsApiAdmin(); + $editor = $this->getEditor(); + + /** @var Page $page */ + $page = Page::query()->first(); + $page->draft = true; + $page->owned_by = $editor->id; + $page->save(); + $this->regenEntityPermissions($page); + + $attachment = $this->createAttachmentForPage($page, [ + 'name' => 'my attachment', + 'path' => 'https://example.com', + 'order' => 1, + ]); + + $resp = $this->getJson("{$this->baseEndpoint}/{$attachment->id}"); + + $resp->assertStatus(404); + } + public function test_update_endpoint() { $this->actingAsApiAdmin(); @@ -250,7 +303,6 @@ class AttachmentsApiTest extends TestCase $attachment = $this->createAttachmentForPage($page); $file = $this->getTestFile('textfile.txt'); - $resp = $this->call('PUT', "{$this->baseEndpoint}/{$attachment->id}", ['name' => 'My updated file'], [], ['file' => $file]); $resp->assertStatus(200); @@ -278,7 +330,7 @@ class AttachmentsApiTest extends TestCase $details = [ 'name' => 'My updated API attachment', - 'link' => 'https://cats.example.com' + 'link' => 'https://cats.example.com', ]; $resp = $this->putJson("{$this->baseEndpoint}/{$attachment->id}", $details); @@ -310,13 +362,14 @@ class AttachmentsApiTest extends TestCase /** @var Attachment $attachment */ $attachment = $page->attachments()->forceCreate(array_merge([ 'uploaded_to' => $page->id, - 'name' => 'test attachment', - 'external' => true, - 'order' => 1, - 'created_by' => $admin->id, - 'updated_by' => $admin->id, - 'path' => 'https://attachment.example.com' + 'name' => 'test attachment', + 'external' => true, + 'order' => 1, + 'created_by' => $admin->id, + 'updated_by' => $admin->id, + 'path' => 'https://attachment.example.com', ], $attributes)); + return $attachment; } @@ -325,6 +378,6 @@ class AttachmentsApiTest extends TestCase */ protected function getTestFile(string $fileName): UploadedFile { - return new UploadedFile(base_path('tests/test-data/test-file.txt'), $fileName, 'text/plain', 55, null, true); + return new UploadedFile(base_path('tests/test-data/test-file.txt'), $fileName, 'text/plain', null, true); } }