diff --git a/apps/cloud_federation_api/appinfo/routes.php b/apps/cloud_federation_api/appinfo/routes.php index cd681ae98e7f2..9dcffd0aa3489 100644 --- a/apps/cloud_federation_api/appinfo/routes.php +++ b/apps/cloud_federation_api/appinfo/routes.php @@ -20,12 +20,6 @@ 'verb' => 'POST', 'root' => '/ocm', ], - [ - 'name' => 'RequestHandler#inviteAccepted', - 'url' => '/invite-accepted', - 'verb' => 'POST', - 'root' => '/ocm', - ], // needs to be kept at the bottom of the list [ diff --git a/apps/cloud_federation_api/lib/AppInfo/Application.php b/apps/cloud_federation_api/lib/AppInfo/Application.php index e34b2f2dc3dbb..7081de70369b3 100644 --- a/apps/cloud_federation_api/lib/AppInfo/Application.php +++ b/apps/cloud_federation_api/lib/AppInfo/Application.php @@ -22,7 +22,6 @@ public function __construct() { } public function register(IRegistrationContext $context): void { - $context->registerCapability(Capabilities::class); } public function boot(IBootContext $context): void { diff --git a/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php b/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php index bfccb2fe20eaf..fcd78de81cf4b 100644 --- a/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php +++ b/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php @@ -67,8 +67,6 @@ public function __construct( private IURLGenerator $urlGenerator, private ICloudFederationProviderManager $cloudFederationProviderManager, private Config $config, - private IEventDispatcher $dispatcher, - private FederatedInviteMapper $federatedInviteMapper, private readonly AddressHandler $addressHandler, private readonly IAppConfig $appConfig, private ICloudFederationFactory $factory, @@ -225,101 +223,6 @@ public function addShare($shareWith, $name, $description, $providerId, $owner, $ return new JSONResponse($responseData, Http::STATUS_CREATED); } - /** - * Inform the sender that an invitation was accepted to start sharing - * - * Inform about an accepted invitation so the user on the sender provider's side - * can initiate the OCM share creation. To protect the identity of the parties, - * for shares created following an OCM invitation, the user id MAY be hashed, - * and recipients implementing the OCM invitation workflow MAY refuse to process - * shares coming from unknown parties. - * @link https://cs3org.github.io/OCM-API/docs.html?branch=v1.1.0&repo=OCM-API&user=cs3org#/paths/~1invite-accepted/post - * - * @param string $recipientProvider The address of the recipent's provider - * @param string $token The token used for the invitation - * @param string $userID The userID of the recipient at the recipient's provider - * @param string $email The email address of the recipient - * @param string $name The display name of the recipient - * - * @return JSONResponse|JSONResponse - * - * Note: Not implementing 404 Invitation token does not exist, instead using 400 - * 200: Invitation accepted - * 400: Invalid token - * 403: Invitation token does not exist - * 409: User is already known by the OCM provider - */ - #[PublicPage] - #[NoCSRFRequired] - #[BruteForceProtection(action: 'inviteAccepted')] - public function inviteAccepted(string $recipientProvider, string $token, string $userID, string $email, string $name): JSONResponse { - $this->logger->debug('Processing share invitation for ' . $userID . ' with token ' . $token . ' and email ' . $email . ' and name ' . $name); - - $updated = $this->timeFactory->getTime(); - - if ($token === '') { - $response = new JSONResponse(['message' => 'Invalid or non existing token', 'error' => true], Http::STATUS_BAD_REQUEST); - $response->throttle(); - return $response; - } - - try { - $invitation = $this->federatedInviteMapper->findByToken($token); - } catch (DoesNotExistException) { - $response = ['message' => 'Invalid or non existing token', 'error' => true]; - $status = Http::STATUS_BAD_REQUEST; - $response = new JSONResponse($response, $status); - $response->throttle(); - return $response; - } - - if ($invitation->isAccepted() === true) { - $response = ['message' => 'Invite already accepted', 'error' => true]; - $status = Http::STATUS_CONFLICT; - return new JSONResponse($response, $status); - } - - if ($invitation->getExpiredAt() !== null && $updated > $invitation->getExpiredAt()) { - $response = ['message' => 'Invitation expired', 'error' => true]; - $status = Http::STATUS_BAD_REQUEST; - return new JSONResponse($response, $status); - } - $localUser = $this->userManager->get($invitation->getUserId()); - if ($localUser === null) { - $response = ['message' => 'Invalid or non existing token', 'error' => true]; - $status = Http::STATUS_BAD_REQUEST; - $response = new JSONResponse($response, $status); - $response->throttle(); - return $response; - } - - $sharedFromEmail = $localUser->getEMailAddress(); - if ($sharedFromEmail === null) { - $response = ['message' => 'Invalid or non existing token', 'error' => true]; - $status = Http::STATUS_BAD_REQUEST; - $response = new JSONResponse($response, $status); - $response->throttle(); - return $response; - } - $sharedFromDisplayName = $localUser->getDisplayName(); - - $response = ['userID' => $localUser->getUID(), 'email' => $sharedFromEmail, 'name' => $sharedFromDisplayName]; - $status = Http::STATUS_OK; - - $invitation->setAccepted(true); - $invitation->setRecipientEmail($email); - $invitation->setRecipientName($name); - $invitation->setRecipientProvider($recipientProvider); - $invitation->setRecipientUserId($userID); - $invitation->setAcceptedAt($updated); - $invitation = $this->federatedInviteMapper->update($invitation); - - $event = new FederatedInviteAcceptedEvent($invitation); - $this->dispatcher->dispatchTyped($event); - - return new JSONResponse($response, $status); - } - /** * Send a notification about an existing share * diff --git a/apps/cloud_federation_api/lib/Db/FederatedInvite.php b/apps/cloud_federation_api/lib/Db/FederatedInvite.php deleted file mode 100644 index b2447ff4e23ce..0000000000000 --- a/apps/cloud_federation_api/lib/Db/FederatedInvite.php +++ /dev/null @@ -1,62 +0,0 @@ -addType('accepted', Types::BOOLEAN); - $this->addType('acceptedAt', Types::BIGINT); - $this->addType('createdAt', Types::BIGINT); - $this->addType('expiredAt', Types::BIGINT); - $this->addType('recipientEmail', Types::STRING); - $this->addType('recipientName', Types::STRING); - $this->addType('recipientProvider', Types::STRING); - $this->addType('recipientUserId', Types::STRING); - $this->addType('token', Types::STRING); - $this->addType('userId', Types::STRING); - } -} diff --git a/apps/cloud_federation_api/lib/Db/FederatedInviteMapper.php b/apps/cloud_federation_api/lib/Db/FederatedInviteMapper.php deleted file mode 100644 index 5feb08b2c7f52..0000000000000 --- a/apps/cloud_federation_api/lib/Db/FederatedInviteMapper.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -class FederatedInviteMapper extends QBMapper { - public const TABLE_NAME = 'federated_invites'; - - public function __construct(IDBConnection $db) { - parent::__construct($db, self::TABLE_NAME); - } - - public function findByToken(string $token): FederatedInvite { - $qb = $this->db->getQueryBuilder(); - $qb->select('*') - ->from('federated_invites') - ->where($qb->expr()->eq('token', $qb->createNamedParameter($token))); - return $this->findEntity($qb); - } - -} diff --git a/apps/cloud_federation_api/lib/Events/FederatedInviteAcceptedEvent.php b/apps/cloud_federation_api/lib/Events/FederatedInviteAcceptedEvent.php deleted file mode 100644 index c4d079d083ea9..0000000000000 --- a/apps/cloud_federation_api/lib/Events/FederatedInviteAcceptedEvent.php +++ /dev/null @@ -1,24 +0,0 @@ -invitation; - } -} diff --git a/apps/cloud_federation_api/tests/RequestHandlerControllerTest.php b/apps/cloud_federation_api/tests/RequestHandlerControllerTest.php deleted file mode 100644 index 04cabbd234c25..0000000000000 --- a/apps/cloud_federation_api/tests/RequestHandlerControllerTest.php +++ /dev/null @@ -1,137 +0,0 @@ -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->addressHandler = $this->createMock(AddressHandler::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->signatureManager = $this->createMock(ISignatureManager::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->addressHandler, - $this->appConfig, - $this->cloudFederationFactory, - $this->cloudIdManager, - $this->discoveryService, - $this->signatureManager, - $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)); - } -} diff --git a/lib/private/OCM/OCMDiscoveryService.php b/lib/private/OCM/OCMDiscoveryService.php index 17a84c12d5007..896c59d3e3dca 100644 --- a/lib/private/OCM/OCMDiscoveryService.php +++ b/lib/private/OCM/OCMDiscoveryService.php @@ -200,13 +200,7 @@ public function getLocalOCMProvider(bool $fullDetails = true): IOCMProvider { $provider->setEnabled(true); $provider->setApiVersion(self::API_VERSION); $provider->setEndPoint(substr($url, 0, $pos)); - $provider->setCapabilities(['invite-accepted', 'notifications', 'shares']); - - // The inviteAcceptDialog is available from the contacts app, if this config value is set - $inviteAcceptDialog = $this->appConfig->getValueString('core', ConfigLexicon::OCM_INVITE_ACCEPT_DIALOG); - if ($inviteAcceptDialog !== '') { - $provider->setInviteAcceptDialog($this->urlGenerator->linkToRouteAbsolute($inviteAcceptDialog)); - } + $provider->setCapabilities(['notifications', 'shares']); $resource = $provider->createNewResourceType(); $resource->setName('file') diff --git a/lib/public/OCM/Events/LocalOCMDiscoveryEvent.php b/lib/public/OCM/Events/LocalOCMDiscoveryEvent.php index a6ef943145b17..7c2ef6e9a5147 100644 --- a/lib/public/OCM/Events/LocalOCMDiscoveryEvent.php +++ b/lib/public/OCM/Events/LocalOCMDiscoveryEvent.php @@ -54,4 +54,15 @@ public function registerResourceType(string $name, array $shareTypes, array $pro ->setProtocols($protocols); $this->provider->addResourceType($resourceType); } + + /** + * Returns the ocm provider. + * + * @return IOCMProvider + * + * @since 33.0.0 + */ + public function getProvider(): IOCMProvider { + return $this->provider; + } }