use hooks to update encryption keys instead of the storage wrapper if a file gets renamed/restored, as long as we

are in the storage wrapper the file cache isn't up-to-date
This commit is contained in:
Bjoern Schiessle 2015-05-11 10:35:42 +02:00
parent ebf3953908
commit 0d5c7a11e2
6 changed files with 156 additions and 22 deletions

View File

@ -727,6 +727,8 @@ class OC {
if ($enabled) { if ($enabled) {
\OCP\Util::connectHook('OCP\Share', 'post_shared', 'OC\Encryption\HookManager', 'postShared'); \OCP\Util::connectHook('OCP\Share', 'post_shared', 'OC\Encryption\HookManager', 'postShared');
\OCP\Util::connectHook('OCP\Share', 'post_unshare', 'OC\Encryption\HookManager', 'postUnshared'); \OCP\Util::connectHook('OCP\Share', 'post_unshare', 'OC\Encryption\HookManager', 'postUnshared');
\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OC\Encryption\HookManager', 'postRename');
\OCP\Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', 'OC\Encryption\HookManager', 'postRestore');
} }
} }

View File

@ -37,6 +37,14 @@ class HookManager {
self::getUpdate()->postUnshared($params); self::getUpdate()->postUnshared($params);
} }
public static function postRename($params) {
self::getUpdate()->postRename($params);
}
public static function postRestore($params) {
self::getUpdate()->postRestore($params);
}
/** /**
* @return Update * @return Update
*/ */

View File

@ -107,6 +107,38 @@ class Update {
} }
} }
/**
* inform encryption module that a file was restored from the trash bin,
* e.g. to update the encryption keys
*
* @param array $params
*/
public function postRestore($params) {
if ($this->encryptionManager->isEnabled()) {
$path = Filesystem::normalizePath('/' . $this->uid . '/files/' . $params['filePath']);
$this->update($path);
}
}
/**
* inform encryption module that a file was renamed,
* e.g. to update the encryption keys
*
* @param array $params
*/
public function postRename($params) {
$source = $params['oldpath'];
$target = $params['newpath'];
if(
$this->encryptionManager->isEnabled() &&
dirname($source) !== dirname($target)
) {
list($owner, $ownerPath) = $this->getOwnerPath($target);
$absPath = '/' . $owner . '/files/' . $ownerPath;
$this->update($absPath);
}
}
/** /**
* get owner and path relative to data/<owner>/files * get owner and path relative to data/<owner>/files
* *
@ -114,7 +146,7 @@ class Update {
* @return array ['owner' => $owner, 'path' => $path] * @return array ['owner' => $owner, 'path' => $path]
* @throw \InvalidArgumentException * @throw \InvalidArgumentException
*/ */
private function getOwnerPath($path) { protected function getOwnerPath($path) {
$info = Filesystem::getFileInfo($path); $info = Filesystem::getFileInfo($path);
$owner = Filesystem::getOwner($path); $owner = Filesystem::getOwner($path);
$view = new View('/' . $owner . '/files'); $view = new View('/' . $owner . '/files');

View File

@ -231,13 +231,7 @@ class Encryption extends Wrapper {
if (isset($this->unencryptedSize[$source])) { if (isset($this->unencryptedSize[$source])) {
$this->unencryptedSize[$target] = $this->unencryptedSize[$source]; $this->unencryptedSize[$target] = $this->unencryptedSize[$source];
} }
$keysRenamed = $this->keyStorage->renameKeys($source, $target); $this->keyStorage->renameKeys($source, $target);
if ($keysRenamed &&
dirname($source) !== dirname($target) &&
$this->util->isFile($target)
) {
$this->update->update($target);
}
} }
} }

View File

