aboutsummaryrefslogtreecommitdiffstats
path: root/apps/federatedfilesharing/lib
diff options
context:
space:
mode:
Diffstat (limited to 'apps/federatedfilesharing/lib')
-rw-r--r--apps/federatedfilesharing/lib/AddressHandler.php29
-rw-r--r--apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php8
-rw-r--r--apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php33
-rw-r--r--apps/federatedfilesharing/lib/Controller/RequestHandlerController.php162
-rw-r--r--apps/federatedfilesharing/lib/Events/FederatedShareAddedEvent.php8
-rw-r--r--apps/federatedfilesharing/lib/FederatedShareProvider.php258
-rw-r--r--apps/federatedfilesharing/lib/Listeners/LoadAdditionalScriptsListener.php3
-rw-r--r--apps/federatedfilesharing/lib/Migration/Version1011Date20201120125158.php8
-rw-r--r--apps/federatedfilesharing/lib/Notifications.php20
-rw-r--r--apps/federatedfilesharing/lib/Notifier.php19
-rw-r--r--apps/federatedfilesharing/lib/OCM/CloudFederationProviderFiles.php106
-rw-r--r--apps/federatedfilesharing/lib/Settings/Admin.php28
-rw-r--r--apps/federatedfilesharing/lib/Settings/Personal.php29
-rw-r--r--apps/federatedfilesharing/lib/Settings/PersonalSection.php17
-rw-r--r--apps/federatedfilesharing/lib/TokenHandler.php8
15 files changed, 369 insertions, 367 deletions
diff --git a/apps/federatedfilesharing/lib/AddressHandler.php b/apps/federatedfilesharing/lib/AddressHandler.php
index 320f65c2b42..4588e6da288 100644
--- a/apps/federatedfilesharing/lib/AddressHandler.php
+++ b/apps/federatedfilesharing/lib/AddressHandler.php
@@ -11,6 +11,7 @@ use OCP\Federation\ICloudIdManager;
use OCP\HintException;
use OCP\IL10N;
use OCP\IURLGenerator;
+use OCP\Util;
/**
* Class AddressHandler - parse, modify and construct federated sharing addresses
@@ -19,30 +20,18 @@ use OCP\IURLGenerator;
*/
class AddressHandler {
- /** @var IL10N */
- private $l;
-
- /** @var IURLGenerator */
- private $urlGenerator;
-
- /** @var ICloudIdManager */
- private $cloudIdManager;
-
/**
* AddressHandler constructor.
*
* @param IURLGenerator $urlGenerator
- * @param IL10N $il10n
+ * @param IL10N $l
* @param ICloudIdManager $cloudIdManager
*/
public function __construct(
- IURLGenerator $urlGenerator,
- IL10N $il10n,
- ICloudIdManager $cloudIdManager
+ private IURLGenerator $urlGenerator,
+ private IL10N $l,
+ private ICloudIdManager $cloudIdManager,
) {
- $this->l = $il10n;
- $this->urlGenerator = $urlGenerator;
- $this->cloudIdManager = $cloudIdManager;
}
/**
@@ -86,12 +75,12 @@ class AddressHandler {
if (rtrim($normalizedServer1, '/') === rtrim($normalizedServer2, '/')) {
// FIXME this should be a method in the user management instead
- \OCP\Util::emitHook(
+ Util::emitHook(
'\OCA\Files_Sharing\API\Server2Server',
'preLoginNameUsedAsUserName',
['uid' => &$user1]
);
- \OCP\Util::emitHook(
+ Util::emitHook(
'\OCA\Files_Sharing\API\Server2Server',
'preLoginNameUsedAsUserName',
['uid' => &$user2]
@@ -128,8 +117,8 @@ class AddressHandler {
* @return bool
*/
public function urlContainProtocol($url) {
- if (str_starts_with($url, 'https://') ||
- str_starts_with($url, 'http://')) {
+ if (str_starts_with($url, 'https://')
+ || str_starts_with($url, 'http://')) {
return true;
}
diff --git a/apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php b/apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php
index f72209642ba..9d66cd71812 100644
--- a/apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php
+++ b/apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php
@@ -22,7 +22,6 @@ use OCP\BackgroundJob\Job;
*/
class RetryJob extends Job {
private bool $retainJob = true;
- private Notifications $notifications;
/** @var int max number of attempts to send the request */
private int $maxTry = 20;
@@ -30,10 +29,11 @@ class RetryJob extends Job {
/** @var int how much time should be between two tries (10 minutes) */
private int $interval = 600;
- public function __construct(Notifications $notifications,
- ITimeFactory $time) {
+ public function __construct(
+ private Notifications $notifications,
+ ITimeFactory $time,
+ ) {
parent::__construct($time);
- $this->notifications = $notifications;
}
/**
diff --git a/apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php b/apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php
index e34ee77a550..b8d2090713b 100644
--- a/apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php
+++ b/apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -11,7 +12,11 @@ use OCA\FederatedFileSharing\AddressHandler;
use OCA\FederatedFileSharing\FederatedShareProvider;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\Attribute\BruteForceProtection;
+use OCP\AppFramework\Http\Attribute\NoAdminRequired;
+use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
use OCP\AppFramework\Http\Attribute\OpenAPI;
+use OCP\AppFramework\Http\Attribute\PublicPage;
use OCP\AppFramework\Http\JSONResponse;
use OCP\Constants;
use OCP\Federation\ICloudIdManager;
@@ -32,7 +37,6 @@ use Psr\Log\LoggerInterface;
*
* @package OCA\FederatedFileSharing\Controller
*/
-#[OpenAPI(scope: OpenAPI::SCOPE_FEDERATION)]
class MountPublicLinkController extends Controller {
/**
* MountPublicLinkController constructor.
@@ -56,17 +60,18 @@ class MountPublicLinkController extends Controller {
/**
* send federated share to a user of a public link
*
- * @NoCSRFRequired
- * @PublicPage
- * @BruteForceProtection(action=publicLink2FederatedShare)
- *
* @param string $shareWith Username to share with
* @param string $token Token of the share
* @param string $password Password of the share
* @return JSONResponse<Http::STATUS_OK, array{remoteUrl: string}, array{}>|JSONResponse<Http::STATUS_BAD_REQUEST, array{message: string}, array{}>
+ *
* 200: Remote URL returned
* 400: Creating share is not possible
*/
+ #[NoCSRFRequired]
+ #[PublicPage]
+ #[BruteForceProtection(action: 'publicLink2FederatedShare')]
+ #[OpenAPI(scope: OpenAPI::SCOPE_FEDERATION)]
public function createFederatedShare($shareWith, $token, $password = '') {
if (!$this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
return new JSONResponse(
@@ -86,8 +91,8 @@ class MountPublicLinkController extends Controller {
// make sure that user is authenticated in case of a password protected link
$storedPassword = $share->getPassword();
- $authenticated = $this->session->get(PublicAuth::DAV_AUTHENTICATED) === $share->getId() ||
- $this->shareManager->checkPassword($share, $password);
+ $authenticated = $this->session->get(PublicAuth::DAV_AUTHENTICATED) === $share->getId()
+ || $this->shareManager->checkPassword($share, $password);
if (!empty($storedPassword) && !$authenticated) {
$response = new JSONResponse(
['message' => 'No permission to access the share'],
@@ -125,8 +130,6 @@ class MountPublicLinkController extends Controller {
/**
* ask other server to get a federated share
*
- * @NoAdminRequired
- *
* @param string $token
* @param string $remote
* @param string $password
@@ -135,6 +138,7 @@ class MountPublicLinkController extends Controller {
* @param string $name (only for legacy reasons, can be removed with legacyMountPublicLink())
* @return JSONResponse
*/
+ #[NoAdminRequired]
public function askForFederatedShare($token, $remote, $password = '', $owner = '', $ownerDisplayName = '', $name = '') {
// check if server admin allows to mount public links from other servers
if ($this->federatedShareProvider->isIncomingServer2serverShareEnabled() === false) {
@@ -148,12 +152,11 @@ class MountPublicLinkController extends Controller {
try {
$response = $httpClient->post($remote . '/index.php/apps/federatedfilesharing/createFederatedShare',
[
- 'body' =>
- [
- 'token' => $token,
- 'shareWith' => rtrim($cloudId->getId(), '/'),
- 'password' => $password
- ],
+ 'body' => [
+ 'token' => $token,
+ 'shareWith' => rtrim($cloudId->getId(), '/'),
+ 'password' => $password
+ ],
'connect_timeout' => 10,
]
);
diff --git a/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php
index c0fc7123a14..7fdd718cbfe 100644
--- a/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php
+++ b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php
@@ -12,7 +12,10 @@ 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\OCSController;
@@ -23,10 +26,12 @@ 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;
@@ -34,75 +39,25 @@ 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,
+ 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
+ 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
*
* @param string|null $remote Address of the remote
@@ -114,11 +69,13 @@ class RequestHandlerController extends OCSController {
* @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, array<empty>, array{}>
+ * @return Http\DataResponse<Http::STATUS_OK, list<empty>, array{}>
* @throws OCSException
*
* 200: Share created successfully
*/
+ #[NoCSRFRequired]
+ #[PublicPage]
public function createShare(
?string $remote = null,
?string $token = null,
@@ -169,13 +126,10 @@ 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 ID of the share
@@ -188,10 +142,12 @@ class RequestHandlerController extends OCSController {
*
* 200: Remote share returned
*/
+ #[NoCSRFRequired]
+ #[PublicPage]
public function reShare(int $id, ?string $token = null, ?string $shareWith = null, ?int $remoteId = 0) {
- if ($token === null ||
- $shareWith === null ||
- $remoteId === null
+ if ($token === null
+ || $shareWith === null
+ || $remoteId === null
) {
throw new OCSBadRequestException();
}
@@ -206,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
]);
@@ -223,20 +179,19 @@ class RequestHandlerController extends OCSController {
/**
- * @NoCSRFRequired
- * @PublicPage
- *
* accept server-to-server share
*
* @param int $id ID of the remote share
* @param string|null $token Shared secret between servers
- * @return Http\DataResponse<Http::STATUS_OK, array<empty>, array{}>
+ * @return Http\DataResponse<Http::STATUS_OK, list<empty>, array{}>
* @throws OCSException
* @throws ShareNotFound
- * @throws \OCP\HintException
+ * @throws HintException
*
* 200: Share accepted successfully
*/
+ #[NoCSRFRequired]
+ #[PublicPage]
public function acceptShare(int $id, ?string $token = null) {
$notification = [
'sharedSecret' => $token,
@@ -255,22 +210,21 @@ 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 ID of the remote share
* @param string|null $token Shared secret between servers
- * @return Http\DataResponse<Http::STATUS_OK, array<empty>, array{}>
+ * @return Http\DataResponse<Http::STATUS_OK, list<empty>, array{}>
* @throws OCSException
*
* 200: Share declined successfully
*/
+ #[NoCSRFRequired]
+ #[PublicPage]
public function declineShare(int $id, ?string $token = null) {
$notification = [
'sharedSecret' => $token,
@@ -289,22 +243,21 @@ 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 ID of the share
* @param string|null $token Shared secret between servers
- * @return Http\DataResponse<Http::STATUS_OK, array<empty>, array{}>
+ * @return Http\DataResponse<Http::STATUS_OK, list<empty>, array{}>
* @throws OCSException
*
* 200: Share unshared successfully
*/
+ #[NoCSRFRequired]
+ #[PublicPage]
public function unshare(int $id, ?string $token = null) {
if (!$this->isS2SEnabled()) {
throw new OCSException('Server does not support federated cloud sharing', 503);
@@ -319,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) {
@@ -330,24 +283,23 @@ class RequestHandlerController extends OCSController {
/**
- * @NoCSRFRequired
- * @PublicPage
- *
* federated share was revoked, either by the owner or the re-sharer
*
* @param int $id ID of the share
* @param string|null $token Shared secret between servers
- * @return Http\DataResponse<Http::STATUS_OK, array<empty>, array{}>
+ * @return Http\DataResponse<Http::STATUS_OK, list<empty>, array{}>
* @throws OCSBadRequestException Revoking the share is not possible
*
* 200: Share revoked successfully
*/
+ #[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();
}
@@ -360,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();
@@ -372,19 +324,18 @@ class RequestHandlerController extends OCSController {
}
/**
- * @NoCSRFRequired
- * @PublicPage
- *
* update share information to keep federated re-shares in sync
*
* @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, array<empty>, array{}>
+ * @return Http\DataResponse<Http::STATUS_OK, list<empty>, array{}>
* @throws OCSBadRequestException Updating permissions is not possible
*
* 200: Permissions updated successfully
*/
+ #[NoCSRFRequired]
+ #[PublicPage]
public function updatePermissions(int $id, ?string $token = null, ?int $permissions = null) {
$ncPermissions = $permissions;
@@ -399,7 +350,7 @@ class RequestHandlerController extends OCSController {
throw new OCSBadRequestException();
}
- return new Http\DataResponse();
+ return new DataResponse();
}
/**
@@ -419,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';
}
@@ -428,9 +379,6 @@ class RequestHandlerController extends OCSController {
}
/**
- * @NoCSRFRequired
- * @PublicPage
- *
* change the owner of a server-to-server share
*
* @param int $id ID of the share
@@ -442,12 +390,14 @@ class RequestHandlerController extends OCSController {
*
* 200: Share moved successfully
*/
+ #[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);
}
- $newRemoteId = (string) ($remote_id ?? $id);
+ $newRemoteId = (string)($remote_id ?? $id);
$cloudId = $this->cloudIdManager->resolveCloudId($remote);
$qb = $this->connection->getQueryBuilder();
@@ -460,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');
}
diff --git a/apps/federatedfilesharing/lib/Events/FederatedShareAddedEvent.php b/apps/federatedfilesharing/lib/Events/FederatedShareAddedEvent.php
index 7654262a57a..2a79f434b8c 100644
--- a/apps/federatedfilesharing/lib/Events/FederatedShareAddedEvent.php
+++ b/apps/federatedfilesharing/lib/Events/FederatedShareAddedEvent.php
@@ -17,14 +17,12 @@ use OCP\EventDispatcher\Event;
*/
class FederatedShareAddedEvent extends Event {
- /** @var string */
- private $remote;
-
/**
* @since 20.0.0
*/
- public function __construct(string $remote) {
- $this->remote = $remote;
+ public function __construct(
+ private string $remote,
+ ) {
}
/**
diff --git a/apps/federatedfilesharing/lib/FederatedShareProvider.php b/apps/federatedfilesharing/lib/FederatedShareProvider.php
index eee60f06068..8a2c12e0ac8 100644
--- a/apps/federatedfilesharing/lib/FederatedShareProvider.php
+++ b/apps/federatedfilesharing/lib/FederatedShareProvider.php
@@ -17,6 +17,7 @@ use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use OCP\Files\NotFoundException;
+use OCP\HintException;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IL10N;
@@ -25,6 +26,7 @@ use OCP\Share\Exceptions\GenericShareException;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IShare;
use OCP\Share\IShareProvider;
+use OCP\Share\IShareProviderSupportsAllSharesInFolder;
use Psr\Log\LoggerInterface;
/**
@@ -32,7 +34,7 @@ use Psr\Log\LoggerInterface;
*
* @package OCA\FederatedFileSharing
*/
-class FederatedShareProvider implements IShareProvider {
+class FederatedShareProvider implements IShareProvider, IShareProviderSupportsAllSharesInFolder {
public const SHARE_TYPE_REMOTE = 6;
/** @var string */
@@ -86,8 +88,8 @@ class FederatedShareProvider implements IShareProvider {
$shareType = $share->getShareType();
$expirationDate = $share->getExpirationDate();
- if ($shareType === IShare::TYPE_REMOTE_GROUP &&
- !$this->isOutgoingServer2serverGroupShareEnabled()
+ if ($shareType === IShare::TYPE_REMOTE_GROUP
+ && !$this->isOutgoingServer2serverGroupShareEnabled()
) {
$message = 'It is not allowed to send federated group shares from this server.';
$message_t = $this->l->t('It is not allowed to send federated group shares from this server.');
@@ -249,7 +251,8 @@ class FederatedShareProvider implements IShareProvider {
$remote,
$shareWith,
$share->getPermissions(),
- $share->getNode()->getName()
+ $share->getNode()->getName(),
+ $share->getShareType(),
);
return [$token, $remoteId];
@@ -267,7 +270,7 @@ class FederatedShareProvider implements IShareProvider {
$query->select('*')->from($this->externalShareTable)
->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner())))
->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
- $qResult = $query->execute();
+ $qResult = $query->executeQuery();
$result = $qResult->fetchAll();
$qResult->closeCursor();
@@ -303,7 +306,7 @@ class FederatedShareProvider implements IShareProvider {
->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
->setValue('permissions', $qb->createNamedParameter($permissions))
- ->setValue('expiration', $qb->createNamedParameter($expirationDate, IQueryBuilder::PARAM_DATE))
+ ->setValue('expiration', $qb->createNamedParameter($expirationDate, IQueryBuilder::PARAM_DATETIME_MUTABLE))
->setValue('token', $qb->createNamedParameter($token))
->setValue('stime', $qb->createNamedParameter(time()));
@@ -313,7 +316,7 @@ class FederatedShareProvider implements IShareProvider {
*/
$qb->setValue('file_target', $qb->createNamedParameter(''));
- $qb->execute();
+ $qb->executeStatement();
return $qb->getLastInsertId();
}
@@ -329,12 +332,12 @@ class FederatedShareProvider implements IShareProvider {
*/
$qb = $this->dbConnection->getQueryBuilder();
$qb->update('share')
- ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
- ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
- ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
- ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
- ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
- ->execute();
+ ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
+ ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
+ ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
+ ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
+ ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATETIME_MUTABLE))
+ ->executeStatement();
// send the updated permission to the owner/initiator, if they are not the same
if ($share->getShareOwner() !== $share->getSharedBy()) {
@@ -349,7 +352,7 @@ class FederatedShareProvider implements IShareProvider {
*
* @param IShare $share
* @throws ShareNotFound
- * @throws \OCP\HintException
+ * @throws HintException
*/
protected function sendPermissionUpdate(IShare $share) {
$remoteId = $this->getRemoteId($share);
@@ -374,7 +377,7 @@ class FederatedShareProvider implements IShareProvider {
$query->update('share')
->where($query->expr()->eq('id', $query->createNamedParameter($shareId)))
->set('token', $query->createNamedParameter($token))
- ->execute();
+ ->executeStatement();
}
/**
@@ -392,7 +395,7 @@ class FederatedShareProvider implements IShareProvider {
'remote_id' => $query->createNamedParameter($remoteId),
]
);
- $query->execute();
+ $query->executeStatement();
}
/**
@@ -406,7 +409,7 @@ class FederatedShareProvider implements IShareProvider {
$query = $this->dbConnection->getQueryBuilder();
$query->select('remote_id')->from('federated_reshares')
->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
- $result = $query->execute();
+ $result = $query->executeQuery();
$data = $result->fetch();
$result->closeCursor();
@@ -428,13 +431,7 @@ class FederatedShareProvider implements IShareProvider {
return $share;
}
- /**
- * Get all children of this share
- *
- * @param IShare $parent
- * @return IShare[]
- */
- public function getChildren(IShare $parent) {
+ public function getChildren(IShare $parent): array {
$children = [];
$qb = $this->dbConnection->getQueryBuilder();
@@ -444,7 +441,7 @@ class FederatedShareProvider implements IShareProvider {
->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
->orderBy('id');
- $cursor = $qb->execute();
+ $cursor = $qb->executeQuery();
while ($data = $cursor->fetch()) {
$children[] = $this->createShareObject($data);
}
@@ -458,7 +455,7 @@ class FederatedShareProvider implements IShareProvider {
*
* @param IShare $share
* @throws ShareNotFound
- * @throws \OCP\HintException
+ * @throws HintException
*/
public function delete(IShare $share) {
[, $remote] = $this->addressHandler->splitUserRemote($share->getSharedWith());
@@ -485,7 +482,7 @@ class FederatedShareProvider implements IShareProvider {
* @param IShare $share
* @param bool $isOwner the user can either be the owner or the user who re-sahred it
* @throws ShareNotFound
- * @throws \OCP\HintException
+ * @throws HintException
*/
protected function revokeShare($share, $isOwner) {
if ($this->userManager->userExists($share->getShareOwner()) && $this->userManager->userExists($share->getSharedBy())) {
@@ -524,12 +521,12 @@ class FederatedShareProvider implements IShareProvider {
$qb->delete('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)))
->andWhere($qb->expr()->neq('share_type', $qb->createNamedParameter(IShare::TYPE_CIRCLE)));
- $qb->execute();
+ $qb->executeStatement();
$qb = $this->dbConnection->getQueryBuilder();
$qb->delete('federated_reshares')
->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
- $qb->execute();
+ $qb->executeStatement();
}
/**
@@ -549,32 +546,41 @@ class FederatedShareProvider implements IShareProvider {
public function getSharesInFolder($userId, Folder $node, $reshares, $shallow = true) {
if (!$shallow) {
- throw new \Exception("non-shallow getSharesInFolder is no longer supported");
+ throw new \Exception('non-shallow getSharesInFolder is no longer supported');
}
+ return $this->getSharesInFolderInternal($userId, $node, $reshares);
+ }
+
+ public function getAllSharesInFolder(Folder $node): array {
+ return $this->getSharesInFolderInternal(null, $node, null);
+ }
+ /**
+ * @return array<int, list<IShare>>
+ */
+ private function getSharesInFolderInternal(?string $userId, Folder $node, ?bool $reshares): array {
$qb = $this->dbConnection->getQueryBuilder();
$qb->select('*')
->from('share', 's')
- ->andWhere($qb->expr()->orX(
- $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
- $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
- ))
+ ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY)))
->andWhere(
$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE))
);
- /**
- * Reshares for this user are shares where they are the owner.
- */
- if ($reshares === false) {
- $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
- } else {
- $qb->andWhere(
- $qb->expr()->orX(
- $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
- $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
- )
- );
+ if ($userId !== null) {
+ /**
+ * Reshares for this user are shares where they are the owner.
+ */
+ if ($reshares !== true) {
+ $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
+ } else {
+ $qb->andWhere(
+ $qb->expr()->orX(
+ $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
+ $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
+ )
+ );
+ }
}
$qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
@@ -583,7 +589,7 @@ class FederatedShareProvider implements IShareProvider {
$qb->orderBy('id');
- $cursor = $qb->execute();
+ $cursor = $qb->executeQuery();
$shares = [];
while ($data = $cursor->fetch()) {
$shares[$data['fileid']][] = $this->createShareObject($data);
@@ -639,7 +645,7 @@ class FederatedShareProvider implements IShareProvider {
$qb->setFirstResult($offset);
$qb->orderBy('id');
- $cursor = $qb->execute();
+ $cursor = $qb->executeQuery();
$shares = [];
while ($data = $cursor->fetch()) {
$shares[] = $this->createShareObject($data);
@@ -660,7 +666,7 @@ class FederatedShareProvider implements IShareProvider {
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
- $cursor = $qb->execute();
+ $cursor = $qb->executeQuery();
$data = $cursor->fetch();
$cursor->closeCursor();
@@ -680,7 +686,7 @@ class FederatedShareProvider implements IShareProvider {
/**
* Get shares for a given path
*
- * @param \OCP\Files\Node $path
+ * @param Node $path
* @return IShare[]
*/
public function getSharesByPath(Node $path) {
@@ -691,7 +697,7 @@ class FederatedShareProvider implements IShareProvider {
->from('share')
->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
- ->execute();
+ ->executeQuery();
$shares = [];
while ($data = $cursor->fetch()) {
@@ -731,7 +737,7 @@ class FederatedShareProvider implements IShareProvider {
$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
}
- $cursor = $qb->execute();
+ $cursor = $qb->executeQuery();
while ($data = $cursor->fetch()) {
$shares[] = $this->createShareObject($data);
@@ -756,7 +762,7 @@ class FederatedShareProvider implements IShareProvider {
->from('share')
->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
- ->execute();
+ ->executeQuery();
$data = $cursor->fetch();
@@ -787,7 +793,7 @@ class FederatedShareProvider implements IShareProvider {
->from('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
- $cursor = $qb->execute();
+ $cursor = $qb->executeQuery();
$data = $cursor->fetch();
$cursor->closeCursor();
@@ -813,6 +819,7 @@ class FederatedShareProvider implements IShareProvider {
->setPermissions((int)$data['permissions'])
->setTarget($data['file_target'])
->setMailSend((bool)$data['mail_send'])
+ ->setStatus((int)$data['accepted'])
->setToken($data['token']);
$shareTime = new \DateTime();
@@ -850,7 +857,7 @@ class FederatedShareProvider implements IShareProvider {
*
* @param string $userId
* @param int $id
- * @return \OCP\Files\Node
+ * @return Node
* @throws InvalidShare
*/
private function getNode($userId, $id) {
@@ -880,126 +887,151 @@ class FederatedShareProvider implements IShareProvider {
//TODO: probably a good idea to send unshare info to remote servers
$qb = $this->dbConnection->getQueryBuilder();
-
$qb->delete('share')
->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE)))
->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
- ->execute();
+ ->executeStatement();
+
+ $qb = $this->dbConnection->getQueryBuilder();
+ $qb->delete('share_external')
+ ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
+ ->andWhere($qb->expr()->eq('user', $qb->createNamedParameter($uid)))
+ ->executeStatement();
}
- /**
- * This provider does not handle groups
- *
- * @param string $gid
- */
public function groupDeleted($gid) {
- // We don't handle groups here
+ $qb = $this->dbConnection->getQueryBuilder();
+ $qb->select('id')
+ ->from('share_external')
+ ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
+ // This is not a typo, the group ID is really stored in the 'user' column
+ ->andWhere($qb->expr()->eq('user', $qb->createNamedParameter($gid)));
+ $cursor = $qb->executeQuery();
+ $parentShareIds = $cursor->fetchAll(\PDO::FETCH_COLUMN);
+ $cursor->closeCursor();
+ if ($parentShareIds === []) {
+ return;
+ }
+
+ $qb = $this->dbConnection->getQueryBuilder();
+ $parentShareIdsParam = $qb->createNamedParameter($parentShareIds, IQueryBuilder::PARAM_INT_ARRAY);
+ $qb->delete('share_external')
+ ->where($qb->expr()->in('id', $parentShareIdsParam))
+ ->orWhere($qb->expr()->in('parent', $parentShareIdsParam))
+ ->executeStatement();
}
- /**
- * This provider does not handle groups
- *
- * @param string $uid
- * @param string $gid
- */
public function userDeletedFromGroup($uid, $gid) {
- // We don't handle groups here
+ $qb = $this->dbConnection->getQueryBuilder();
+ $qb->select('id')
+ ->from('share_external')
+ ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
+ // This is not a typo, the group ID is really stored in the 'user' column
+ ->andWhere($qb->expr()->eq('user', $qb->createNamedParameter($gid)));
+ $cursor = $qb->executeQuery();
+ $parentShareIds = $cursor->fetchAll(\PDO::FETCH_COLUMN);
+ $cursor->closeCursor();
+ if ($parentShareIds === []) {
+ return;
+ }
+
+ $qb = $this->dbConnection->getQueryBuilder();
+ $parentShareIdsParam = $qb->createNamedParameter($parentShareIds, IQueryBuilder::PARAM_INT_ARRAY);
+ $qb->delete('share_external')
+ ->where($qb->expr()->in('parent', $parentShareIdsParam))
+ ->andWhere($qb->expr()->eq('user', $qb->createNamedParameter($uid)))
+ ->executeStatement();
}
/**
- * check if users from other Nextcloud instances are allowed to mount public links share by this instance
- *
- * @return bool
+ * Check if users from other Nextcloud instances are allowed to mount public links share by this instance
*/
- public function isOutgoingServer2serverShareEnabled() {
+ public function isOutgoingServer2serverShareEnabled(): bool {
if ($this->gsConfig->onlyInternalFederation()) {
return false;
}
$result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
- return ($result === 'yes');
+ return $result === 'yes';
}
/**
- * check if users are allowed to mount public links from other Nextclouds
- *
- * @return bool
+ * Check if users are allowed to mount public links from other Nextclouds
*/
- public function isIncomingServer2serverShareEnabled() {
+ public function isIncomingServer2serverShareEnabled(): bool {
if ($this->gsConfig->onlyInternalFederation()) {
return false;
}
$result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
- return ($result === 'yes');
+ return $result === 'yes';
}
/**
- * check if users from other Nextcloud instances are allowed to send federated group shares
- *
- * @return bool
+ * Check if users from other Nextcloud instances are allowed to send federated group shares
*/
- public function isOutgoingServer2serverGroupShareEnabled() {
+ public function isOutgoingServer2serverGroupShareEnabled(): bool {
if ($this->gsConfig->onlyInternalFederation()) {
return false;
}
$result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no');
- return ($result === 'yes');
+ return $result === 'yes';
}
/**
- * check if users are allowed to receive federated group shares
- *
- * @return bool
+ * Check if users are allowed to receive federated group shares
*/
- public function isIncomingServer2serverGroupShareEnabled() {
+ public function isIncomingServer2serverGroupShareEnabled(): bool {
if ($this->gsConfig->onlyInternalFederation()) {
return false;
}
$result = $this->config->getAppValue('files_sharing', 'incoming_server2server_group_share_enabled', 'no');
- return ($result === 'yes');
+ return $result === 'yes';
}
/**
- * check if federated group sharing is supported, therefore the OCM API need to be enabled
- *
- * @return bool
+ * Check if federated group sharing is supported, therefore the OCM API need to be enabled
*/
- public function isFederatedGroupSharingSupported() {
+ public function isFederatedGroupSharingSupported(): bool {
return $this->cloudFederationProviderManager->isReady();
}
/**
* Check if querying sharees on the lookup server is enabled
- *
- * @return bool
*/
- public function isLookupServerQueriesEnabled() {
+ public function isLookupServerQueriesEnabled(): bool {
// in a global scale setup we should always query the lookup server
if ($this->gsConfig->isGlobalScaleEnabled()) {
return true;
}
- $result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'yes');
- return ($result === 'yes');
+ $result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no') === 'yes';
+ // TODO: Reenable if lookup server is used again
+ // return $result;
+ return false;
}
/**
* Check if it is allowed to publish user specific data to the lookup server
- *
- * @return bool
*/
- public function isLookupServerUploadEnabled() {
+ public function isLookupServerUploadEnabled(): bool {
// in a global scale setup the admin is responsible to keep the lookup server up-to-date
if ($this->gsConfig->isGlobalScaleEnabled()) {
return false;
}
- $result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
- return ($result === 'yes');
+ $result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'no') === 'yes';
+ // TODO: Reenable if lookup server is used again
+ // return $result;
+ return false;
}
/**
- * @inheritdoc
+ * Check if auto accepting incoming shares from trusted servers is enabled
*/
+ public function isFederatedTrustedShareAutoAccept(): bool {
+ $result = $this->config->getAppValue('files_sharing', 'federatedTrustedShareAutoAccept', 'yes');
+ return $result === 'yes';
+ }
+
public function getAccessList($nodes, $currentAccess) {
$ids = [];
foreach ($nodes as $node) {
@@ -1011,11 +1043,8 @@ class FederatedShareProvider implements IShareProvider {
->from('share')
->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE)))
->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
- ->andWhere($qb->expr()->orX(
- $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
- $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
- ));
- $cursor = $qb->execute();
+ ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY)));
+ $cursor = $qb->executeQuery();
if ($currentAccess === false) {
$remote = $cursor->fetch() !== false;
@@ -1041,14 +1070,9 @@ class FederatedShareProvider implements IShareProvider {
$qb->select('*')
->from('share')
- ->where(
- $qb->expr()->orX(
- $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE)),
- $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE_GROUP))
- )
- );
+ ->where($qb->expr()->in('share_type', $qb->createNamedParameter([IShare::TYPE_REMOTE_GROUP, IShare::TYPE_REMOTE], IQueryBuilder::PARAM_INT_ARRAY)));
- $cursor = $qb->execute();
+ $cursor = $qb->executeQuery();
while ($data = $cursor->fetch()) {
try {
$share = $this->createShareObject($data);
diff --git a/apps/federatedfilesharing/lib/Listeners/LoadAdditionalScriptsListener.php b/apps/federatedfilesharing/lib/Listeners/LoadAdditionalScriptsListener.php
index 73f0cd34f3f..34fbd85db5a 100644
--- a/apps/federatedfilesharing/lib/Listeners/LoadAdditionalScriptsListener.php
+++ b/apps/federatedfilesharing/lib/Listeners/LoadAdditionalScriptsListener.php
@@ -14,6 +14,7 @@ use OCP\App\IAppManager;
use OCP\AppFramework\Services\IInitialState;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
+use OCP\Util;
/** @template-implements IEventListener<LoadAdditionalScriptsEvent> */
class LoadAdditionalScriptsListener implements IEventListener {
@@ -34,7 +35,7 @@ class LoadAdditionalScriptsListener implements IEventListener {
if ($this->federatedShareProvider->isIncomingServer2serverShareEnabled()) {
$this->initialState->provideInitialState('notificationsEnabled', $this->appManager->isEnabledForUser('notifications'));
- \OCP\Util::addInitScript('federatedfilesharing', 'external');
+ Util::addInitScript('federatedfilesharing', 'external');
}
}
}
diff --git a/apps/federatedfilesharing/lib/Migration/Version1011Date20201120125158.php b/apps/federatedfilesharing/lib/Migration/Version1011Date20201120125158.php
index 78517e3a297..e78c93ec1a5 100644
--- a/apps/federatedfilesharing/lib/Migration/Version1011Date20201120125158.php
+++ b/apps/federatedfilesharing/lib/Migration/Version1011Date20201120125158.php
@@ -18,11 +18,9 @@ use OCP\Migration\SimpleMigrationStep;
class Version1011Date20201120125158 extends SimpleMigrationStep {
- /** @var IDBConnection */
- private $connection;
-
- public function __construct(IDBConnection $connection) {
- $this->connection = $connection;
+ public function __construct(
+ private IDBConnection $connection,
+ ) {
}
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
diff --git a/apps/federatedfilesharing/lib/Notifications.php b/apps/federatedfilesharing/lib/Notifications.php
index 25900ca420d..613c05613ef 100644
--- a/apps/federatedfilesharing/lib/Notifications.php
+++ b/apps/federatedfilesharing/lib/Notifications.php
@@ -13,6 +13,7 @@ use OCP\BackgroundJob\IJobList;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Federation\ICloudFederationFactory;
use OCP\Federation\ICloudFederationProviderManager;
+use OCP\HintException;
use OCP\Http\Client\IClientService;
use OCP\OCS\IDiscoveryService;
use Psr\Log\LoggerInterface;
@@ -45,7 +46,7 @@ class Notifications {
* @param string $sharedByFederatedId
* @param int $shareType (can be a remote user or group share)
* @return bool
- * @throws \OCP\HintException
+ * @throws HintException
* @throws \OC\ServerNotAvailableException
*/
public function sendRemoteShare($token, $shareWith, $name, $remoteId, $owner, $ownerFederatedId, $sharedBy, $sharedByFederatedId, $shareType) {
@@ -104,15 +105,16 @@ class Notifications {
* @param int $permission
* @param string $filename
* @return array|false
- * @throws \OCP\HintException
+ * @throws HintException
* @throws \OC\ServerNotAvailableException
*/
- public function requestReShare($token, $id, $shareId, $remote, $shareWith, $permission, $filename) {
+ public function requestReShare($token, $id, $shareId, $remote, $shareWith, $permission, $filename, $shareType) {
$fields = [
'shareWith' => $shareWith,
'token' => $token,
'permission' => $permission,
'remoteId' => $shareId,
+ 'shareType' => $shareType,
];
$ocmFields = $fields;
@@ -240,10 +242,10 @@ class Notifications {
$result = $this->tryHttpPostToShareEndpoint(rtrim($remote, '/'), '/' . $remoteId . '/' . $action, $fields, $action);
$status = json_decode($result['result'], true);
- if ($result['success'] &&
- isset($status['ocs']['meta']['statuscode']) &&
- ($status['ocs']['meta']['statuscode'] === 100 ||
- $status['ocs']['meta']['statuscode'] === 200
+ if ($result['success']
+ && isset($status['ocs']['meta']['statuscode'])
+ && ($status['ocs']['meta']['statuscode'] === 100
+ || $status['ocs']['meta']['statuscode'] === 200
)
) {
return true;
@@ -286,7 +288,7 @@ class Notifications {
* @return array
* @throws \Exception
*/
- protected function tryHttpPostToShareEndpoint($remoteDomain, $urlSuffix, array $fields, $action = "share") {
+ protected function tryHttpPostToShareEndpoint($remoteDomain, $urlSuffix, array $fields, $action = 'share') {
if ($this->addressHandler->urlContainProtocol($remoteDomain) === false) {
$remoteDomain = 'https://' . $remoteDomain;
}
@@ -396,7 +398,7 @@ class Notifications {
$fields['remoteId'],
[
'sharedSecret' => $fields['token'],
- 'messgage' => 'file is no longer shared with you'
+ 'message' => 'file is no longer shared with you'
]
);
return $this->federationProviderManager->sendNotification($remoteDomain, $notification);
diff --git a/apps/federatedfilesharing/lib/Notifier.php b/apps/federatedfilesharing/lib/Notifier.php
index 4c4380d0875..10b57c578a2 100644
--- a/apps/federatedfilesharing/lib/Notifier.php
+++ b/apps/federatedfilesharing/lib/Notifier.php
@@ -18,16 +18,8 @@ use OCP\Notification\INotifier;
use OCP\Notification\UnknownNotificationException;
class Notifier implements INotifier {
- /** @var IFactory */
- protected $factory;
- /** @var IManager */
- protected $contactsManager;
- /** @var IURLGenerator */
- protected $url;
/** @var array */
protected $federatedContacts;
- /** @var ICloudIdManager */
- protected $cloudIdManager;
/**
* @param IFactory $factory
@@ -35,11 +27,12 @@ class Notifier implements INotifier {
* @param IURLGenerator $url
* @param ICloudIdManager $cloudIdManager
*/
- public function __construct(IFactory $factory, IManager $contactsManager, IURLGenerator $url, ICloudIdManager $cloudIdManager) {
- $this->factory = $factory;
- $this->contactsManager = $contactsManager;
- $this->url = $url;
- $this->cloudIdManager = $cloudIdManager;
+ public function __construct(
+ protected IFactory $factory,
+ protected IManager $contactsManager,
+ protected IURLGenerator $url,
+ protected ICloudIdManager $cloudIdManager,
+ ) {
}
/**
diff --git a/apps/federatedfilesharing/lib/OCM/CloudFederationProviderFiles.php b/apps/federatedfilesharing/lib/OCM/CloudFederationProviderFiles.php
index 2f41502d4f6..1ce639532e8 100644
--- a/apps/federatedfilesharing/lib/OCM/CloudFederationProviderFiles.php
+++ b/apps/federatedfilesharing/lib/OCM/CloudFederationProviderFiles.php
@@ -1,28 +1,33 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\FederatedFileSharing\OCM;
+use NCU\Federation\ISignedCloudFederationProvider;
use OC\AppFramework\Http;
use OC\Files\Filesystem;
use OCA\FederatedFileSharing\AddressHandler;
use OCA\FederatedFileSharing\FederatedShareProvider;
+use OCA\Federation\TrustedServers;
use OCA\Files_Sharing\Activity\Providers\RemoteShares;
use OCA\Files_Sharing\External\Manager;
+use OCA\GlobalSiteSelector\Service\SlaveService;
use OCP\Activity\IManager as IActivityManager;
use OCP\App\IAppManager;
+use OCP\AppFramework\QueryException;
use OCP\Constants;
use OCP\Federation\Exceptions\ActionNotSupportedException;
use OCP\Federation\Exceptions\AuthenticationFailedException;
use OCP\Federation\Exceptions\BadRequestException;
use OCP\Federation\Exceptions\ProviderCouldNotAddShareException;
use OCP\Federation\ICloudFederationFactory;
-use OCP\Federation\ICloudFederationProvider;
use OCP\Federation\ICloudFederationProviderManager;
use OCP\Federation\ICloudFederationShare;
use OCP\Federation\ICloudIdManager;
+use OCP\Files\IFilenameValidator;
use OCP\Files\NotFoundException;
use OCP\HintException;
use OCP\IConfig;
@@ -34,11 +39,13 @@ use OCP\Notification\IManager as INotificationManager;
use OCP\Server;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager;
+use OCP\Share\IProviderFactory;
use OCP\Share\IShare;
use OCP\Util;
use Psr\Log\LoggerInterface;
+use SensitiveParameter;
-class CloudFederationProviderFiles implements ICloudFederationProvider {
+class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
/**
* CloudFederationProvider constructor.
*/
@@ -59,6 +66,8 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
private IConfig $config,
private Manager $externalShareManager,
private LoggerInterface $logger,
+ private IFilenameValidator $filenameValidator,
+ private readonly IProviderFactory $shareProviderFactory,
) {
}
@@ -76,7 +85,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
* @return string provider specific unique ID of the share
*
* @throws ProviderCouldNotAddShareException
- * @throws \OCP\AppFramework\QueryException
+ * @throws QueryException
* @throws HintException
* @since 14.0.0
*/
@@ -115,7 +124,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
}
if ($remote && $token && $name && $owner && $remoteId && $shareWith) {
- if (!Util::isValidFileName($name)) {
+ if (!$this->filenameValidator->isFilenameValid($name)) {
throw new ProviderCouldNotAddShareException('The mountpoint name contains invalid characters.', '', Http::STATUS_BAD_REQUEST);
}
@@ -142,11 +151,22 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
try {
$this->externalShareManager->addShare($remote, $token, '', $name, $owner, $shareType, false, $shareWith, $remoteId);
- $shareId = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share_external');
+ $shareId = Server::get(IDBConnection::class)->lastInsertId('*PREFIX*share_external');
// get DisplayName about the owner of the share
$ownerDisplayName = $this->getUserDisplayName($ownerFederatedId);
+ $trustedServers = null;
+ if ($this->appManager->isEnabledForAnyone('federation')
+ && class_exists(TrustedServers::class)) {
+ try {
+ $trustedServers = Server::get(TrustedServers::class);
+ } catch (\Throwable $e) {
+ $this->logger->debug('Failed to create TrustedServers', ['exception' => $e]);
+ }
+ }
+
+
if ($shareType === IShare::TYPE_USER) {
$event = $this->activityManager->generateEvent();
$event->setApp('files_sharing')
@@ -154,8 +174,13 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/'), $ownerDisplayName])
->setAffectedUser($shareWith)
->setObject('remote_share', $shareId, $name);
- \OC::$server->getActivityManager()->publish($event);
+ Server::get(IActivityManager::class)->publish($event);
$this->notifyAboutNewShare($shareWith, $shareId, $ownerFederatedId, $sharedByFederatedId, $name, $ownerDisplayName);
+
+ // If auto-accept is enabled, accept the share
+ if ($this->federatedShareProvider->isFederatedTrustedShareAutoAccept() && $trustedServers?->isTrustedServer($remote) === true) {
+ $this->externalShareManager->acceptShare($shareId, $shareWith);
+ }
} else {
$groupMembers = $this->groupManager->get($shareWith)->getUsers();
foreach ($groupMembers as $user) {
@@ -165,10 +190,16 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/'), $ownerDisplayName])
->setAffectedUser($user->getUID())
->setObject('remote_share', $shareId, $name);
- \OC::$server->getActivityManager()->publish($event);
+ Server::get(IActivityManager::class)->publish($event);
$this->notifyAboutNewShare($user->getUID(), $shareId, $ownerFederatedId, $sharedByFederatedId, $name, $ownerDisplayName);
+
+ // If auto-accept is enabled, accept the share
+ if ($this->federatedShareProvider->isFederatedTrustedShareAutoAccept() && $trustedServers?->isTrustedServer($remote) === true) {
+ $this->externalShareManager->acceptShare($shareId, $user->getUID());
+ }
}
}
+
return $shareId;
} catch (\Exception $e) {
$this->logger->error('Server can not add remote share.', [
@@ -278,7 +309,10 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
$this->verifyShare($share, $token);
$this->executeAcceptShare($share);
- if ($share->getShareOwner() !== $share->getSharedBy()) {
+
+ if ($share->getShareOwner() !== $share->getSharedBy()
+ && !$this->userManager->userExists($share->getSharedBy())) {
+ // only if share was initiated from another instance
[, $remote] = $this->addressHandler->splitUserRemote($share->getSharedBy());
$remoteId = $this->federatedShareProvider->getRemoteId($share);
$notification = $this->cloudFederationFactory->getCloudFederationNotification();
@@ -429,7 +463,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
*/
private function unshare($id, array $notification) {
if (!$this->isS2SEnabled(true)) {
- throw new ActionNotSupportedException("incoming shares disabled!");
+ throw new ActionNotSupportedException('incoming shares disabled!');
}
if (!isset($notification['sharedSecret'])) {
@@ -447,7 +481,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
)
);
- $result = $qb->execute();
+ $result = $qb->executeQuery();
$share = $result->fetch();
$result->closeCursor();
@@ -467,13 +501,13 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
)
);
- $qb->execute();
+ $qb->executeStatement();
// delete all child in case of a group share
$qb = $this->connection->getQueryBuilder();
$qb->delete('share_external')
->where($qb->expr()->eq('parent', $qb->createNamedParameter((int)$share['id'])));
- $qb->execute();
+ $qb->executeStatement();
$ownerDisplayName = $this->getUserDisplayName($owner->getId());
@@ -486,7 +520,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
$notification = $this->notificationManager->createNotification();
$notification->setApp('files_sharing')
->setUser($share['user'])
- ->setObject('remote_share', (int)$share['id']);
+ ->setObject('remote_share', (string)$share['id']);
$this->notificationManager->markProcessed($notification);
$event = $this->activityManager->generateEvent();
@@ -495,7 +529,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_UNSHARED, [$owner->getId(), $path, $ownerDisplayName])
->setAffectedUser($user)
->setObject('remote_share', (int)$share['id'], $path);
- \OC::$server->getActivityManager()->publish($event);
+ Server::get(IActivityManager::class)->publish($event);
}
}
@@ -621,7 +655,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
$query->update('share')
->where($query->expr()->eq('id', $query->createNamedParameter($share->getId())))
->set('permissions', $query->createNamedParameter($permissions))
- ->execute();
+ ->executeStatement();
}
@@ -672,8 +706,8 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
*/
protected function verifyShare(IShare $share, $token) {
if (
- $share->getShareType() === IShare::TYPE_REMOTE &&
- $share->getToken() === $token
+ $share->getShareType() === IShare::TYPE_REMOTE
+ && $share->getToken() === $token
) {
return true;
}
@@ -726,13 +760,13 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
public function getUserDisplayName(string $userId): string {
// check if gss is enabled and available
- if (!$this->appManager->isInstalled('globalsiteselector')
+ if (!$this->appManager->isEnabledForAnyone('globalsiteselector')
|| !class_exists('\OCA\GlobalSiteSelector\Service\SlaveService')) {
return '';
}
try {
- $slaveService = Server::get(\OCA\GlobalSiteSelector\Service\SlaveService::class);
+ $slaveService = Server::get(SlaveService::class);
} catch (\Throwable $e) {
Server::get(LoggerInterface::class)->error(
$e->getMessage(),
@@ -743,4 +777,38 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
return $slaveService->getUserDisplayName($this->cloudIdManager->removeProtocolFromUrl($userId), false);
}
+
+ /**
+ * @inheritDoc
+ *
+ * @param string $sharedSecret
+ * @param array $payload
+ * @return string
+ */
+ public function getFederationIdFromSharedSecret(
+ #[SensitiveParameter]
+ string $sharedSecret,
+ array $payload,
+ ): string {
+ $provider = $this->shareProviderFactory->getProviderForType(IShare::TYPE_REMOTE);
+ try {
+ $share = $provider->getShareByToken($sharedSecret);
+ } catch (ShareNotFound) {
+ // Maybe we're dealing with a share federated from another server
+ $share = $this->externalShareManager->getShareByToken($sharedSecret);
+ if ($share === false) {
+ return '';
+ }
+
+ return $share['user'] . '@' . $share['remote'];
+ }
+
+ // if uid_owner is a local account, the request comes from the recipient
+ // if not, request comes from the instance that owns the share and recipient is the re-sharer
+ if ($this->userManager->get($share->getShareOwner()) !== null) {
+ return $share->getSharedWith();
+ } else {
+ return $share->getShareOwner();
+ }
+ }
}
diff --git a/apps/federatedfilesharing/lib/Settings/Admin.php b/apps/federatedfilesharing/lib/Settings/Admin.php
index bb41aede1c8..fc685f952c7 100644
--- a/apps/federatedfilesharing/lib/Settings/Admin.php
+++ b/apps/federatedfilesharing/lib/Settings/Admin.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -14,27 +15,16 @@ use OCP\IURLGenerator;
use OCP\Settings\IDelegatedSettings;
class Admin implements IDelegatedSettings {
- private FederatedShareProvider $fedShareProvider;
- private IConfig $gsConfig;
- private IL10N $l;
- private IURLGenerator $urlGenerator;
- private IInitialState $initialState;
-
/**
* Admin constructor.
*/
public function __construct(
- FederatedShareProvider $fedShareProvider,
- IConfig $globalScaleConfig,
- IL10N $l,
- IURLGenerator $urlGenerator,
- IInitialState $initialState
+ private FederatedShareProvider $fedShareProvider,
+ private IConfig $gsConfig,
+ private IL10N $l,
+ private IURLGenerator $urlGenerator,
+ private IInitialState $initialState,
) {
- $this->fedShareProvider = $fedShareProvider;
- $this->gsConfig = $globalScaleConfig;
- $this->l = $l;
- $this->urlGenerator = $urlGenerator;
- $this->initialState = $initialState;
}
/**
@@ -51,6 +41,7 @@ class Admin implements IDelegatedSettings {
$this->initialState->provideInitialState('incomingServer2serverGroupShareEnabled', $this->fedShareProvider->isIncomingServer2serverGroupShareEnabled());
$this->initialState->provideInitialState('lookupServerEnabled', $this->fedShareProvider->isLookupServerQueriesEnabled());
$this->initialState->provideInitialState('lookupServerUploadEnabled', $this->fedShareProvider->isLookupServerUploadEnabled());
+ $this->initialState->provideInitialState('federatedTrustedShareAutoAccept', $this->fedShareProvider->isFederatedTrustedShareAutoAccept());
return new TemplateResponse('federatedfilesharing', 'settings-admin', [], '');
}
@@ -64,8 +55,8 @@ class Admin implements IDelegatedSettings {
/**
* @return int whether the form should be rather on the top or bottom of
- * the admin section. The forms are arranged in ascending order of the
- * priority values. It is required to return a value between 0 and 100.
+ * the admin section. The forms are arranged in ascending order of the
+ * priority values. It is required to return a value between 0 and 100.
*
* E.g.: 70
*/
@@ -87,6 +78,7 @@ class Admin implements IDelegatedSettings {
'incomingServer2serverGroupShareEnabled',
'lookupServerEnabled',
'lookupServerUploadEnabled',
+ 'federatedTrustedShareAutoAccept',
],
];
}
diff --git a/apps/federatedfilesharing/lib/Settings/Personal.php b/apps/federatedfilesharing/lib/Settings/Personal.php
index 4eee4064740..2889fb77c1f 100644
--- a/apps/federatedfilesharing/lib/Settings/Personal.php
+++ b/apps/federatedfilesharing/lib/Settings/Personal.php
@@ -17,24 +17,13 @@ use OCP\IUserSession;
use OCP\Settings\ISettings;
class Personal implements ISettings {
- private FederatedShareProvider $federatedShareProvider;
- private IUserSession $userSession;
- private Defaults $defaults;
- private IInitialState $initialState;
- private IURLGenerator $urlGenerator;
-
public function __construct(
- FederatedShareProvider $federatedShareProvider,
- IUserSession $userSession,
- Defaults $defaults,
- IInitialState $initialState,
- IURLGenerator $urlGenerator
+ private FederatedShareProvider $federatedShareProvider,
+ private IUserSession $userSession,
+ private Defaults $defaults,
+ private IInitialState $initialState,
+ private IURLGenerator $urlGenerator,
) {
- $this->federatedShareProvider = $federatedShareProvider;
- $this->userSession = $userSession;
- $this->defaults = $defaults;
- $this->initialState = $initialState;
- $this->urlGenerator = $urlGenerator;
}
/**
@@ -60,8 +49,8 @@ class Personal implements ISettings {
* @since 9.1
*/
public function getSection(): ?string {
- if ($this->federatedShareProvider->isIncomingServer2serverShareEnabled() ||
- $this->federatedShareProvider->isIncomingServer2serverGroupShareEnabled()) {
+ if ($this->federatedShareProvider->isIncomingServer2serverShareEnabled()
+ || $this->federatedShareProvider->isIncomingServer2serverGroupShareEnabled()) {
return 'sharing';
}
return null;
@@ -69,8 +58,8 @@ class Personal implements ISettings {
/**
* @return int whether the form should be rather on the top or bottom of
- * the admin section. The forms are arranged in ascending order of the
- * priority values. It is required to return a value between 0 and 100.
+ * the admin section. The forms are arranged in ascending order of the
+ * priority values. It is required to return a value between 0 and 100.
*
* E.g.: 70
* @since 9.1
diff --git a/apps/federatedfilesharing/lib/Settings/PersonalSection.php b/apps/federatedfilesharing/lib/Settings/PersonalSection.php
index 90f1f8ddee0..eea10e39393 100644
--- a/apps/federatedfilesharing/lib/Settings/PersonalSection.php
+++ b/apps/federatedfilesharing/lib/Settings/PersonalSection.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -10,14 +11,10 @@ use OCP\IURLGenerator;
use OCP\Settings\IIconSection;
class PersonalSection implements IIconSection {
- /** @var IURLGenerator */
- private $urlGenerator;
- /** @var IL10N */
- private $l;
-
- public function __construct(IURLGenerator $urlGenerator, IL10N $l) {
- $this->urlGenerator = $urlGenerator;
- $this->l = $l;
+ public function __construct(
+ private IURLGenerator $urlGenerator,
+ private IL10N $l,
+ ) {
}
/**
@@ -55,8 +52,8 @@ class PersonalSection implements IIconSection {
/**
* @return int whether the form should be rather on the top or bottom of
- * the settings navigation. The sections are arranged in ascending order of
- * the priority values. It is required to return a value between 0 and 99.
+ * the settings navigation. The sections are arranged in ascending order of
+ * the priority values. It is required to return a value between 0 and 99.
*
* E.g.: 70
* @since 9.1
diff --git a/apps/federatedfilesharing/lib/TokenHandler.php b/apps/federatedfilesharing/lib/TokenHandler.php
index e0a6d2cbe8c..0151d12f5d9 100644
--- a/apps/federatedfilesharing/lib/TokenHandler.php
+++ b/apps/federatedfilesharing/lib/TokenHandler.php
@@ -17,16 +17,14 @@ use OCP\Security\ISecureRandom;
class TokenHandler {
public const TOKEN_LENGTH = 15;
- /** @var ISecureRandom */
- private $secureRandom;
-
/**
* TokenHandler constructor.
*
* @param ISecureRandom $secureRandom
*/
- public function __construct(ISecureRandom $secureRandom) {
- $this->secureRandom = $secureRandom;
+ public function __construct(
+ private ISecureRandom $secureRandom,
+ ) {
}
/**