request = $this->createMock(IRequest::class); $this->logger = $this->createMock(LoggerInterface::class); $this->userManager = $this->createMock(IUserManager::class); $this->groupManager = $this->createMock(IGroupManager::class); $this->urlGenerator = $this->createMock(IURLGenerator::class); $this->cloudFederationProviderManager = $this->createMock(ICloudFederationProviderManager::class); $this->config = $this->createMock(Config::class); $this->eventDispatcher = $this->createMock(IEventDispatcher::class); $this->federatedInviteMapper = $this->createMock(FederatedInviteMapper::class); $this->appConfig = $this->createMock(IAppConfig::class); $this->cloudFederationFactory = $this->createMock(ICloudFederationFactory::class); $this->cloudIdManager = $this->createMock(ICloudIdManager::class); $this->discoveryService = $this->createMock(IOCMDiscoveryService::class); $this->timeFactory = $this->createMock(ITimeFactory::class); $this->requestHandlerController = new RequestHandlerController( 'cloud_federation_api', $this->request, $this->logger, $this->userManager, $this->groupManager, $this->urlGenerator, $this->cloudFederationProviderManager, $this->config, $this->eventDispatcher, $this->federatedInviteMapper, $this->appConfig, $this->cloudFederationFactory, $this->cloudIdManager, $this->discoveryService, $this->timeFactory, ); } public function testInviteAccepted(): void { $token = 'token'; $userId = 'userId'; $invite = new FederatedInvite(); $invite->setCreatedAt(1); $invite->setUserId($userId); $invite->setToken($token); $this->federatedInviteMapper->expects(self::once()) ->method('findByToken') ->with($token) ->willReturn($invite); $this->federatedInviteMapper->expects(self::once()) ->method('update') ->willReturnArgument(0); $user = $this->createMock(IUser::class); $user->method('getUID') ->willReturn($userId); $user->method('getEMailAddress') ->willReturn('email'); $user->method('getDisplayName') ->willReturn('displayName'); $this->userManager->expects(self::once()) ->method('get') ->with($userId) ->willReturn($user); $recipientProvider = 'http://127.0.0.1'; $recipientId = 'remote'; $recipientEmail = 'remote@example.org'; $recipientName = 'Remote Remoteson'; $response = ['userID' => $userId, 'email' => 'email', 'name' => 'displayName']; $json = new JSONResponse($response, Http::STATUS_OK); $this->assertEquals($json, $this->requestHandlerController->inviteAccepted($recipientProvider, $token, $recipientId, $recipientEmail, $recipientName)); } public function testNotificationReceived(): void { $notificationType = 'SHARE_ACCEPTED'; $resourceType = 'file'; $providerId = '1337'; $notification = ['sharedSecret' => 'secret']; $notificationObject = new CloudFederationNotification(); $this->appConfig->method('getValueBool')->willReturn(true); $provider = $this->createMock(ICloudFederationProvider::class); $provider->method('notificationReceived')->willReturn([]); $this->cloudFederationFactory->method('getCloudFederationNotification') ->willReturn($notificationObject); $this->cloudFederationProviderManager->method('getCloudFederationProvider') ->willReturn($provider); $this->eventDispatcher->expects(self::once()) ->method('dispatchTyped') ->with(self::callback( fn ( OCMNotificationReceivedEvent $event) => $event->getNotification() === $notificationObject ) ); $response = $this->requestHandlerController->receiveNotification( $notificationType, $resourceType, $providerId, $notification ); self::assertEquals(Http::STATUS_CREATED, $response->getStatus()); self::assertEquals([ 'notificationType' => $notificationType, 'resourceType' => $resourceType, 'providerId' => $providerId, 'notification' => $notification, ], $notificationObject->getMessage()); } public function testAddShareRejectsProtocolWithoutSharedSecret(): void { // Disable signature verification so we reach the protocol validation. $this->appConfig->method('getValueBool')->willReturn(true); $protocol = [ 'name' => 'multi', 'webdav' => ['requirements' => ['must-exchange-token']], ]; $result = $this->requestHandlerController->addShare( 'bob@https://bob.example.com', 'Jupyter', '', '8', 'alice@alice.example.com', 'alice', 'alice@alice.example.com', 'alice', $protocol, 'user', 'file', ); $this->assertInstanceOf(JSONResponse::class, $result); $this->assertEquals(Http::STATUS_BAD_REQUEST, $result->getStatus()); $this->assertSame('Missing sharedSecret in protocol', $result->getData()['message']); } public function testAddShareAcceptsMultiProtocolSharedSecret(): void { // Disable signature verification so we reach the protocol validation. $this->appConfig->method('getValueBool')->willReturn(true); // No supported share types: the share passes the sharedSecret gate and is // rejected later with 501, proving the multi envelope validated. $this->config->method('getSupportedShareTypes')->willReturn([]); $protocol = [ 'name' => 'multi', 'webdav' => ['sharedSecret' => 'XHRcgrx1X8uZELY8kxApldZtzoreH8Wj', 'requirements' => ['must-exchange-token']], 'webapp' => ['sharedSecret' => 'XHRcgrx1X8uZELY8kxApldZtzoreH8Wj', 'uri' => 'https://app.example/open'], ]; $result = $this->requestHandlerController->addShare( 'bob@https://bob.example.com', 'Jupyter', '', '8', 'alice@alice.example.com', 'alice', 'alice@alice.example.com', 'alice', $protocol, 'user', 'file', ); $this->assertInstanceOf(JSONResponse::class, $result); $this->assertEquals(Http::STATUS_NOT_IMPLEMENTED, $result->getStatus()); $this->assertNotSame('Missing sharedSecret in protocol', $result->getData()['message'] ?? ''); } public function testAddShareRoutesFolderResourceTypeMultiProtocol(): void { // Disable signature verification so we reach the share handling. $this->appConfig->method('getValueBool')->willReturn(true); // The files provider is registered for both 'file' and 'folder'. $this->config->method('getSupportedShareTypes')->with('folder')->willReturn(['user']); $cloudId = $this->createMock(ICloudId::class); $cloudId->method('getUser')->willReturn('bob'); $this->cloudIdManager->method('resolveCloudId')->willReturn($cloudId); $this->userManager->method('userExists')->with('bob')->willReturn(true); $share = $this->createMock(ICloudFederationShare::class); $this->cloudFederationFactory->method('getCloudFederationShare')->willReturn($share); $provider = $this->createMock(ICloudFederationProvider::class); $provider->expects($this->once()) ->method('shareReceived') ->with($share) ->willReturn('share-id-1'); $this->cloudFederationProviderManager->expects($this->once()) ->method('getCloudFederationProvider') ->with('folder') ->willReturn($provider); $recipient = $this->createMock(IUser::class); $recipient->method('getDisplayName')->willReturn('Bob'); $recipient->method('getUID')->willReturn('bob'); $this->userManager->method('get')->with('bob')->willReturn($recipient); $protocol = [ 'name' => 'multi', 'webdav' => ['sharedSecret' => 'XHRcgrx1X8uZELY8kxApldZtzoreH8Wj', 'requirements' => ['must-exchange-token']], 'webapp' => ['sharedSecret' => 'XHRcgrx1X8uZELY8kxApldZtzoreH8Wj', 'uri' => 'https://app.example/open'], ]; $result = $this->requestHandlerController->addShare( 'bob@https://bob.example.com', 'Jupyter', '', '8', 'alice@alice.example.com', 'alice', 'alice@alice.example.com', 'alice', $protocol, 'user', 'folder', ); $this->assertInstanceOf(JSONResponse::class, $result); $this->assertEquals(Http::STATUS_CREATED, $result->getStatus()); $this->assertSame('Bob', $result->getData()['recipientDisplayName']); } }