exclude('ClassName', Folder::class) as $file) { /** * @var File $file */ $path = TestAssetStore::getLocalPath($file); Filesystem::makeFolder(dirname($path)); $fh = fopen($path, "w+"); fwrite($fh, str_repeat('x', 1000000)); fclose($fh); // Create variant for each file $this->getAssetStore()->setFromString( str_repeat('y', 100), $file->Filename, $file->Hash, 'variant' ); } } /** * @dataProvider getFilenames */ public function testIsValidFilename($name, $isValid) { $controller = new ProtectedFileController(); $this->assertEquals( $isValid, $controller->isValidFilename($name), "Assert filename \"$name\" is " . $isValid ? "valid" : "invalid" ); } public function getFilenames() { return array( // Valid names array('name.jpg', true), array('parent/name.jpg', true), array('parent/name', true), array('parent\name.jpg', true), array('parent\name', true), array('name', true), // Invalid names array('.invalid/name.jpg', false), array('.invalid\name.jpg', false), array('.htaccess', false), array('test/.htaccess.jpg', false), array('name/.jpg', false), array('test\.htaccess.jpg', false), array('name\.jpg', false) ); } /** * Test that certain requests are denied */ public function testInvalidRequest() { $result = $this->get('assets/.protected/file.jpg'); $this->assertResponseEquals(400, null, $result); } /** * Test that invalid files generate 404 response */ public function testFileNotFound() { $result = $this->get('assets/missing.jpg'); $this->assertResponseEquals(404, null, $result); } /** * Check public access to assets is available at the appropriate time */ public function testAccessControl() { $expectedContent = str_repeat('x', 1000000); $variantContent = str_repeat('y', 100); $result = $this->get('assets/55b443b601/FileTest.txt'); $this->assertResponseEquals(200, $expectedContent, $result); $result = $this->get('assets/55b443b601/FileTest__variant.txt'); $this->assertResponseEquals(200, $variantContent, $result); // Make this file protected $this->getAssetStore()->protect( 'FileTest.txt', '55b443b60176235ef09801153cca4e6da7494a0c' ); // Should now return explicitly denied errors $result = $this->get('assets/55b443b601/FileTest.txt'); $this->assertResponseEquals(403, null, $result); $result = $this->get('assets/55b443b601/FileTest__variant.txt'); $this->assertResponseEquals(403, null, $result); // Other assets remain available $result = $this->get('assets/55b443b601/FileTest.pdf'); $this->assertResponseEquals(200, $expectedContent, $result); $result = $this->get('assets/55b443b601/FileTest__variant.pdf'); $this->assertResponseEquals(200, $variantContent, $result); // granting access will allow access $this->getAssetStore()->grant( 'FileTest.txt', '55b443b60176235ef09801153cca4e6da7494a0c' ); $result = $this->get('assets/55b443b601/FileTest.txt'); $this->assertResponseEquals(200, $expectedContent, $result); $result = $this->get('assets/55b443b601/FileTest__variant.txt'); $this->assertResponseEquals(200, $variantContent, $result); // Revoking access will remove access again $this->getAssetStore()->revoke( 'FileTest.txt', '55b443b60176235ef09801153cca4e6da7494a0c' ); $result = $this->get('assets/55b443b601/FileTest.txt'); $this->assertResponseEquals(403, null, $result); $result = $this->get('assets/55b443b601/FileTest__variant.txt'); $this->assertResponseEquals(403, null, $result); // Moving file back to public store restores access $this->getAssetStore()->publish( 'FileTest.txt', '55b443b60176235ef09801153cca4e6da7494a0c' ); $result = $this->get('assets/55b443b601/FileTest.txt'); $this->assertResponseEquals(200, $expectedContent, $result); $result = $this->get('assets/55b443b601/FileTest__variant.txt'); $this->assertResponseEquals(200, $variantContent, $result); // Deleting the file will make the response 404 $this->getAssetStore()->delete( 'FileTest.txt', '55b443b60176235ef09801153cca4e6da7494a0c' ); $result = $this->get('assets/55b443b601/FileTest.txt'); $this->assertResponseEquals(404, null, $result); $result = $this->get('assets/55b443b601/FileTest__variant.txt'); $this->assertResponseEquals(404, null, $result); } /** * Test that access to folders is not permitted */ public function testFolders() { $result = $this->get('assets/55b443b601'); $this->assertResponseEquals(403, null, $result); $result = $this->get('assets/FileTest-subfolder'); $this->assertResponseEquals(403, null, $result); // Flysystem reports root folder as not present $result = $this->get('assets'); $this->assertResponseEquals(404, null, $result); } /** * @return AssetStore */ protected function getAssetStore() { return Injector::inst()->get('AssetStore'); } /** * Assert that a response matches the given parameters * * @param int $code HTTP code * @param string $body Body expected for 200 responses * @param HTTPResponse $response */ protected function assertResponseEquals($code, $body, HTTPResponse $response) { $this->assertEquals($code, $response->getStatusCode()); if ($code === 200) { $this->assertFalse($response->isError()); $this->assertEquals($body, $response->getBody()); $this->assertEquals('text/plain', $response->getHeader('Content-Type')); } else { $this->assertTrue($response->isError()); } } }