Chris@18: NULL, Chris@18: 'filemime' => NULL, Chris@18: 'filesize' => NULL, Chris@18: 'status' => NULL, Chris@18: 'changed' => NULL, Chris@18: ]; Chris@18: Chris@18: /** Chris@18: * The file author. Chris@18: * Chris@18: * @var \Drupal\user\UserInterface Chris@18: */ Chris@18: protected $author; Chris@18: Chris@18: /** Chris@18: * {@inheritdoc} Chris@18: */ Chris@18: protected function setUpAuthorization($method) { Chris@18: switch ($method) { Chris@18: case 'GET': Chris@18: $this->grantPermissionsToTestedRole(['access content']); Chris@18: break; Chris@18: Chris@18: case 'PATCH': Chris@18: case 'DELETE': Chris@18: // \Drupal\file\FileAccessControlHandler::checkAccess() grants 'update' Chris@18: // and 'delete' access only to the user that owns the file. So there is Chris@18: // no permission to grant: instead, the file owner must be changed from Chris@18: // its default (user 1) to the current user. Chris@18: $this->makeCurrentUserFileOwner(); Chris@18: break; Chris@18: } Chris@18: } Chris@18: Chris@18: /** Chris@18: * Makes the current user the file owner. Chris@18: */ Chris@18: protected function makeCurrentUserFileOwner() { Chris@18: $account = User::load(2); Chris@18: $this->entity->setOwnerId($account->id()); Chris@18: $this->entity->setOwner($account); Chris@18: $this->entity->save(); Chris@18: } Chris@18: Chris@18: /** Chris@18: * {@inheritdoc} Chris@18: */ Chris@18: protected function createEntity() { Chris@18: $this->author = User::load(1); Chris@18: Chris@18: $file = File::create(); Chris@18: $file->setOwnerId($this->author->id()); Chris@18: $file->setFilename('drupal.txt'); Chris@18: $file->setMimeType('text/plain'); Chris@18: $file->setFileUri('public://drupal.txt'); Chris@18: $file->set('status', FILE_STATUS_PERMANENT); Chris@18: $file->save(); Chris@18: Chris@18: file_put_contents($file->getFileUri(), 'Drupal'); Chris@18: Chris@18: return $file; Chris@18: } Chris@18: Chris@18: /** Chris@18: * {@inheritdoc} Chris@18: */ Chris@18: protected function createAnotherEntity($key) { Chris@18: /* @var \Drupal\file\FileInterface $duplicate */ Chris@18: $duplicate = parent::createAnotherEntity($key); Chris@18: $duplicate->setFileUri("public://$key.txt"); Chris@18: $duplicate->save(); Chris@18: return $duplicate; Chris@18: } Chris@18: Chris@18: /** Chris@18: * {@inheritdoc} Chris@18: */ Chris@18: protected function getExpectedDocument() { Chris@18: $self_url = Url::fromUri('base:/jsonapi/file/file/' . $this->entity->uuid())->setAbsolute()->toString(TRUE)->getGeneratedUrl(); Chris@18: return [ Chris@18: 'jsonapi' => [ Chris@18: 'meta' => [ Chris@18: 'links' => [ Chris@18: 'self' => ['href' => 'http://jsonapi.org/format/1.0/'], Chris@18: ], Chris@18: ], Chris@18: 'version' => '1.0', Chris@18: ], Chris@18: 'links' => [ Chris@18: 'self' => ['href' => $self_url], Chris@18: ], Chris@18: 'data' => [ Chris@18: 'id' => $this->entity->uuid(), Chris@18: 'type' => 'file--file', Chris@18: 'links' => [ Chris@18: 'self' => ['href' => $self_url], Chris@18: ], Chris@18: 'attributes' => [ Chris@18: 'created' => (new \DateTime())->setTimestamp($this->entity->getCreatedTime())->setTimezone(new \DateTimeZone('UTC'))->format(\DateTime::RFC3339), Chris@18: 'changed' => (new \DateTime())->setTimestamp($this->entity->getChangedTime())->setTimezone(new \DateTimeZone('UTC'))->format(\DateTime::RFC3339), Chris@18: 'filemime' => 'text/plain', Chris@18: 'filename' => 'drupal.txt', Chris@18: 'filesize' => (int) $this->entity->getSize(), Chris@18: 'langcode' => 'en', Chris@18: 'status' => TRUE, Chris@18: 'uri' => [ Chris@18: 'url' => base_path() . $this->siteDirectory . '/files/drupal.txt', Chris@18: 'value' => 'public://drupal.txt', Chris@18: ], Chris@18: 'drupal_internal__fid' => 1, Chris@18: ], Chris@18: 'relationships' => [ Chris@18: 'uid' => [ Chris@18: 'data' => [ Chris@18: 'id' => $this->author->uuid(), Chris@18: 'type' => 'user--user', Chris@18: ], Chris@18: 'links' => [ Chris@18: 'related' => ['href' => $self_url . '/uid'], Chris@18: 'self' => ['href' => $self_url . '/relationships/uid'], Chris@18: ], Chris@18: ], Chris@18: ], Chris@18: ], Chris@18: ]; Chris@18: } Chris@18: Chris@18: /** Chris@18: * {@inheritdoc} Chris@18: */ Chris@18: protected function getPostDocument() { Chris@18: return [ Chris@18: 'data' => [ Chris@18: 'type' => 'file--file', Chris@18: 'attributes' => [ Chris@18: 'filename' => 'drupal.txt', Chris@18: ], Chris@18: ], Chris@18: ]; Chris@18: } Chris@18: Chris@18: /** Chris@18: * {@inheritdoc} Chris@18: */ Chris@18: public function testPostIndividual() { Chris@18: // @todo https://www.drupal.org/node/1927648 Chris@18: $this->markTestSkipped(); Chris@18: } Chris@18: Chris@18: /** Chris@18: * {@inheritdoc} Chris@18: */ Chris@18: protected function getExpectedUnauthorizedAccessMessage($method) { Chris@18: if ($method === 'GET') { Chris@18: return "The 'access content' permission is required."; Chris@18: } Chris@18: if ($method === 'PATCH' || $method === 'DELETE') { Chris@18: return "Only the file owner can update or delete the file entity."; Chris@18: } Chris@18: return parent::getExpectedUnauthorizedAccessMessage($method); Chris@18: } Chris@18: Chris@18: /** Chris@18: * {@inheritdoc} Chris@18: */ Chris@18: public function testCollectionFilterAccess() { Chris@18: $label_field_name = 'filename'; Chris@18: // Verify the expected behavior in the common case: when the file is public. Chris@18: $this->doTestCollectionFilterAccessBasedOnPermissions($label_field_name, 'access content'); Chris@18: Chris@18: $collection_url = Url::fromRoute('jsonapi.entity_test--bar.collection'); Chris@18: $collection_filter_url = $collection_url->setOption('query', ["filter[spotlight.$label_field_name]" => $this->entity->label()]); Chris@18: $request_options = []; Chris@18: $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json'; Chris@18: $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions()); Chris@18: Chris@18: // 1 result because the current user is the file owner, even though the file Chris@18: // is private. Chris@18: $this->entity->setFileUri('private://drupal.txt'); Chris@18: $this->entity->setOwner($this->account); Chris@18: $this->entity->save(); Chris@18: $response = $this->request('GET', $collection_filter_url, $request_options); Chris@18: $doc = Json::decode((string) $response->getBody()); Chris@18: $this->assertCount(1, $doc['data']); Chris@18: Chris@18: // 0 results because the current user is no longer the file owner and the Chris@18: // file is private. Chris@18: $this->entity->setOwner(User::load(0)); Chris@18: $this->entity->save(); Chris@18: $response = $this->request('GET', $collection_filter_url, $request_options); Chris@18: $doc = Json::decode((string) $response->getBody()); Chris@18: $this->assertCount(0, $doc['data']); Chris@18: } Chris@18: Chris@18: }