diff --git a/lib/Controller/ShareController.php b/lib/Controller/ShareController.php index 388552d1b8..140941e94a 100644 --- a/lib/Controller/ShareController.php +++ b/lib/Controller/ShareController.php @@ -11,7 +11,6 @@ use OCA\Tables\Middleware\Attribute\RequirePermission; use OCA\Tables\Service\ShareService; use OCA\Tables\Service\ValueObject\ShareCreate; -use OCA\Tables\Service\ValueObject\ShareToken; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\DataResponse; @@ -90,15 +89,12 @@ public function create( bool $permissionDelete = false, bool $permissionManage = false, int $displayMode = Application::NAV_ENTRY_MODE_ALL, - ?string $password = null, - ?string $shareToken = null, ): DataResponse { - $shareTokenObject = $shareToken !== null ? new ShareToken($shareToken) : null; $dto = new ShareCreate( $nodeId, $nodeType, $receiver, $receiverType, $permissionRead, $permissionCreate, $permissionUpdate, $permissionDelete, $permissionManage, $displayMode, - $password, $shareTokenObject, + null, null, ); return $this->handleError(function () use ($dto) { diff --git a/lib/Middleware/ShareControlMiddleware.php b/lib/Middleware/ShareControlMiddleware.php index cddc945888..c1d0a04e62 100644 --- a/lib/Middleware/ShareControlMiddleware.php +++ b/lib/Middleware/ShareControlMiddleware.php @@ -22,6 +22,7 @@ use OCP\AppFramework\PublicShareController; use OCP\IRequest; use OCP\ISession; +use OCP\Share\IManager as ShareManager; use ReflectionMethod; class ShareControlMiddleware extends Middleware { @@ -31,6 +32,7 @@ public function __construct( private readonly IRequest $request, private readonly ShareService $shareService, private readonly ISession $session, + private readonly ShareManager $shareManager, ) { } @@ -72,11 +74,29 @@ private function assertIsAccessible(string $tokenInput): void { /** * @throws NotFoundError * @throws InvalidArgumentException + * @throws PermissionError */ public function assertShareTokenIsValidAndExisting(string $tokenInput): void { $shareToken = new ShareToken($tokenInput); $this->share = $this->shareService->findByToken($shareToken); $this->shareService->assertPublicShareAccessible($this->share); + $this->assertPublicLinkSharingAllowedForShareSender(); + } + + /** + * if public link token is already issued, prevent them from working after admin disables + * + * @throws PermissionError + */ + private function assertPublicLinkSharingAllowedForShareSender(): void { + if (!$this->shareManager->shareApiAllowLinks()) { + throw new PermissionError('Public link sharing is disabled by your administrator.'); + } + + $sender = $this->share->getSender(); + if ($sender !== null && $this->shareManager->sharingDisabledForUser($sender)) { + throw new PermissionError('Sharing is restricted by your administrator for your account.'); + } } public function afterException($controller, $methodName, \Exception $exception): DataResponse { diff --git a/lib/Service/ShareService.php b/lib/Service/ShareService.php index 2438e1c6f7..c7b46ca711 100644 --- a/lib/Service/ShareService.php +++ b/lib/Service/ShareService.php @@ -177,14 +177,7 @@ public function assertPublicShareAccessible(Share $share): void { * @throws PermissionError */ public function createLinkShare(Table|View $node, ?string $password = null): Share { - // check admin sharing policy for this user (allowed/excluded sharing groups) - if ($this->shareManager->sharingDisabledForUser($this->userId)) { - throw new PermissionError('Sharing is restricted by your administrator for your account.'); - } - // check global admin setting for public link sharing - if (!$this->shareManager->shareApiAllowLinks()) { - throw new PermissionError('Public link sharing is disabled by your administrator.'); - } + $this->assertPublicLinkSharingAllowed(); for ($i = 0; $i < 3; $i++) { // there is the theoretical chance, that an existing share token would be re-used, @@ -230,6 +223,18 @@ protected function generateShareToken(): ShareToken { return new ShareToken($shareToken); } + /** + * @throws PermissionError + */ + private function assertPublicLinkSharingAllowed(): void { + if ($this->shareManager->sharingDisabledForUser($this->userId)) { + throw new PermissionError('Sharing is restricted by your administrator for your account.'); + } + if (!$this->shareManager->shareApiAllowLinks()) { + throw new PermissionError('Public link sharing is disabled by your administrator.'); + } + } + /** * @param string|null $userId * @return array Indexed by view id @@ -359,6 +364,9 @@ private function buildBaseShare( if ($receiverType === ShareReceiverType::GROUP && !$this->shareManager->allowGroupSharing()) { throw new PermissionError('Group sharing is disabled by your administrator.'); } + if ($receiverType === ShareReceiverType::LINK) { + $this->assertPublicLinkSharingAllowed(); + } $this->enforceGroupMembersOnlyPolicy($this->userId, $receiverType, $receiver); $time = new DateTime(); diff --git a/tests/unit/Service/ShareServiceTest.php b/tests/unit/Service/ShareServiceTest.php index 348bd89013..addc8270a7 100644 --- a/tests/unit/Service/ShareServiceTest.php +++ b/tests/unit/Service/ShareServiceTest.php @@ -12,6 +12,7 @@ use OCA\Tables\Db\ContextNavigationMapper; use OCA\Tables\Db\Share; use OCA\Tables\Db\ShareMapper; +use OCA\Tables\Db\Table; use OCA\Tables\Db\TableMapper; use OCA\Tables\Db\ViewMapper; use OCA\Tables\Errors\PermissionError; @@ -21,6 +22,7 @@ use OCA\Tables\Service\PermissionsService; use OCA\Tables\Service\ShareService; use OCA\Tables\Service\ValueObject\ShareCreate; +use OCA\Tables\Service\ValueObject\ShareToken; use OCP\IDBConnection; use OCP\IUser; use OCP\IUserManager; @@ -145,4 +147,46 @@ public function testAssertPublicShareAccessibleThrowsWhenSenderCannotShare(): vo $this->expectException(PermissionError::class); $this->shareService->assertPublicShareAccessible($this->publicShare); } + + public function testCreateLinkShareThrowsWhenPublicLinksDisabled(): void { + $this->shareManager->method('sharingDisabledForUser')->willReturn(false); + $this->shareManager->method('shareApiAllowLinks')->willReturn(false); + + $this->mapper->expects($this->never())->method('insert'); + + $this->expectException(PermissionError::class); + $this->expectExceptionMessage('Public link sharing is disabled by your administrator.'); + + $table = new Table(); + $table->setId(1); + $this->shareService->createLinkShare($table); + } + + public function testCreateThrowsWhenPublicLinksDisabledForGenericLinkShare(): void { + $this->shareManager->method('sharingDisabledForUser')->willReturn(false); + $this->shareManager->method('shareApiAllowLinks')->willReturn(false); + + $this->mapper->expects($this->never())->method('insert'); + + $this->expectException(PermissionError::class); + $this->expectExceptionMessage('Public link sharing is disabled by your administrator.'); + + $this->shareService->create( + new ShareCreate( + 1, + 'table', + '', + 'link', + true, + false, + false, + true, + false, + 0, + null, + new ShareToken('tokenBypass2026x'), + ) + ); + } + }