refactor: Rename some variables in external share's manager

Signed-off-by: Carl Schwan <carl.schwan@nextcloud.com>
This commit is contained in:
Carl Schwan 2025-12-09 11:20:37 +01:00
parent bfb7e7dd8e
commit a011cb7780
No known key found for this signature in database
GPG key ID: 02325448204E452A
12 changed files with 189 additions and 336 deletions

View file

@ -867,7 +867,7 @@ class FederatedShareProvider implements IShareProvider, IShareProviderSupportsAl
$qb = $this->dbConnection->getQueryBuilder();
$qb->delete('share_external')
->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)))
->andWhere($qb->expr()->eq('user', $qb->createNamedParameter($uid)))
->executeStatement();
}

View file

@ -15,12 +15,12 @@ use OCA\FederatedFileSharing\FederatedShareProvider;
use OCA\Federation\TrustedServers;
use OCA\Files_Sharing\Activity\Providers\RemoteShares;
use OCA\Files_Sharing\External\ExternalShare;
use OCA\Files_Sharing\External\ExternalShareMapper;
use OCA\Files_Sharing\External\Manager;
use OCA\GlobalSiteSelector\Service\SlaveService;
use OCA\Polls\Db\Share;
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;
@ -34,8 +34,6 @@ use OCP\Files\IFilenameValidator;
use OCP\Files\NotFoundException;
use OCP\HintException;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IGroup;
use OCP\IGroupManager;
use OCP\IURLGenerator;
use OCP\IUser;
@ -48,52 +46,41 @@ use OCP\Share\IProviderFactory;
use OCP\Share\IShare;
use OCP\Snowflake\IGenerator;
use OCP\Util;
use Override;
use Psr\Log\LoggerInterface;
use SensitiveParameter;
class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
/**
* CloudFederationProvider constructor.
*/
public function __construct(
private IAppManager $appManager,
private FederatedShareProvider $federatedShareProvider,
private AddressHandler $addressHandler,
private IUserManager $userManager,
private IManager $shareManager,
private ICloudIdManager $cloudIdManager,
private IActivityManager $activityManager,
private INotificationManager $notificationManager,
private IURLGenerator $urlGenerator,
private ICloudFederationFactory $cloudFederationFactory,
private ICloudFederationProviderManager $cloudFederationProviderManager,
private IDBConnection $connection,
private IGroupManager $groupManager,
private IConfig $config,
private Manager $externalShareManager,
private LoggerInterface $logger,
private IFilenameValidator $filenameValidator,
private readonly IAppManager $appManager,
private readonly FederatedShareProvider $federatedShareProvider,
private readonly AddressHandler $addressHandler,
private readonly IUserManager $userManager,
private readonly IManager $shareManager,
private readonly ICloudIdManager $cloudIdManager,
private readonly IActivityManager $activityManager,
private readonly INotificationManager $notificationManager,
private readonly IURLGenerator $urlGenerator,
private readonly ICloudFederationFactory $cloudFederationFactory,
private readonly ICloudFederationProviderManager $cloudFederationProviderManager,
private readonly IGroupManager $groupManager,
private readonly IConfig $config,
private readonly Manager $externalShareManager,
private readonly LoggerInterface $logger,
private readonly IFilenameValidator $filenameValidator,
private readonly IProviderFactory $shareProviderFactory,
private readonly SetupManager $setupManager,
private readonly IGenerator $snowflakeGenerator,
private readonly ExternalShareMapper $externalShareMapper,
) {
}
#[Override]
public function getShareType(): string {
return 'file';
}
/**
* share received from another server
*
* @param ICloudFederationShare $share
* @return string provider specific unique ID of the share
*
* @throws ProviderCouldNotAddShareException
* @throws QueryException
* @throws HintException
* @since 14.0.0
*/
#[Override]
public function shareReceived(ICloudFederationShare $share): string {
if (!$this->isS2SEnabled(true)) {
throw new ProviderCouldNotAddShareException('Server does not support federated cloud sharing', '', Http::STATUS_SERVICE_UNAVAILABLE);
@ -132,9 +119,9 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
throw new ProviderCouldNotAddShareException('The mountpoint name contains invalid characters.', '', Http::STATUS_BAD_REQUEST);
}
$userOrGroup = null;
$user = null;
$group = null;
// FIXME this should be a method in the user management instead
if ($shareType === IShare::TYPE_USER) {
$this->logger->debug('shareWith before, ' . $shareWith, ['app' => 'files_sharing']);
Util::emitHook(
@ -144,17 +131,15 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
);
$this->logger->debug('shareWith after, ' . $shareWith, ['app' => 'files_sharing']);
$userOrGroup = $this->userManager->get($shareWith);
if ($userOrGroup === null) {
$user = $this->userManager->get($shareWith);
if ($user === null) {
throw new ProviderCouldNotAddShareException('User does not exists', '', Http::STATUS_BAD_REQUEST);
}
$this->setupManager->setupForUser($userOrGroup);
}
if ($shareType === IShare::TYPE_GROUP) {
$userOrGroup = $this->groupManager->get($shareWith);
if ($userOrGroup === null) {
$this->setupManager->setupForUser($user);
} else {
$group = $this->groupManager->get($shareWith);
if ($group === null) {
throw new ProviderCouldNotAddShareException('Group does not exists', '', Http::STATUS_BAD_REQUEST);
}
}
@ -171,7 +156,7 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
$externalShare->setAccepted(IShare::STATUS_PENDING);
try {
$this->externalShareManager->addShare($externalShare, $userOrGroup);
$this->externalShareManager->addShare($externalShare, $user ?: $group);
// get DisplayName about the owner of the share
$ownerDisplayName = $this->getUserDisplayName($ownerFederatedId);
@ -186,9 +171,7 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
}
}
if ($shareType === IShare::TYPE_USER) {
/** @var IUser $userOrGroup */
$event = $this->activityManager->generateEvent();
$event->setApp('files_sharing')
->setType('remote_share')
@ -200,12 +183,10 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
// If auto-accept is enabled, accept the share
if ($this->federatedShareProvider->isFederatedTrustedShareAutoAccept() && $trustedServers?->isTrustedServer($remote) === true) {
/** @var IUser $userOrGroup */
$this->externalShareManager->acceptShare($externalShare, $userOrGroup);
$this->externalShareManager->acceptShare($externalShare, $user);
}
} else {
/** @var IGroup $userOrGroup */
$groupMembers = $userOrGroup->getUsers();
$groupMembers = $group->getUsers();
foreach ($groupMembers as $user) {
$event = $this->activityManager->generateEvent();
$event->setApp('files_sharing')
@ -236,56 +217,28 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
throw new ProviderCouldNotAddShareException('server can not add remote share, missing parameter', '', HTTP::STATUS_BAD_REQUEST);
}
/**
* notification received from another server
*
* @param string $notificationType (e.g. SHARE_ACCEPTED)
* @param string $providerId id of the share
* @param array $notification payload of the notification
* @return array<string> data send back to the sender
*
* @throws ActionNotSupportedException
* @throws AuthenticationFailedException
* @throws BadRequestException
* @throws HintException
* @since 14.0.0
*/
public function notificationReceived($notificationType, $providerId, array $notification) {
switch ($notificationType) {
case 'SHARE_ACCEPTED':
return $this->shareAccepted($providerId, $notification);
case 'SHARE_DECLINED':
return $this->shareDeclined($providerId, $notification);
case 'SHARE_UNSHARED':
return $this->unshare($providerId, $notification);
case 'REQUEST_RESHARE':
return $this->reshareRequested($providerId, $notification);
case 'RESHARE_UNDO':
return $this->undoReshare($providerId, $notification);
case 'RESHARE_CHANGE_PERMISSION':
return $this->updateResharePermissions($providerId, $notification);
}
throw new BadRequestException([$notificationType]);
#[Override]
public function notificationReceived(string $notificationType, string $providerId, array $notification): array {
return match ($notificationType) {
'SHARE_ACCEPTED' => $this->shareAccepted($providerId, $notification),
'SHARE_DECLINED' => $this->shareDeclined($providerId, $notification),
'SHARE_UNSHARED' => $this->unshare($providerId, $notification),
'REQUEST_RESHARE' => $this->reshareRequested($providerId, $notification),
'RESHARE_UNDO' => $this->undoReshare($providerId, $notification),
'RESHARE_CHANGE_PERMISSION' => $this->updateResharePermissions($providerId, $notification),
default => throw new BadRequestException([$notificationType]),
};
}
/**
* map OCM share type (strings) to Nextcloud internal share types (integer)
*
* @param string $shareType
* @return int
* Map OCM share type (strings) to Nextcloud internal share types (integer)
* @return IShare::TYPE_GROUP|IShare::TYPE_USER
*/
private function mapShareTypeToNextcloud($shareType) {
$result = IShare::TYPE_USER;
if ($shareType === 'group') {
$result = IShare::TYPE_GROUP;
}
return $result;
private function mapShareTypeToNextcloud(string $shareType): int {
return $shareType === 'group' ? IShare::TYPE_GROUP : IShare::TYPE_USER;
}
private function notifyAboutNewShare($shareWith, string $shareId, $ownerFederatedId, $sharedByFederatedId, string $name, string $displayName): void {
private function notifyAboutNewShare(string $shareWith, string $shareId, $ownerFederatedId, $sharedByFederatedId, string $name, string $displayName): void {
$notification = $this->notificationManager->createNotification();
$notification->setApp('files_sharing')
->setUser($shareWith)
@ -309,15 +262,14 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
/**
* process notification that the recipient accepted a share
*
* @param string $id
* @param array $notification
* @param array{sharedSecret?: string} $notification
* @return array<string>
* @throws ActionNotSupportedException
* @throws AuthenticationFailedException
* @throws BadRequestException
* @throws HintException
*/
private function shareAccepted($id, array $notification) {
private function shareAccepted(string $id, array $notification): array {
if (!$this->isS2SEnabled()) {
throw new ActionNotSupportedException('Server does not support federated cloud sharing');
}
@ -356,21 +308,22 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
}
/**
* @param IShare $share
* @throws ShareNotFound
*/
protected function executeAcceptShare(IShare $share) {
protected function executeAcceptShare(IShare $share): void {
$user = $this->getCorrectUser($share);
try {
$fileId = (int)$share->getNode()->getId();
[$file, $link] = $this->getFile($this->getCorrectUid($share), $fileId);
} catch (\Exception $e) {
$fileId = $share->getNode()->getId();
[$file, $link] = $this->getFile($user, $fileId);
} catch (\Exception) {
throw new ShareNotFound();
}
$event = $this->activityManager->generateEvent();
$event->setApp('files_sharing')
->setType('remote_share')
->setAffectedUser($this->getCorrectUid($share))
->setAffectedUser($user->getUID())
->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_ACCEPTED, [$share->getSharedWith(), [$fileId => $file]])
->setObject('files', $fileId, $file)
->setLink($link);
@ -380,8 +333,7 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
/**
* process notification that the recipient declined a share
*
* @param string $id
* @param array $notification
* @param array{sharedSecret?: string} $notification
* @return array<string>
* @throws ActionNotSupportedException
* @throws AuthenticationFailedException
@ -390,7 +342,7 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
* @throws HintException
*
*/
protected function shareDeclined($id, array $notification) {
protected function shareDeclined(string $id, array $notification): array {
if (!$this->isS2SEnabled()) {
throw new ActionNotSupportedException('Server does not support federated cloud sharing');
}
@ -417,7 +369,6 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
'sharedSecret' => $token,
'message' => 'Recipient declined the re-share'
]
);
$this->cloudFederationProviderManager->sendNotification($remote, $notification);
}
@ -430,23 +381,24 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
/**
* delete declined share and create a activity
*
* @param IShare $share
* @throws ShareNotFound
*/
protected function executeDeclineShare(IShare $share) {
protected function executeDeclineShare(IShare $share): void {
$this->federatedShareProvider->removeShareFromTable($share);
$user = $this->getCorrectUser($share);
try {
$fileId = (int)$share->getNode()->getId();
[$file, $link] = $this->getFile($this->getCorrectUid($share), $fileId);
} catch (\Exception $e) {
$fileId = $share->getNode()->getId();
[$file, $link] = $this->getFile($user, $fileId);
} catch (\Exception) {
throw new ShareNotFound();
}
$event = $this->activityManager->generateEvent();
$event->setApp('files_sharing')
->setType('remote_share')
->setAffectedUser($this->getCorrectUid($share))
->setAffectedUser($user->getUID())
->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_DECLINED, [$share->getSharedWith(), [$fileId => $file]])
->setObject('files', $fileId, $file)
->setLink($link);
@ -456,13 +408,12 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
/**
* received the notification that the owner unshared a file from you
*
* @param string $id
* @param array $notification
* @param array{sharedSecret?: string} $notification
* @return array<string>
* @throws AuthenticationFailedException
* @throws BadRequestException
*/
private function undoReshare($id, array $notification) {
private function undoReshare(string $id, array $notification): array {
if (!isset($notification['sharedSecret'])) {
throw new BadRequestException(['sharedSecret']);
}
@ -478,13 +429,12 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
/**
* unshare file from self
*
* @param string $id
* @param array $notification
* @param array{sharedSecret?: string} $notification
* @return array<string>
* @throws ActionNotSupportedException
* @throws BadRequestException
*/
private function unshare($id, array $notification) {
private function unshare(string $id, array $notification): array {
if (!$this->isS2SEnabled(true)) {
throw new ActionNotSupportedException('incoming shares disabled!');
}
@ -494,56 +444,29 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
}
$token = $notification['sharedSecret'];
$qb = $this->connection->getQueryBuilder();
$qb->select('*')
->from('share_external')
->where(
$qb->expr()->andX(
$qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
$qb->expr()->eq('share_token', $qb->createNamedParameter($token))
)
);
$share = $this->externalShareMapper->getShareByRemoteIdAndToken($id, $token);
$result = $qb->executeQuery();
$share = $result->fetchAssociative();
$result->closeCursor();
if ($token && $id && $share !== null) {
$remote = $this->cleanupRemote($share->getRemote());
if ($token && $id && !empty($share)) {
$remote = $this->cleanupRemote($share['remote']);
$owner = $this->cloudIdManager->getCloudId($share->getOwner(), $remote);
$mountpoint = $share->getMountpoint();
$user = $share->getUser();
$owner = $this->cloudIdManager->getCloudId($share['owner'], $remote);
$mountpoint = $share['mountpoint'];
$user = $share['user'];
$qb = $this->connection->getQueryBuilder();
$qb->delete('share_external')
->where(
$qb->expr()->andX(
$qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
$qb->expr()->eq('share_token', $qb->createNamedParameter($token))
)
);
$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->executeStatement();
$this->externalShareMapper->delete($share);
$ownerDisplayName = $this->getUserDisplayName($owner->getId());
if ((int)$share['share_type'] === IShare::TYPE_USER) {
if ($share['accepted']) {
if ($share->getShareType() === IShare::TYPE_USER) {
if ($share->getAccepted()) {
$path = trim($mountpoint, '/');
} else {
$path = trim($share['name'], '/');
$path = trim($share->getName(), '/');
}
$notification = $this->notificationManager->createNotification();
$notification->setApp('files_sharing')
->setUser($share['user'])
->setObject('remote_share', (string)$share['id']);
->setUser($share->getUser())
->setObject('remote_share', $share->getId());
$this->notificationManager->markProcessed($notification);
$event = $this->activityManager->generateEvent();
@ -551,7 +474,7 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
->setType('remote_share')
->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_UNSHARED, [$owner->getId(), $path, $ownerDisplayName])
->setAffectedUser($user)
->setObject('remote_share', (int)$share['id'], $path);
->setObject('remote_share', $share->getId(), $path);
Server::get(IActivityManager::class)->publish($event);
}
}
@ -559,7 +482,7 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
return [];
}
private function cleanupRemote($remote) {
private function cleanupRemote(string $remote): string {
$remote = substr($remote, strpos($remote, '://') + 3);
return rtrim($remote, '/');
@ -568,15 +491,14 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
/**
* recipient of a share request to re-share the file with another user
*
* @param string $id
* @param array $notification
* @param array{sharedSecret?: string, shareWith?: string, senderId?: string} $notification
* @return array<string>
* @throws AuthenticationFailedException
* @throws BadRequestException
* @throws ProviderCouldNotAddShareException
* @throws ShareNotFound
*/
protected function reshareRequested($id, array $notification) {
protected function reshareRequested(string $id, array $notification) {
if (!isset($notification['sharedSecret'])) {
throw new BadRequestException(['sharedSecret']);
}
@ -626,71 +548,22 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
}
/**
* update permission of a re-share so that the share dialog shows the right
* Update permission of a re-share so that the share dialog shows the right
* permission if the owner or the sender changes the permission
*
* @param string $id
* @param array $notification
* @return array<string>
* @return string[]
* @throws AuthenticationFailedException
* @throws BadRequestException
*/
protected function updateResharePermissions($id, array $notification) {
protected function updateResharePermissions(string $id, array $notification): array {
throw new HintException('Updating reshares not allowed');
}
/**
* translate OCM Permissions to Nextcloud permissions
*
* @param array $ocmPermissions
* @return int
* @throws BadRequestException
* @return list{?string, string} with internal path of the file and a absolute link to it
*/
protected function ocmPermissions2ncPermissions(array $ocmPermissions) {
$ncPermissions = 0;
foreach ($ocmPermissions as $permission) {
switch (strtolower($permission)) {
case 'read':
$ncPermissions += Constants::PERMISSION_READ;
break;
case 'write':
$ncPermissions += Constants::PERMISSION_CREATE + Constants::PERMISSION_UPDATE;
break;
case 'share':
$ncPermissions += Constants::PERMISSION_SHARE;
break;
default:
throw new BadRequestException(['permission']);
}
}
return $ncPermissions;
}
/**
* update permissions in database
*
* @param IShare $share
* @param int $permissions
*/
protected function updatePermissionsInDatabase(IShare $share, $permissions) {
$query = $this->connection->getQueryBuilder();
$query->update('share')
->where($query->expr()->eq('id', $query->createNamedParameter($share->getId())))
->set('permissions', $query->createNamedParameter($permissions))
->executeStatement();
}
/**
* get file
*
* @param string $user
* @param int $fileSource
* @return array with internal path of the file and a absolute link to it
*/
private function getFile($user, $fileSource) {
\OC_Util::setupFS($user);
private function getFile(IUser $user, int $fileSource): array {
$this->setupManager->setupForUser($user);
try {
$file = Filesystem::getPath($fileSource);
@ -704,30 +577,26 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
}
/**
* check if we are the initiator or the owner of a re-share and return the correct UID
*
* @param IShare $share
* @return string
* Check if we are the initiator or the owner of a re-share and return the correct UID
*/
protected function getCorrectUid(IShare $share) {
if ($this->userManager->userExists($share->getShareOwner())) {
return $share->getShareOwner();
protected function getCorrectUser(IShare $share): IUser {
if ($user = $this->userManager->get($share->getShareOwner())) {
return $user;
}
return $share->getSharedBy();
$user = $this->userManager->get($share->getSharedBy());
if ($user === null) {
throw new \RuntimeException('Neither the share owner or the share initiator exist');
}
return $user;
}
/**
* check if we got the right share
*
* @param IShare $share
* @param string $token
* @return bool
* @throws AuthenticationFailedException
*/
protected function verifyShare(IShare $share, $token) {
protected function verifyShare(IShare $share, string $token): bool {
if (
$share->getShareType() === IShare::TYPE_REMOTE
&& $share->getToken() === $token
@ -751,12 +620,9 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
/**
* check if server-to-server sharing is enabled
*
* @param bool $incoming
* @return bool
* Check if server-to-server sharing is enabled
*/
private function isS2SEnabled($incoming = false) {
private function isS2SEnabled(bool $incoming = false): bool {
$result = $this->appManager->isEnabledForUser('files_sharing');
if ($incoming) {
@ -768,19 +634,11 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
return $result;
}
/**
* get the supported share types, e.g. "user", "group", etc.
*
* @return array
*
* @since 14.0.0
*/
public function getSupportedShareTypes() {
#[Override]
public function getSupportedShareTypes(): array {
return ['user', 'group'];
}
public function getUserDisplayName(string $userId): string {
// check if gss is enabled and available
if (!$this->appManager->isEnabledForAnyone('globalsiteselector')
@ -801,13 +659,7 @@ class CloudFederationProviderFiles implements ISignedCloudFederationProvider {
return $slaveService->getUserDisplayName($this->cloudIdManager->removeProtocolFromUrl($userId), false);
}
/**
* @inheritDoc
*
* @param string $sharedSecret
* @param array $payload
* @return string
*/
#[Override]
public function getFederationIdFromSharedSecret(
#[SensitiveParameter]
string $sharedSecret,

View file

@ -7,7 +7,6 @@
*/
namespace OCA\Files_Sharing\Command;
use OCA\Files_Sharing\External\ExternalShareMapper;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Federation\ICloudIdManager;
use OCP\IDBConnection;

View file

@ -86,8 +86,8 @@ class ExternalShare extends Entity implements \JsonSerializable {
$this->setter('name', [$name]);
}
public function setUserOrGroup(IUser|IGroup|null $userOrGroup): void {
$this->setUser($userOrGroup instanceof IGroup ? $userOrGroup->getGID() : $userOrGroup->getUID());
public function setShareWith(IUser|IGroup $shareWith): void {
$this->setUser($shareWith instanceof IGroup ? $shareWith->getGID() : $shareWith->getUID());
}
/**

View file

@ -11,6 +11,7 @@ declare(strict_types=1);
namespace OCA\Files_Sharing\External;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\Entity;
use OCP\AppFramework\Db\QBMapper;
use OCP\DB\Exception;
use OCP\DB\QueryBuilder\IQueryBuilder;
@ -19,6 +20,7 @@ use OCP\IGroup;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\Share\IShare;
use Override;
/**
* @template-extends QBMapper<ExternalShare>
@ -214,4 +216,37 @@ class ExternalShareMapper extends QBMapper {
$qb->delete('share_external')
->executeStatement();
}
#[Override]
public function delete(Entity $entity): ExternalShare {
/** @var ExternalShare $share */
$share = $entity;
$qb = $this->db->getQueryBuilder();
$qb->delete(self::TABLE_NAME)
// delete the share itself
->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
// delete all child in case of a group share
->orWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
->executeStatement();
return $share;
}
public function getShareByRemoteIdAndToken(string $id, mixed $token): ?ExternalShare {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from(self::TABLE_NAME)
->where(
$qb->expr()->andX(
$qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
$qb->expr()->eq('share_token', $qb->createNamedParameter($token))
)
);
try {
return $this->findEntity($qb);
} catch (Exception) {
return null;
}
}
}

View file

@ -69,26 +69,26 @@ class Manager {
* @throws NotPermittedException
* @throws NoUserException
*/
public function addShare(ExternalShare $shareExternal, IUser|IGroup|null $userOrGroup = null): ?Mount {
$userOrGroup = $userOrGroup ?? $this->user;
public function addShare(ExternalShare $externalShare, IUser|IGroup|null $shareWith = null): ?Mount {
$shareWith = $shareWith ?? $this->user;
if ($shareExternal->getAccepted() !== IShare::STATUS_ACCEPTED) {
if ($externalShare->getAccepted() !== IShare::STATUS_ACCEPTED) {
// To avoid conflicts with the mount point generation later,
// we only use a temporary mount point name here. The real
// mount point name will be generated when accepting the share,
// using the original share item name.
$tmpMountPointName = '{{TemporaryMountPointName#' . $shareExternal->getName() . '}}';
$shareExternal->setMountpoint($tmpMountPointName);
$shareExternal->setUserOrGroup($userOrGroup);
$tmpMountPointName = '{{TemporaryMountPointName#' . $externalShare->getName() . '}}';
$externalShare->setMountpoint($tmpMountPointName);
$externalShare->setShareWith($shareWith);
$i = 1;
while (true) {
try {
$this->externalShareMapper->insert($shareExternal);
$this->externalShareMapper->insert($externalShare);
break;
} catch (Exception $e) {
if ($e->getReason() === Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
$shareExternal->setMountpoint($tmpMountPointName . '-' . $i);
$externalShare->setMountpoint($tmpMountPointName . '-' . $i);
$i++;
} else {
throw $e;
@ -99,22 +99,22 @@ class Manager {
return null;
}
$user = $userOrGroup instanceof IUser ? $userOrGroup : $this->user;
$user = $shareWith instanceof IUser ? $shareWith : $this->user;
$userFolder = $this->rootFolder->getUserFolder($user->getUID());
$mountPoint = $userFolder->getNonExistingName($shareExternal->getName());
$mountPoint = $userFolder->getNonExistingName($externalShare->getName());
$mountPoint = Filesystem::normalizePath('/' . $mountPoint);
$shareExternal->setMountpoint($mountPoint);
$shareExternal->setUserOrGroup($user);
$this->externalShareMapper->insert($shareExternal);
$externalShare->setMountpoint($mountPoint);
$externalShare->setShareWith($user);
$this->externalShareMapper->insert($externalShare);
$options = [
'remote' => $shareExternal->getRemote(),
'token' => $shareExternal->getShareToken(),
'password' => $shareExternal->getPassword(),
'mountpoint' => $shareExternal->getMountpoint(),
'owner' => $shareExternal->getOwner(),
'remote' => $externalShare->getRemote(),
'token' => $externalShare->getShareToken(),
'password' => $externalShare->getPassword(),
'mountpoint' => $externalShare->getMountpoint(),
'owner' => $externalShare->getOwner(),
];
return $this->mountShare($options, $user);
}
@ -168,7 +168,7 @@ class Manager {
public function getShareByToken(string $token): ExternalShare|false {
try {
return $this->externalShareMapper->getShareByToken($token);
} catch (DoesNotExistException $e) {
} catch (DoesNotExistException) {
return false;
}
}
@ -184,7 +184,7 @@ class Manager {
} else {
try {
$subShare = $this->externalShareMapper->getUserShare($externalShare, $user);
} catch (DoesNotExistException $e) {
} catch (DoesNotExistException) {
$subShare = new ExternalShare();
$subShare->setId($this->snowflakeGenerator->nextId());
$subShare->setRemote($externalShare->getRemote());

View file

@ -10,23 +10,17 @@ namespace OCA\Files_Sharing\External;
use OC\Files\Mount\MountPoint;
use OC\Files\Mount\MoveableMount;
use OC\Files\Storage\Storage;
use OC\Files\Storage\StorageFactory;
use OCA\Files_Sharing\ISharedMountPoint;
use Override;
class Mount extends MountPoint implements MoveableMount, ISharedMountPoint {
/**
* @param string|Storage $storage
* @param string $mountpoint
* @param array $options
* @param \OCA\Files_Sharing\External\Manager $manager
* @param \OC\Files\Storage\StorageFactory $loader
*/
public function __construct(
$storage,
$mountpoint,
$options,
protected $manager,
$loader = null,
string|Storage $storage,
string $mountpoint,
array $options,
protected Manager $manager,
?StorageFactory $loader = null,
) {
parent::__construct($storage, $mountpoint, $options, $loader, null, null, MountProvider::class);
}
@ -50,12 +44,7 @@ class Mount extends MountPoint implements MoveableMount, ISharedMountPoint {
return $this->manager->removeShare($this->mountPoint);
}
/**
* Get the type of mount point, used to distinguish things like shares and external storage
* in the web interface
*
* @return string
*/
#[Override]
public function getMountType(): string {
return 'shared';
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@ -7,18 +9,20 @@
*/
namespace OCA\Files_Sharing\External;
use OCA\Files_Sharing\External\Storage as ExternalShareStorage;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Federation\ICloudIdManager;
use OCP\Files\Config\IMountProvider;
use OCP\Files\Storage\IStorageFactory;
use OCP\Http\Client\IClientService;
use OCP\ICertificateManager;
use OCP\IDBConnection;
use OCP\IUser;
use OCP\Server;
use OCP\Share\IShare;
class MountProvider implements IMountProvider {
public const STORAGE = '\OCA\Files_Sharing\External\Storage';
public const STORAGE = ExternalShareStorage::class;
/**
* @var callable
@ -26,33 +30,32 @@ class MountProvider implements IMountProvider {
private $managerProvider;
/**
* @param IDBConnection $connection
* @param callable $managerProvider due to setup order we need a callable that return the manager instead of the manager itself
* @param ICloudIdManager $cloudIdManager
* @param callable $managerProvider due to set up order we need a callable that return the manager instead of the manager itself
*/
public function __construct(
private IDBConnection $connection,
private readonly IDBConnection $connection,
callable $managerProvider,
private ICloudIdManager $cloudIdManager,
private readonly ICloudIdManager $cloudIdManager,
) {
$this->managerProvider = $managerProvider;
}
public function getMount(IUser $user, $data, IStorageFactory $storageFactory) {
private function getMount(IUser $user, array $data, IStorageFactory $storageFactory): Mount {
$managerProvider = $this->managerProvider;
$manager = $managerProvider();
$data['manager'] = $manager;
$mountPoint = '/' . $user->getUID() . '/files/' . ltrim($data['mountpoint'], '/');
$data['mountpoint'] = $mountPoint;
$data['cloudId'] = $this->cloudIdManager->getCloudId($data['owner'], $data['remote']);
$data['certificateManager'] = \OC::$server->getCertificateManager();
$data['certificateManager'] = Server::get(ICertificateManager::class);
$data['HttpClientService'] = Server::get(IClientService::class);
return new Mount(self::STORAGE, $mountPoint, $data, $manager, $storageFactory);
}
public function getMountsForUser(IUser $user, IStorageFactory $loader) {
public function getMountsForUser(IUser $user, IStorageFactory $loader): array {
$qb = $this->connection->getQueryBuilder();
$qb->select('remote', 'share_token', 'password', 'mountpoint', 'owner')
$qb->select('id', 'remote', 'share_token', 'password', 'mountpoint', 'owner')
->from('share_external')
->where($qb->expr()->eq('user', $qb->createNamedParameter($user->getUID())))
->andWhere($qb->expr()->eq('accepted', $qb->createNamedParameter(IShare::STATUS_ACCEPTED, IQueryBuilder::PARAM_INT)));

View file

@ -991,7 +991,7 @@ class ShareByMailProvider extends DefaultShareProvider implements IShareProvider
*/
protected function createShareObject(array $data): IShare {
$share = new Share($this->rootFolder, $this->userManager);
$share->setId((int)$data['id'])
$share->setId($data['id'])
->setShareType((int)$data['share_type'])
->setPermissions((int)$data['permissions'])
->setTarget($data['file_target'])

View file

@ -1286,9 +1286,6 @@
</InvalidReturnType>
</file>
<file src="apps/federatedfilesharing/lib/OCM/CloudFederationProviderFiles.php">
<DeprecatedClass>
<code><![CDATA[\OC_Util::setupFS($user)]]></code>
</DeprecatedClass>
<DeprecatedMethod>
<code><![CDATA[Util::emitHook(
'\OCA\Files_Sharing\API\Server2Server',
@ -1299,12 +1296,6 @@
<code><![CDATA[sendNotification]]></code>
<code><![CDATA[sendNotification]]></code>
</DeprecatedMethod>
<InvalidArgument>
<code><![CDATA[$id]]></code>
<code><![CDATA[$id]]></code>
<code><![CDATA[$id]]></code>
<code><![CDATA[$id]]></code>
</InvalidArgument>
</file>
<file src="apps/federation/lib/DbHandler.php">
<LessSpecificReturnStatement>
@ -2538,12 +2529,6 @@
<code><![CDATA[getAppValue]]></code>
</DeprecatedMethod>
</file>
<file src="apps/sharebymail/lib/ShareByMailProvider.php">
<InvalidArgument>
<code><![CDATA[$share->getId()]]></code>
<code><![CDATA[(int)$data['id']]]></code>
</InvalidArgument>
</file>
<file src="apps/systemtags/lib/Activity/Listener.php">
<DeprecatedConstant>
<code><![CDATA[ManagerEvent::EVENT_CREATE]]></code>
@ -4251,17 +4236,7 @@
<code><![CDATA[$this->dbprettyname]]></code>
</UndefinedThisPropertyFetch>
</file>
<file src="lib/private/Share20/DefaultShareProvider.php">
<InvalidArgument>
<code><![CDATA[$share->getId()]]></code>
<code><![CDATA[$share->getId()]]></code>
<code><![CDATA[(int)$data['id']]]></code>
</InvalidArgument>
</file>
<file src="lib/private/Share20/Manager.php">
<InvalidArgument>
<code><![CDATA[$id]]></code>
</InvalidArgument>
<UndefinedClass>
<code><![CDATA[\OCA\Circles\Api\v1\Circles]]></code>
</UndefinedClass>

View file

@ -989,7 +989,7 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv
*/
private function createShare($data) {
$share = new Share($this->rootFolder, $this->userManager);
$share->setId((int)$data['id'])
$share->setId($data['id'])
->setShareType((int)$data['share_type'])
->setPermissions((int)$data['permissions'])
->setTarget($data['file_target'])

View file

@ -117,7 +117,7 @@ interface IShareProvider {
/**
* Get share by id
*
* @param int $id
* @param string $id
* @param string|null $recipientId
* @return \OCP\Share\IShare
* @throws ShareNotFound