fix(sharing): Publish activity for download by public link

Even if dav endpoint is now used.

Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
This commit is contained in:
Côme Chilliet 2025-03-13 12:09:38 +01:00 committed by Côme Chilliet
parent d1383602c7
commit 12ce8c0ef0
4 changed files with 123 additions and 0 deletions

View file

@ -59,6 +59,7 @@ return array(
'OCA\\Files_Sharing\\ISharedMountPoint' => $baseDir . '/../lib/ISharedMountPoint.php',
'OCA\\Files_Sharing\\ISharedStorage' => $baseDir . '/../lib/ISharedStorage.php',
'OCA\\Files_Sharing\\Listener\\BeforeDirectFileDownloadListener' => $baseDir . '/../lib/Listener/BeforeDirectFileDownloadListener.php',
'OCA\\Files_Sharing\\Listener\\BeforeNodeReadListener' => $baseDir . '/../lib/Listener/BeforeNodeReadListener.php',
'OCA\\Files_Sharing\\Listener\\BeforeZipCreatedListener' => $baseDir . '/../lib/Listener/BeforeZipCreatedListener.php',
'OCA\\Files_Sharing\\Listener\\LoadAdditionalListener' => $baseDir . '/../lib/Listener/LoadAdditionalListener.php',
'OCA\\Files_Sharing\\Listener\\LoadPublicFileRequestAuthListener' => $baseDir . '/../lib/Listener/LoadPublicFileRequestAuthListener.php',

View file

@ -74,6 +74,7 @@ class ComposerStaticInitFiles_Sharing
'OCA\\Files_Sharing\\ISharedMountPoint' => __DIR__ . '/..' . '/../lib/ISharedMountPoint.php',
'OCA\\Files_Sharing\\ISharedStorage' => __DIR__ . '/..' . '/../lib/ISharedStorage.php',
'OCA\\Files_Sharing\\Listener\\BeforeDirectFileDownloadListener' => __DIR__ . '/..' . '/../lib/Listener/BeforeDirectFileDownloadListener.php',
'OCA\\Files_Sharing\\Listener\\BeforeNodeReadListener' => __DIR__ . '/..' . '/../lib/Listener/BeforeNodeReadListener.php',
'OCA\\Files_Sharing\\Listener\\BeforeZipCreatedListener' => __DIR__ . '/..' . '/../lib/Listener/BeforeZipCreatedListener.php',
'OCA\\Files_Sharing\\Listener\\LoadAdditionalListener' => __DIR__ . '/..' . '/../lib/Listener/LoadAdditionalListener.php',
'OCA\\Files_Sharing\\Listener\\LoadPublicFileRequestAuthListener' => __DIR__ . '/..' . '/../lib/Listener/LoadPublicFileRequestAuthListener.php',

View file

@ -16,6 +16,7 @@ use OCA\Files_Sharing\External\Manager;
use OCA\Files_Sharing\External\MountProvider as ExternalMountProvider;
use OCA\Files_Sharing\Helper;
use OCA\Files_Sharing\Listener\BeforeDirectFileDownloadListener;
use OCA\Files_Sharing\Listener\BeforeNodeReadListener;
use OCA\Files_Sharing\Listener\BeforeZipCreatedListener;
use OCA\Files_Sharing\Listener\LoadAdditionalListener;
use OCA\Files_Sharing\Listener\LoadPublicFileRequestAuthListener;
@ -42,6 +43,7 @@ use OCP\Federation\ICloudIdManager;
use OCP\Files\Config\IMountProviderCollection;
use OCP\Files\Events\BeforeDirectFileDownloadEvent;
use OCP\Files\Events\BeforeZipCreatedEvent;
use OCP\Files\Events\Node\BeforeNodeReadEvent;
use OCP\Group\Events\GroupChangedEvent;
use OCP\Group\Events\GroupDeletedEvent;
use OCP\Group\Events\UserAddedEvent;
@ -94,6 +96,9 @@ class Application extends App implements IBootstrap {
$context->registerEventListener(ShareCreatedEvent::class, UserShareAcceptanceListener::class);
$context->registerEventListener(UserAddedEvent::class, UserAddedToGroupListener::class);
// Publish activity for public download
$context->registerEventListener(BeforeNodeReadEvent::class, BeforeNodeReadListener::class);
// Handle download events for view only checks
$context->registerEventListener(BeforeZipCreatedEvent::class, BeforeZipCreatedListener::class);
$context->registerEventListener(BeforeDirectFileDownloadEvent::class, BeforeDirectFileDownloadListener::class);

View file

@ -0,0 +1,116 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Sharing\Listener;
use OCA\Files_Sharing\Activity\Providers\Downloads;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Files\Events\Node\BeforeNodeReadEvent;
use OCP\Files\File;
use OCP\Files\IRootFolder;
use OCP\Files\Storage\ISharedStorage;
use OCP\IRequest;
use OCP\IUserSession;
use OCP\Share\IShare;
/**
* @template-implements IEventListener<BeforeNodeReadEvent|Event>
*/
class BeforeNodeReadListener implements IEventListener {
public function __construct(
private IUserSession $userSession,
private IRootFolder $rootFolder,
protected \OCP\Activity\IManager $activityManager,
private IRequest $request,
) {
}
public function handle(Event $event): void {
if (!($event instanceof BeforeNodeReadEvent)) {
return;
}
$node = $event->getNode();
if (!($node instanceof File)) {
return;
}
try {
$storage = $node->getStorage();
} catch (NotFoundException) {
return;
}
if (!$storage->instanceOfStorage(ISharedStorage::class)) {
return;
}
/** @var ISharedStorage $storage */
$share = $storage->getShare();
$this->singleFileDownloaded($share, $node);
}
/**
* create activity if a single file was downloaded from a link share
*/
protected function singleFileDownloaded(IShare $share, File $node): void {
$fileId = $node->getId();
$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
$userNode = $userFolder->getFirstNodeById($fileId);
$ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
$userPath = $userFolder->getRelativePath($userNode?->getPath() ?? '') ?? '';
$ownerPath = $ownerFolder->getRelativePath($node->getPath()) ?? '';
$parameters = [$userPath];
if ($share->getShareType() === IShare::TYPE_EMAIL) {
$subject = Downloads::SUBJECT_SHARED_FILE_BY_EMAIL_DOWNLOADED;
$parameters[] = $share->getSharedWith();
} elseif ($share->getShareType() === IShare::TYPE_LINK) {
$subject = Downloads::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
$remoteAddress = $this->request->getRemoteAddress();
$dateTime = new \DateTime();
$dateTime = $dateTime->format('Y-m-d H');
$remoteAddressHash = md5($dateTime . '-' . $remoteAddress);
$parameters[] = $remoteAddressHash;
} else {
return;
}
$this->publishActivity($subject, $parameters, $share->getSharedBy(), $fileId, $userPath);
if ($share->getShareOwner() !== $share->getSharedBy()) {
$parameters[0] = $ownerPath;
$this->publishActivity($subject, $parameters, $share->getShareOwner(), $fileId, $ownerPath);
}
}
/**
* publish activity
*/
protected function publishActivity(
string $subject,
array $parameters,
string $affectedUser,
int $fileId,
string $filePath,
): void {
$event = $this->activityManager->generateEvent();
$event->setApp('files_sharing')
->setType('public_links')
->setSubject($subject, $parameters)
->setAffectedUser($affectedUser)
->setObject('files', $fileId, $filePath);
$this->activityManager->publish($event);
}
}