NULL, 'filemime' => NULL, 'filesize' => NULL, 'status' => NULL, 'changed' => NULL, ]; /** * @var \Drupal\user\UserInterface */ protected $author; /** * {@inheritdoc} */ protected function setUpAuthorization($method) { switch ($method) { case 'GET': $this->grantPermissionsToTestedRole(['access content']); break; case 'PATCH': case 'DELETE': // \Drupal\file\FileAccessControlHandler::checkAccess() grants 'update' // and 'delete' access only to the user that owns the file. So there is // no permission to grant: instead, the file owner must be changed from // its default (user 1) to the current user. $this->makeCurrentUserFileOwner(); break; } } /** * {@inheritdoc} */ protected function grantPermissionsToTestedRole(array $permissions) { // testPatch() and testDelete() test the 'bc_entity_resource_permissions' BC // layer; also call makeCurrentUserFileOwner() then. if ($permissions === ['restful patch entity:file'] || $permissions === ['restful delete entity:file']) { $this->makeCurrentUserFileOwner(); } parent::grantPermissionsToTestedRole($permissions); } /** * Makes the current user the file owner. */ protected function makeCurrentUserFileOwner() { $account = static::$auth ? User::load(2) : User::load(0); $this->entity->setOwnerId($account->id()); $this->entity->setOwner($account); $this->entity->save(); } /** * {@inheritdoc} */ protected function createEntity() { $this->author = User::load(1); $file = File::create(); $file->setOwnerId($this->author->id()); $file->setFilename('drupal.txt'); $file->setMimeType('text/plain'); $file->setFileUri('public://drupal.txt'); $file->set('status', FILE_STATUS_PERMANENT); $file->save(); file_put_contents($file->getFileUri(), 'Drupal'); return $file; } /** * {@inheritdoc} */ protected function getExpectedNormalizedEntity() { return [ 'changed' => [ $this->formatExpectedTimestampItemValues($this->entity->getChangedTime()), ], 'created' => [ $this->formatExpectedTimestampItemValues((int) $this->entity->getCreatedTime()), ], 'fid' => [ [ 'value' => 1, ], ], 'filemime' => [ [ 'value' => 'text/plain', ], ], 'filename' => [ [ 'value' => 'drupal.txt', ], ], 'filesize' => [ [ 'value' => (int) $this->entity->getSize(), ], ], 'langcode' => [ [ 'value' => 'en', ], ], 'status' => [ [ 'value' => TRUE, ], ], 'uid' => [ [ 'target_id' => (int) $this->author->id(), 'target_type' => 'user', 'target_uuid' => $this->author->uuid(), 'url' => base_path() . 'user/' . $this->author->id(), ], ], 'uri' => [ [ 'url' => base_path() . $this->siteDirectory . '/files/drupal.txt', 'value' => 'public://drupal.txt', ], ], 'uuid' => [ [ 'value' => $this->entity->uuid(), ], ], ]; } /** * {@inheritdoc} */ protected function getNormalizedPostEntity() { return [ 'uid' => [ [ 'target_id' => $this->author->id(), ], ], 'filename' => [ [ 'value' => 'drupal.txt', ], ], ]; } /** * {@inheritdoc} */ protected function getNormalizedPatchEntity() { return array_diff_key($this->getNormalizedPostEntity(), ['uid' => TRUE]); } /** * {@inheritdoc} */ protected function getExpectedCacheContexts() { return [ 'user.permissions', ]; } /** * {@inheritdoc} */ public function testPost() { // Drupal does not allow creating file entities independently. It allows you // to create file entities that are referenced from another entity (e.g. an // image for a node's image field). // For that purpose, there is the "file_upload" REST resource plugin. // @see \Drupal\file\FileAccessControlHandler::checkCreateAccess() // @see \Drupal\file\Plugin\rest\resource\FileUploadResource $this->markTestSkipped(); } /** * {@inheritdoc} */ protected function getExpectedUnauthorizedAccessMessage($method) { if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { return parent::getExpectedUnauthorizedAccessMessage($method); } if ($method === 'GET') { return "The 'access content' permission is required."; } if ($method === 'PATCH' || $method === 'DELETE') { return 'Only the file owner can update or delete the file entity.'; } return parent::getExpectedUnauthorizedAccessMessage($method); } }