@ -68,10 +68,6 @@ class UpdateTest extends TestCase {
$this->encryptionModule = $this->getMockBuilder('\OCP\Encryption\IEncryptionModule') $this->encryptionModule = $this->getMockBuilder('\OCP\Encryption\IEncryptionModule')
->disableOriginalConstructor()->getMock(); ->disableOriginalConstructor()->getMock();
$this->encryptionManager->expects($this->once())
->method('getEncryptionModule')
->willReturn($this->encryptionModule);
$this->uid = 'testUser1'; $this->uid = 'testUser1';
$this->update = new Update( $this->update = new Update(
@ -93,6 +89,10 @@ class UpdateTest extends TestCase {
*/ */
public function testUpdate($path, $isDir, $allFiles, $numberOfFiles) { public function testUpdate($path, $isDir, $allFiles, $numberOfFiles) {
$this->encryptionManager->expects($this->once())
->method('getEncryptionModule')
->willReturn($this->encryptionModule);
$this->view->expects($this->once()) $this->view->expects($this->once())
->method('is_dir') ->method('is_dir')
->willReturn($isDir); ->willReturn($isDir);
@ -126,4 +126,111 @@ class UpdateTest extends TestCase {
); );
} }
/**
* @dataProvider dataTestPostRename
*
* @param string $source
* @param string $target
* @param boolean $encryptionEnabled
*/
public function testPostRename($source, $target, $encryptionEnabled) {
$updateMock = $this->getUpdateMock(['update', 'getOwnerPath']);
$this->encryptionManager->expects($this->once())
->method('isEnabled')
->willReturn($encryptionEnabled);
if (dirname($source) === dirname($target) || $encryptionEnabled === false) {
$updateMock->expects($this->never())->method('getOwnerPath');
$updateMock->expects($this->never())->method('update');
} else {
$updateMock->expects($this->once())
->method('getOwnerPath')
->willReturnCallback(function($path) use ($target) {
$this->assertSame(
$target,
$path,
'update needs to be executed for the target destination');
return ['owner', $path];
});
$updateMock->expects($this->once())->method('update');
}
$updateMock->postRename(['oldpath' => $source, 'newpath' => $target]);
}
/**
* test data for testPostRename()
*
* @return array
*/
public function dataTestPostRename() {
return array(
array('/test.txt', '/testNew.txt', true),
array('/test.txt', '/testNew.txt', false),
array('/folder/test.txt', '/testNew.txt', true),
array('/folder/test.txt', '/testNew.txt', false),
array('/folder/test.txt', '/testNew.txt', true),
array('/test.txt', '/folder/testNew.txt', false),
);
}
/**
* @dataProvider dataTestPostRestore
*
* @param boolean $encryptionEnabled
*/
public function testPostRestore($encryptionEnabled) {
$updateMock = $this->getUpdateMock(['update']);
$this->encryptionManager->expects($this->once())
->method('isEnabled')
->willReturn($encryptionEnabled);
if ($encryptionEnabled) {
$updateMock->expects($this->once())->method('update');
} else {
$updateMock->expects($this->never())->method('update');
}
$updateMock->postRestore(['filePath' => '/folder/test.txt']);
}
/**
* test data for testPostRestore()
*
* @return array
*/
public function dataTestPostRestore() {
return array(
array(true),
array(false),
);
}
/**
* create mock of the update method
*
* @param array$methods methods which should be set
* @return \OC\Encryption\Update | \PHPUnit_Framework_MockObject_MockObject
*/
protected function getUpdateMock($methods) {
return $this->getMockBuilder('\OC\Encryption\Update')
->setConstructorArgs(
[
$this->view,
$this->util,
$this->mountManager,
$this->encryptionManager,
$this->fileHelper,
$this->uid
]
)->setMethods($methods)->getMock();
}
} }

View File

@ -157,13 +157,11 @@ class Encryption extends \Test\Files\Storage\Storage {
* @param string $target * @param string $target
* @param $encryptionEnabled * @param $encryptionEnabled
* @param boolean $renameKeysReturn * @param boolean $renameKeysReturn
* @param boolean $shouldUpdate
*/ */
public function testRename($source, public function testRename($source,
$target, $target,
$encryptionEnabled, $encryptionEnabled,
$renameKeysReturn, $renameKeysReturn) {
$shouldUpdate) {
if ($encryptionEnabled) { if ($encryptionEnabled) {
$this->keyStore $this->keyStore
->expects($this->once()) ->expects($this->once())
@ -177,13 +175,6 @@ class Encryption extends \Test\Files\Storage\Storage {
->method('isFile')->willReturn(true); ->method('isFile')->willReturn(true);
$this->encryptionManager->expects($this->once()) $this->encryptionManager->expects($this->once())
->method('isEnabled')->willReturn($encryptionEnabled); ->method('isEnabled')->willReturn($encryptionEnabled);
if ($shouldUpdate) {
$this->update->expects($this->once())
->method('update');
} else {
$this->update->expects($this->never())
->method('update');
}
$this->instance->mkdir($source); $this->instance->mkdir($source);
$this->instance->mkdir(dirname($target)); $this->instance->mkdir(dirname($target));