diff options
Diffstat (limited to 'apps/federatedfilesharing/lib/Controller/RequestHandlerController.php')
-rw-r--r-- | apps/federatedfilesharing/lib/Controller/RequestHandlerController.php | 322 |
1 files changed, 135 insertions, 187 deletions
diff --git a/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php index c5e1a8b4e7e..7fdd718cbfe 100644 --- a/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php +++ b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php @@ -1,41 +1,24 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Bjoern Schiessle <bjoern@schiessle.org> - * @author Björn Schießle <bjoern@schiessle.org> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace OCA\FederatedFileSharing\Controller; use OCA\FederatedFileSharing\AddressHandler; use OCA\FederatedFileSharing\FederatedShareProvider; use OCA\FederatedFileSharing\Notifications; +use OCP\App\IAppManager; use OCP\AppFramework\Http; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; +use OCP\AppFramework\Http\Attribute\OpenAPI; +use OCP\AppFramework\Http\Attribute\PublicPage; +use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCS\OCSBadRequestException; use OCP\AppFramework\OCS\OCSException; -use OCP\AppFramework\OCS\OCSForbiddenException; use OCP\AppFramework\OCSController; -use OCP\App\IAppManager; use OCP\Constants; use OCP\EventDispatcher\IEventDispatcher; use OCP\Federation\Exceptions\ProviderCouldNotAddShareException; @@ -43,101 +26,67 @@ use OCP\Federation\Exceptions\ProviderDoesNotExistsException; use OCP\Federation\ICloudFederationFactory; use OCP\Federation\ICloudFederationProviderManager; use OCP\Federation\ICloudIdManager; +use OCP\HintException; use OCP\IDBConnection; use OCP\IRequest; use OCP\IUserManager; use OCP\Log\Audit\CriticalActionPerformedEvent; +use OCP\Server; use OCP\Share; use OCP\Share\Exceptions\ShareNotFound; use Psr\Log\LoggerInterface; +#[OpenAPI(scope: OpenAPI::SCOPE_FEDERATION)] class RequestHandlerController extends OCSController { - /** @var FederatedShareProvider */ - private $federatedShareProvider; - - /** @var IDBConnection */ - private $connection; - - /** @var Share\IManager */ - private $shareManager; - - /** @var Notifications */ - private $notifications; - - /** @var AddressHandler */ - private $addressHandler; - - /** @var IUserManager */ - private $userManager; - - /** @var string */ - private $shareTable = 'share'; - - /** @var ICloudIdManager */ - private $cloudIdManager; - - /** @var LoggerInterface */ - private $logger; - - /** @var ICloudFederationFactory */ - private $cloudFederationFactory; - - /** @var ICloudFederationProviderManager */ - private $cloudFederationProviderManager; - - /** @var IEventDispatcher */ - private $eventDispatcher; - - public function __construct(string $appName, - IRequest $request, - FederatedShareProvider $federatedShareProvider, - IDBConnection $connection, - Share\IManager $shareManager, - Notifications $notifications, - AddressHandler $addressHandler, - IUserManager $userManager, - ICloudIdManager $cloudIdManager, - LoggerInterface $logger, - ICloudFederationFactory $cloudFederationFactory, - ICloudFederationProviderManager $cloudFederationProviderManager, - IEventDispatcher $eventDispatcher + public function __construct( + string $appName, + IRequest $request, + private FederatedShareProvider $federatedShareProvider, + private IDBConnection $connection, + private Share\IManager $shareManager, + private Notifications $notifications, + private AddressHandler $addressHandler, + private IUserManager $userManager, + private ICloudIdManager $cloudIdManager, + private LoggerInterface $logger, + private ICloudFederationFactory $cloudFederationFactory, + private ICloudFederationProviderManager $cloudFederationProviderManager, + private IEventDispatcher $eventDispatcher, ) { parent::__construct($appName, $request); - - $this->federatedShareProvider = $federatedShareProvider; - $this->connection = $connection; - $this->shareManager = $shareManager; - $this->notifications = $notifications; - $this->addressHandler = $addressHandler; - $this->userManager = $userManager; - $this->cloudIdManager = $cloudIdManager; - $this->logger = $logger; - $this->cloudFederationFactory = $cloudFederationFactory; - $this->cloudFederationProviderManager = $cloudFederationProviderManager; - $this->eventDispatcher = $eventDispatcher; } /** - * @NoCSRFRequired - * @PublicPage - * * create a new share * - * @return Http\DataResponse + * @param string|null $remote Address of the remote + * @param string|null $token Shared secret between servers + * @param string|null $name Name of the shared resource + * @param string|null $owner Display name of the receiver + * @param string|null $sharedBy Display name of the sender + * @param string|null $shareWith ID of the user that receives the share + * @param int|null $remoteId ID of the remote + * @param string|null $sharedByFederatedId Federated ID of the sender + * @param string|null $ownerFederatedId Federated ID of the receiver + * @return Http\DataResponse<Http::STATUS_OK, list<empty>, array{}> * @throws OCSException + * + * 200: Share created successfully */ - public function createShare() { - $remote = isset($_POST['remote']) ? $_POST['remote'] : null; - $token = isset($_POST['token']) ? $_POST['token'] : null; - $name = isset($_POST['name']) ? $_POST['name'] : null; - $owner = isset($_POST['owner']) ? $_POST['owner'] : null; - $sharedBy = isset($_POST['sharedBy']) ? $_POST['sharedBy'] : null; - $shareWith = isset($_POST['shareWith']) ? $_POST['shareWith'] : null; - $remoteId = isset($_POST['remoteId']) ? (int)$_POST['remoteId'] : null; - $sharedByFederatedId = isset($_POST['sharedByFederatedId']) ? $_POST['sharedByFederatedId'] : null; - $ownerFederatedId = isset($_POST['ownerFederatedId']) ? $_POST['ownerFederatedId'] : null; - + #[NoCSRFRequired] + #[PublicPage] + public function createShare( + ?string $remote = null, + ?string $token = null, + ?string $name = null, + ?string $owner = null, + ?string $sharedBy = null, + ?string $shareWith = null, + ?int $remoteId = null, + ?string $sharedByFederatedId = null, + ?string $ownerFederatedId = null, + ) { if ($ownerFederatedId === null) { $ownerFederatedId = $this->cloudIdManager->getCloudId($owner, $this->cleanupRemote($remote))->getId(); } @@ -165,9 +114,9 @@ class RequestHandlerController extends OCSController { $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file'); $provider->shareReceived($share); if ($sharedByFederatedId === $ownerFederatedId) { - $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('A new federated share with "%s" was created by "%s" and shared with "%s"', [$name, $ownerFederatedId, $shareWith])); + $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('A new federated share with "%s" was created by "%s" and shared with "%s"', [$name, $ownerFederatedId, $shareWith])); } else { - $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('A new federated share with "%s" was shared by "%s" (resource owner is: "%s") and shared with "%s"', [$name, $sharedByFederatedId, $ownerFederatedId, $shareWith])); + $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('A new federated share with "%s" was shared by "%s" (resource owner is: "%s") and shared with "%s"', [$name, $sharedByFederatedId, $ownerFederatedId, $shareWith])); } } catch (ProviderDoesNotExistsException $e) { throw new OCSException('Server does not support federated cloud sharing', 503); @@ -177,32 +126,28 @@ class RequestHandlerController extends OCSController { throw new OCSException('internal server error, was not able to add share from ' . $remote, 500); } - return new Http\DataResponse(); + return new DataResponse(); } /** - * @NoCSRFRequired - * @PublicPage - * * create re-share on behalf of another user * - * @param int $id - * @return Http\DataResponse - * @throws OCSBadRequestException + * @param int $id ID of the share + * @param string|null $token Shared secret between servers + * @param string|null $shareWith ID of the user that receives the share + * @param int|null $remoteId ID of the remote + * @return Http\DataResponse<Http::STATUS_OK, array{token: string, remoteId: string}, array{}> + * @throws OCSBadRequestException Re-sharing is not possible * @throws OCSException - * @throws OCSForbiddenException + * + * 200: Remote share returned */ - public function reShare($id) { - $token = $this->request->getParam('token', null); - $shareWith = $this->request->getParam('shareWith', null); - $permission = (int)$this->request->getParam('permission', null); - $remoteId = (int)$this->request->getParam('remoteId', null); - - if ($id === null || - $token === null || - $shareWith === null || - $permission === null || - $remoteId === null + #[NoCSRFRequired] + #[PublicPage] + public function reShare(int $id, ?string $token = null, ?string $shareWith = null, ?int $remoteId = 0) { + if ($token === null + || $shareWith === null + || $remoteId === null ) { throw new OCSBadRequestException(); } @@ -217,7 +162,7 @@ class RequestHandlerController extends OCSController { try { $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file'); [$newToken, $localId] = $provider->notificationReceived('REQUEST_RESHARE', $id, $notification); - return new Http\DataResponse([ + return new DataResponse([ 'token' => $newToken, 'remoteId' => $localId ]); @@ -234,20 +179,20 @@ class RequestHandlerController extends OCSController { /** - * @NoCSRFRequired - * @PublicPage - * * accept server-to-server share * - * @param int $id - * @return Http\DataResponse + * @param int $id ID of the remote share + * @param string|null $token Shared secret between servers + * @return Http\DataResponse<Http::STATUS_OK, list<empty>, array{}> * @throws OCSException * @throws ShareNotFound - * @throws \OCP\HintException + * @throws HintException + * + * 200: Share accepted successfully */ - public function acceptShare($id) { - $token = isset($_POST['token']) ? $_POST['token'] : null; - + #[NoCSRFRequired] + #[PublicPage] + public function acceptShare(int $id, ?string $token = null) { $notification = [ 'sharedSecret' => $token, 'message' => 'Recipient accept the share' @@ -265,22 +210,22 @@ class RequestHandlerController extends OCSController { $this->logger->debug('internal server error, can not process notification: ' . $e->getMessage(), ['exception' => $e]); } - return new Http\DataResponse(); + return new DataResponse(); } /** - * @NoCSRFRequired - * @PublicPage - * * decline server-to-server share * - * @param int $id - * @return Http\DataResponse + * @param int $id ID of the remote share + * @param string|null $token Shared secret between servers + * @return Http\DataResponse<Http::STATUS_OK, list<empty>, array{}> * @throws OCSException + * + * 200: Share declined successfully */ - public function declineShare($id) { - $token = isset($_POST['token']) ? $_POST['token'] : null; - + #[NoCSRFRequired] + #[PublicPage] + public function declineShare(int $id, ?string $token = null) { $notification = [ 'sharedSecret' => $token, 'message' => 'Recipient declined the share' @@ -298,26 +243,26 @@ class RequestHandlerController extends OCSController { $this->logger->debug('internal server error, can not process notification: ' . $e->getMessage(), ['exception' => $e]); } - return new Http\DataResponse(); + return new DataResponse(); } /** - * @NoCSRFRequired - * @PublicPage - * * remove server-to-server share if it was unshared by the owner * - * @param int $id - * @return Http\DataResponse + * @param int $id ID of the share + * @param string|null $token Shared secret between servers + * @return Http\DataResponse<Http::STATUS_OK, list<empty>, array{}> * @throws OCSException + * + * 200: Share unshared successfully */ - public function unshare($id) { + #[NoCSRFRequired] + #[PublicPage] + public function unshare(int $id, ?string $token = null) { if (!$this->isS2SEnabled()) { throw new OCSException('Server does not support federated cloud sharing', 503); } - $token = isset($_POST['token']) ? $_POST['token'] : null; - try { $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file'); $notification = ['sharedSecret' => $token]; @@ -327,7 +272,7 @@ class RequestHandlerController extends OCSController { $this->logger->debug('processing unshare notification failed: ' . $e->getMessage(), ['exception' => $e]); } - return new Http\DataResponse(); + return new DataResponse(); } private function cleanupRemote($remote) { @@ -338,23 +283,23 @@ class RequestHandlerController extends OCSController { /** - * @NoCSRFRequired - * @PublicPage - * * federated share was revoked, either by the owner or the re-sharer * - * @param int $id - * @return Http\DataResponse - * @throws OCSBadRequestException + * @param int $id ID of the share + * @param string|null $token Shared secret between servers + * @return Http\DataResponse<Http::STATUS_OK, list<empty>, array{}> + * @throws OCSBadRequestException Revoking the share is not possible + * + * 200: Share revoked successfully */ - public function revoke($id) { - $token = $this->request->getParam('token'); - + #[NoCSRFRequired] + #[PublicPage] + public function revoke(int $id, ?string $token = null) { try { $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file'); $notification = ['sharedSecret' => $token]; $provider->notificationReceived('RESHARE_UNDO', $id, $notification); - return new Http\DataResponse(); + return new DataResponse(); } catch (\Exception $e) { throw new OCSBadRequestException(); } @@ -367,7 +312,7 @@ class RequestHandlerController extends OCSController { * @return bool */ private function isS2SEnabled($incoming = false) { - $result = \OCP\Server::get(IAppManager::class)->isEnabledForUser('files_sharing'); + $result = Server::get(IAppManager::class)->isEnabledForUser('files_sharing'); if ($incoming) { $result = $result && $this->federatedShareProvider->isIncomingServer2serverShareEnabled(); @@ -379,18 +324,20 @@ class RequestHandlerController extends OCSController { } /** - * @NoCSRFRequired - * @PublicPage - * * update share information to keep federated re-shares in sync * - * @param int $id - * @return Http\DataResponse - * @throws OCSBadRequestException + * @param int $id ID of the share + * @param string|null $token Shared secret between servers + * @param int|null $permissions New permissions + * @return Http\DataResponse<Http::STATUS_OK, list<empty>, array{}> + * @throws OCSBadRequestException Updating permissions is not possible + * + * 200: Permissions updated successfully */ - public function updatePermissions($id) { - $token = $this->request->getParam('token', null); - $ncPermissions = $this->request->getParam('permissions', null); + #[NoCSRFRequired] + #[PublicPage] + public function updatePermissions(int $id, ?string $token = null, ?int $permissions = null) { + $ncPermissions = $permissions; try { $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file'); @@ -403,7 +350,7 @@ class RequestHandlerController extends OCSController { throw new OCSBadRequestException(); } - return new Http\DataResponse(); + return new DataResponse(); } /** @@ -423,8 +370,8 @@ class RequestHandlerController extends OCSController { $ocmPermissions[] = 'read'; } - if (($ncPermissions & Constants::PERMISSION_CREATE) || - ($ncPermissions & Constants::PERMISSION_UPDATE)) { + if (($ncPermissions & Constants::PERMISSION_CREATE) + || ($ncPermissions & Constants::PERMISSION_UPDATE)) { $ocmPermissions[] = 'write'; } @@ -432,24 +379,25 @@ class RequestHandlerController extends OCSController { } /** - * @NoCSRFRequired - * @PublicPage - * * change the owner of a server-to-server share * - * @param int $id - * @return Http\DataResponse - * @throws \InvalidArgumentException - * @throws OCSException + * @param int $id ID of the share + * @param string|null $token Shared secret between servers + * @param string|null $remote Address of the remote + * @param string|null $remote_id ID of the remote + * @return Http\DataResponse<Http::STATUS_OK, array{remote: string, owner: string}, array{}> + * @throws OCSBadRequestException Moving share is not possible + * + * 200: Share moved successfully */ - public function move($id) { + #[NoCSRFRequired] + #[PublicPage] + public function move(int $id, ?string $token = null, ?string $remote = null, ?string $remote_id = null) { if (!$this->isS2SEnabled()) { throw new OCSException('Server does not support federated cloud sharing', 503); } - $token = $this->request->getParam('token'); - $remote = $this->request->getParam('remote'); - $newRemoteId = $this->request->getParam('remote_id', $id); + $newRemoteId = (string)($remote_id ?? $id); $cloudId = $this->cloudIdManager->resolveCloudId($remote); $qb = $this->connection->getQueryBuilder(); @@ -462,7 +410,7 @@ class RequestHandlerController extends OCSController { $affected = $query->executeStatement(); if ($affected > 0) { - return new Http\DataResponse(['remote' => $cloudId->getRemote(), 'owner' => $cloudId->getUser()]); + return new DataResponse(['remote' => $cloudId->getRemote(), 'owner' => $cloudId->getUser()]); } else { throw new OCSBadRequestException('Share not found or token invalid'); } |