diff --git a/tests/src/Kernel/WopiControllerTest.php b/tests/src/Kernel/WopiControllerTest.php index 4438b51b..7941e430 100644 --- a/tests/src/Kernel/WopiControllerTest.php +++ b/tests/src/Kernel/WopiControllerTest.php @@ -17,7 +17,9 @@ use Drupal\collabora_online\Jwt\JwtTranscoderInterface; use Drupal\file\Entity\File; use Drupal\file\FileInterface; +use Drupal\media\Entity\Media; use Drupal\media\MediaInterface; +use Drupal\user\Entity\User; use Drupal\user\UserInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -68,8 +70,11 @@ protected function setUp(): void { 'jwt', ]); - $this->user = $this->createUser(['access content']); $this->media = $this->createMediaEntity('document'); + $this->user = $this->createUser([ + 'access content', + 'edit any document in collabora', + ]); $fid = $this->media->getSource()->getSourceFieldValue($this->media); $this->file = File::load($fid); @@ -77,21 +82,134 @@ protected function setUp(): void { } /** - * Tests sucessful response for check file info. + * Tests a successful response for check file info. * * @see \Drupal\collabora_online\Controller\WopiController::wopiCheckFileInfo() */ - public function testWopiInfoSucess(): void { - /** @var \Drupal\collabora_online\Jwt\JwtTranscoderInterface $transcoder */ - $transcoder = \Drupal::service(JwtTranscoderInterface::class); - $expire_timestamp = gettimeofday(TRUE) + 1000; + public function testWopiInfoSuccess(): void { + $request = Request::create( + '/cool/wopi/files/' . $this->media->id(), + 'GET', + [ + 'id' => $this->media->id(), + 'action' => 'info', + 'access_token' => $this->getAccessToken(), + ] + ); - $access_token = $transcoder->encode([ - 'fid' => $this->file->id(), - 'uid' => $this->user->id(), - 'wri' => FALSE, - 'exp' => $expire_timestamp, - ], $expire_timestamp); + $mtime = date_create_immutable_from_format('U', (string) $this->file->getChangedTime()); + + $this->assertResponse( + Response::HTTP_OK, + json_encode([ + 'BaseFileName' => $this->file->getFilename(), + 'Size' => $this->file->getSize(), + 'LastModifiedTime' => $mtime->format('c'), + 'UserId' => $this->user->id(), + 'UserFriendlyName' => $this->user->getDisplayName(), + 'UserExtraInfo' => [ + 'mail' => $this->user->getEmail(), + ], + 'UserCanWrite' => FALSE, + 'IsAdminUser' => FALSE, + 'IsAnonymousUser' => FALSE, + ]), + $request + ); + } + + /** + * Tests a successful response for check file info with write operation. + * + * @see \Drupal\collabora_online\Controller\WopiController::wopiCheckFileInfo() + */ + public function testWopiInfoSuccessWrite(): void { + $request = Request::create( + '/cool/wopi/files/' . $this->media->id(), + 'GET', + [ + 'id' => $this->media->id(), + 'action' => 'info', + 'access_token' => $this->getAccessToken(write: TRUE), + ] + ); + + $mtime = date_create_immutable_from_format('U', (string) $this->file->getChangedTime()); + + $this->assertResponse( + Response::HTTP_OK, + json_encode([ + 'BaseFileName' => $this->file->getFilename(), + 'Size' => $this->file->getSize(), + 'LastModifiedTime' => $mtime->format('c'), + 'UserId' => $this->user->id(), + 'UserFriendlyName' => $this->user->getDisplayName(), + 'UserExtraInfo' => [ + 'mail' => $this->user->getEmail(), + ], + 'UserCanWrite' => TRUE, + 'IsAdminUser' => FALSE, + 'IsAnonymousUser' => FALSE, + ]), + $request + ); + } + + /** + * Tests response for check file info with a bad token. + * + * @see \Drupal\collabora_online\Controller\WopiController::wopiCheckFileInfo() + */ + public function testWopiInfoAccessDeniedToken(): void { + $request = Request::create( + '/cool/wopi/files/' . $this->media->id(), + 'GET', + [ + 'id' => $this->media->id(), + 'action' => 'info', + 'access_token' => 'a', + ] + ); + + $this->assertResponse( + Response::HTTP_FORBIDDEN, + 'Authentication failed.', + $request + ); + } + + /** + * Tests response for check file info with a bad MID. + * + * @see \Drupal\collabora_online\Controller\WopiController::wopiCheckFileInfo() + */ + public function testWopiInfoAccessDeniedMedia(): void { + $this->assertNull(Media::load(5)); + + $request = Request::create( + '/cool/wopi/files/5', + 'GET', + [ + 'id' => '5', + 'action' => 'info', + 'access_token' => $this->getAccessToken(), + ] + ); + + $this->assertResponse( + Response::HTTP_FORBIDDEN, + 'Authentication failed.', + $request + ); + } + + /** + * Tests response for check file info with a bad UID. + * + * @see \Drupal\collabora_online\Controller\WopiController::wopiCheckFileInfo() + */ + public function testWopiInfoAccessDeniedUser(): void { + $this->assertNull(User::load(5)); $request = Request::create( '/cool/wopi/files/' . $this->media->id(), @@ -99,30 +217,79 @@ public function testWopiInfoSucess(): void { [ 'id' => $this->media->id(), 'action' => 'info', - 'access_token' => $access_token, + 'access_token' => $this->getAccessToken(uid: 5), ] ); + $this->assertResponse( + Response::HTTP_FORBIDDEN, + 'Authentication failed.', + $request + ); + } + + /** + * Tests response for check file info without permission to edit. + * + * @see \Drupal\collabora_online\Controller\WopiController::wopiCheckFileInfo() + */ + public function testWopiInfoAccessDeniedWrite(): void { + $this->user = $this->createUser(['access content']); + $this->setCurrentUser($this->user); + + $request = Request::create( + '/cool/wopi/files/' . $this->media->id(), + 'GET', + [ + 'id' => $this->media->id(), + 'action' => 'info', + 'access_token' => $this->getAccessToken(write: TRUE), + ] + ); + + $this->assertResponse( + Response::HTTP_FORBIDDEN, + 'Authentication failed.', + $request + ); + } + + /** + * Retrieves an encoded access token. + * + * @param int $fid + * The file id. + * @param int $uid + * The user id. + * @param bool $write + * The write permission. + * + * @return string + * The enconded token. + */ + protected function getAccessToken(?int $fid = NULL, ?int $uid = NULL, bool $write = FALSE): string { + /** @var \Drupal\collabora_online\Jwt\JwtTranscoderInterface $transcoder */ + $transcoder = \Drupal::service(JwtTranscoderInterface::class); + $expire_timestamp = gettimeofday(TRUE) + 1000; + + return $transcoder->encode([ + 'fid' => $fid ?? $this->file->id(), + 'uid' => $uid ?? $this->user->id(), + 'wri' => $write, + 'exp' => $expire_timestamp, + ], $expire_timestamp); + } + + /** + * Asserts status code and content from a request. + */ + protected function assertResponse(int $expected_code, string $expected_content, Request $request): void { /** @var \Symfony\Component\HttpKernel\HttpKernelInterface $kernel */ $kernel = \Drupal::service('http_kernel'); $response = $kernel->handle($request); - $content = json_decode($response->getContent(), TRUE); - $mtime = date_create_immutable_from_format('U', (string) $this->file->getChangedTime()); - $this->assertEquals(Response::HTTP_OK, $response->getStatusCode()); - $this->assertEquals([ - 'BaseFileName' => $this->file->getFilename(), - 'Size' => $this->file->getSize(), - 'LastModifiedTime' => $mtime->format('c'), - 'UserId' => $this->user->id(), - 'UserFriendlyName' => $this->user->getDisplayName(), - 'UserExtraInfo' => [ - 'mail' => $this->user->getEmail(), - ], - 'UserCanWrite' => FALSE, - 'IsAdminUser' => FALSE, - 'IsAnonymousUser' => FALSE, - ], $content); + $this->assertEquals($expected_code, $response->getStatusCode()); + $this->assertEquals($expected_content, $response->getContent()); } }