2015-01-14 14:39:23 -05:00
|
|
|
<?php
|
2024-05-23 03:26:56 -04:00
|
|
|
|
2025-02-11 10:06:33 -05:00
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
2015-01-14 14:39:23 -05:00
|
|
|
/**
|
2024-05-23 03:26:56 -04:00
|
|
|
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
|
|
|
|
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
|
|
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
2015-01-14 14:39:23 -05:00
|
|
|
*/
|
2025-02-11 10:06:33 -05:00
|
|
|
|
2015-01-14 14:39:23 -05:00
|
|
|
namespace OC\Encryption;
|
|
|
|
|
|
2021-03-11 05:32:29 -05:00
|
|
|
use InvalidArgumentException;
|
2019-11-22 14:52:10 -05:00
|
|
|
use OC\Files\View;
|
2021-03-11 05:32:29 -05:00
|
|
|
use OCP\Encryption\Exceptions\GenericEncryptionException;
|
2025-02-11 10:06:33 -05:00
|
|
|
use OCP\Files\File as OCPFile;
|
|
|
|
|
use OCP\Files\Folder;
|
|
|
|
|
use OCP\Files\NotFoundException;
|
2021-03-11 05:32:29 -05:00
|
|
|
use Psr\Log\LoggerInterface;
|
2015-01-14 14:39:23 -05:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* update encrypted files, e.g. because a file was shared
|
|
|
|
|
*/
|
|
|
|
|
class Update {
|
|
|
|
|
public function __construct(
|
2025-02-11 10:06:33 -05:00
|
|
|
protected Util $util,
|
|
|
|
|
protected Manager $encryptionManager,
|
|
|
|
|
protected File $file,
|
|
|
|
|
protected LoggerInterface $logger,
|
2023-11-23 04:22:34 -05:00
|
|
|
) {
|
2015-01-14 14:39:23 -05:00
|
|
|
}
|
|
|
|
|
|
2015-04-23 10:48:11 -04:00
|
|
|
/**
|
|
|
|
|
* hook after file was shared
|
|
|
|
|
*/
|
2025-02-11 10:06:33 -05:00
|
|
|
public function postShared(OCPFile|Folder $node): void {
|
|
|
|
|
$this->update($node);
|
2015-01-14 14:39:23 -05:00
|
|
|
}
|
|
|
|
|
|
2015-04-23 10:48:11 -04:00
|
|
|
/**
|
|
|
|
|
* hook after file was unshared
|
|
|
|
|
*/
|
2025-02-11 10:06:33 -05:00
|
|
|
public function postUnshared(OCPFile|Folder $node): void {
|
|
|
|
|
$this->update($node);
|
2015-01-14 14:39:23 -05:00
|
|
|
}
|
|
|
|
|
|
2015-05-11 04:35:42 -04:00
|
|
|
/**
|
|
|
|
|
* inform encryption module that a file was restored from the trash bin,
|
|
|
|
|
* e.g. to update the encryption keys
|
|
|
|
|
*/
|
2025-02-11 10:06:33 -05:00
|
|
|
public function postRestore(OCPFile|Folder $node): void {
|
|
|
|
|
$this->update($node);
|
2015-05-11 04:35:42 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* inform encryption module that a file was renamed,
|
|
|
|
|
* e.g. to update the encryption keys
|
|
|
|
|
*/
|
2025-02-11 10:06:33 -05:00
|
|
|
public function postRename(OCPFile|Folder $source, OCPFile|Folder $target): void {
|
|
|
|
|
if (dirname($source->getPath()) !== dirname($target->getPath())) {
|
|
|
|
|
$this->update($target);
|
2015-05-11 04:35:42 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-14 14:39:23 -05:00
|
|
|
/**
|
2025-02-11 10:06:33 -05:00
|
|
|
* get owner and path relative to data/
|
2015-01-14 14:39:23 -05:00
|
|
|
*
|
2024-09-17 11:18:30 -04:00
|
|
|
* @throws \InvalidArgumentException
|
2015-01-14 14:39:23 -05:00
|
|
|
*/
|
2025-02-11 10:06:33 -05:00
|
|
|
protected function getOwnerPath(OCPFile|Folder $node): string {
|
|
|
|
|
$owner = $node->getOwner()?->getUID();
|
|
|
|
|
if ($owner === null) {
|
|
|
|
|
throw new InvalidArgumentException('No owner found for ' . $node->getId());
|
|
|
|
|
}
|
2015-04-23 10:48:11 -04:00
|
|
|
$view = new View('/' . $owner . '/files');
|
2025-02-11 10:06:33 -05:00
|
|
|
try {
|
|
|
|
|
$path = $view->getPath($node->getId());
|
|
|
|
|
} catch (NotFoundException $e) {
|
|
|
|
|
throw new InvalidArgumentException('No file found for ' . $node->getId(), previous:$e);
|
2015-04-23 10:48:11 -04:00
|
|
|
}
|
2025-02-11 10:06:33 -05:00
|
|
|
return '/' . $owner . '/files/' . $path;
|
2015-04-23 10:48:11 -04:00
|
|
|
}
|
2015-01-14 14:39:23 -05:00
|
|
|
|
2015-04-23 10:48:11 -04:00
|
|
|
/**
|
|
|
|
|
* notify encryption module about added/removed users from a file/folder
|
|
|
|
|
*
|
|
|
|
|
* @param string $path relative to data/
|
|
|
|
|
* @throws Exceptions\ModuleDoesNotExistsException
|
|
|
|
|
*/
|
2025-02-11 10:06:33 -05:00
|
|
|
public function update(OCPFile|Folder $node): void {
|
2017-05-30 05:59:49 -04:00
|
|
|
$encryptionModule = $this->encryptionManager->getEncryptionModule();
|
|
|
|
|
|
|
|
|
|
// if the encryption module doesn't encrypt the files on a per-user basis
|
|
|
|
|
// we have nothing to do here.
|
|
|
|
|
if ($encryptionModule->needDetailedAccessList() === false) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-11 10:06:33 -05:00
|
|
|
$path = $this->getOwnerPath($node);
|
2015-04-01 07:59:29 -04:00
|
|
|
// if a folder was shared, get a list of all (sub-)folders
|
2025-02-11 10:06:33 -05:00
|
|
|
if ($node instanceof Folder) {
|
2015-04-23 10:48:11 -04:00
|
|
|
$allFiles = $this->util->getAllFiles($path);
|
2015-04-01 07:59:29 -04:00
|
|
|
} else {
|
2020-03-26 04:30:18 -04:00
|
|
|
$allFiles = [$path];
|
2015-04-01 07:59:29 -04:00
|
|
|
}
|
2015-01-14 14:39:23 -05:00
|
|
|
|
2015-04-23 10:48:11 -04:00
|
|
|
foreach ($allFiles as $file) {
|
|
|
|
|
$usersSharing = $this->file->getAccessList($file);
|
2021-03-11 05:32:29 -05:00
|
|
|
try {
|
2025-08-07 12:08:42 -04:00
|
|
|
$encryptionModule->update($file, '', $usersSharing);
|
2021-03-11 05:32:29 -05:00
|
|
|
} catch (GenericEncryptionException $e) {
|
|
|
|
|
// If the update of an individual file fails e.g. due to a corrupt key we should continue the operation and just log the failure
|
2025-08-07 12:08:42 -04:00
|
|
|
$this->logger->error('Failed to update encryption module for ' . $file, [ 'exception' => $e ]);
|
2021-03-11 05:32:29 -05:00
|
|
|
}
|
2015-04-01 07:59:29 -04:00
|
|
|
}
|
2015-01-14 14:39:23 -05:00
|
|
|
}
|
2015-04-01 07:59:29 -04:00
|
|
|
}
|