forked from extern/egroupware
Api: Sharing listens to Vfs hooks to stay up-to-date with deleted or renamed files
This commit is contained in:
parent
66f197d0b0
commit
173b695cf2
@ -54,24 +54,29 @@ $setup_info['api']['tables'][] = 'egw_ea_valid';
|
|||||||
$setup_info['api']['tables'][] = 'egw_ea_notifications';
|
$setup_info['api']['tables'][] = 'egw_ea_notifications';
|
||||||
|
|
||||||
// hooks used by vfs_home_hooks to manage user- and group-directories for the new stream based VFS
|
// hooks used by vfs_home_hooks to manage user- and group-directories for the new stream based VFS
|
||||||
$setup_info['api']['hooks']['addaccount'] = array('EGroupware\\Api\\Vfs\\Hooks::addAccount', 'EGroupware\\Api\\Mail\\Hooks::addaccount');
|
$setup_info['api']['hooks']['addaccount'] = array('EGroupware\\Api\\Vfs\\Hooks::addAccount', 'EGroupware\\Api\\Mail\\Hooks::addaccount');
|
||||||
$setup_info['api']['hooks']['deleteaccount'] = array('EGroupware\\Api\\Vfs\\Hooks::deleteAccount', 'EGroupware\\Api\\Mail\\Hooks::deleteaccount');
|
$setup_info['api']['hooks']['deleteaccount'] = array('EGroupware\\Api\\Vfs\\Hooks::deleteAccount', 'EGroupware\\Api\\Mail\\Hooks::deleteaccount');
|
||||||
$setup_info['api']['hooks']['editaccount'] = array('EGroupware\\Api\\Vfs\\Hooks::editAccount', 'EGroupware\\Api\\Mail\\Hooks::addaccount');
|
$setup_info['api']['hooks']['editaccount'] = array('EGroupware\\Api\\Vfs\\Hooks::editAccount', 'EGroupware\\Api\\Mail\\Hooks::addaccount');
|
||||||
$setup_info['api']['hooks']['addgroup'] = 'EGroupware\\Api\\Vfs\\Hooks::addGroup';
|
$setup_info['api']['hooks']['addgroup'] = 'EGroupware\\Api\\Vfs\\Hooks::addGroup';
|
||||||
$setup_info['api']['hooks']['deletegroup'] = array('EGroupware\\Api\\Vfs\\Hooks::deleteGroup', 'EGroupware\\Api\\Mail\\Hooks::deletegroup');
|
$setup_info['api']['hooks']['deletegroup'] = array('EGroupware\\Api\\Vfs\\Hooks::deleteGroup', 'EGroupware\\Api\\Mail\\Hooks::deletegroup');
|
||||||
$setup_info['api']['hooks']['editgroup'] = 'EGroupware\\Api\\Vfs\\Hooks::editGroup';
|
$setup_info['api']['hooks']['editgroup'] = 'EGroupware\\Api\\Vfs\\Hooks::editGroup';
|
||||||
$setup_info['api']['hooks']['changepassword'] = 'EGroupware\\Api\\Mail\\Hooks::changepassword';
|
$setup_info['api']['hooks']['changepassword'] = 'EGroupware\\Api\\Mail\\Hooks::changepassword';
|
||||||
$setup_info['api']['hooks']['sidebox_all'] = 'EGroupware\\Api\\Framework\\Tutorial::tutorial_menu';
|
$setup_info['api']['hooks']['sidebox_all'] = 'EGroupware\\Api\\Framework\\Tutorial::tutorial_menu';
|
||||||
|
|
||||||
|
// Hooks to delete shares when file is deleted
|
||||||
|
$setup_info['api']['hooks']['vfs_unlink'] = 'EGroupware\\Api\\Vfs\\Sharing::vfsUpdate';
|
||||||
|
$setup_info['api']['hooks']['vfs_rename'] = 'EGroupware\\Api\\Vfs\\Sharing::vfsUpdate';
|
||||||
|
$setup_info['api']['hooks']['vfs_rmdir'] = 'EGroupware\\Api\\Vfs\\Sharing::vfsUpdate';
|
||||||
|
|
||||||
// installation checks
|
// installation checks
|
||||||
$setup_info['api']['check_install'] = array(
|
$setup_info['api']['check_install'] = array(
|
||||||
'' => array(
|
'' => array(
|
||||||
'func' => 'pear_check',
|
'func' => 'pear_check',
|
||||||
'from' => 'Api/Mail',
|
'from' => 'Api/Mail',
|
||||||
),
|
),
|
||||||
'pear.horde.org/Horde_Imap_Client' => array(
|
'pear.horde.org/Horde_Imap_Client' => array(
|
||||||
'func' => 'pear_check',
|
'func' => 'pear_check',
|
||||||
'from' => 'Api/Mail',
|
'from' => 'Api/Mail',
|
||||||
'version' => '2.24.2',
|
'version' => '2.24.2',
|
||||||
),
|
),
|
||||||
'pear.horde.org/Horde_Nls' => array(
|
'pear.horde.org/Horde_Nls' => array(
|
||||||
|
@ -15,8 +15,6 @@ namespace EGroupware\Api\Vfs;
|
|||||||
|
|
||||||
use EGroupware\Api;
|
use EGroupware\Api;
|
||||||
use EGroupware\Api\Vfs;
|
use EGroupware\Api\Vfs;
|
||||||
use EGroupware\Collabora\Wopi;
|
|
||||||
|
|
||||||
use filemanager_ui;
|
use filemanager_ui;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -398,6 +396,52 @@ class Sharing extends \EGroupware\Api\Sharing
|
|||||||
return $actions;
|
return $actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook callback to watch VFS and remove any shares for files that get moved or removed
|
||||||
|
*/
|
||||||
|
public static function vfsUpdate($data)
|
||||||
|
{
|
||||||
|
$path = $data['location'] == 'vfs_rename' ? $data['from'] : $data['path'];
|
||||||
|
if (parse_url($path, PHP_URL_SCHEME) !== 'vfs')
|
||||||
|
{
|
||||||
|
$path = Api\Vfs::PREFIX . ($path[0] == '/' ? '' : '/') . $path;
|
||||||
|
}
|
||||||
|
if ($data['location'] == 'vfs_rmdir')
|
||||||
|
{
|
||||||
|
// Normally removing a directory removes the files first, so any shares inside the directory would
|
||||||
|
// be handled already, but just in case, get it all.
|
||||||
|
$path .= '%';
|
||||||
|
}
|
||||||
|
|
||||||
|
$shares = array();
|
||||||
|
foreach ($GLOBALS['egw']->db->select(self::TABLE, array(
|
||||||
|
'share_id', 'share_path', 'share_owner'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
"share_path LIKE '$path'"
|
||||||
|
),
|
||||||
|
__LINE__, __FILE__, false) as $share)
|
||||||
|
{
|
||||||
|
$shares[] = $share;
|
||||||
|
}
|
||||||
|
foreach ($shares as $share)
|
||||||
|
{
|
||||||
|
if ($data['location'] == 'vfs_rename')
|
||||||
|
{
|
||||||
|
if (parse_url($data['to'], PHP_URL_SCHEME) !== 'vfs')
|
||||||
|
{
|
||||||
|
$data['to'] = $path = Api\Vfs::PREFIX . ($data['to'][0] == '/' ? '' : '/') . $data['to'];
|
||||||
|
}
|
||||||
|
$GLOBALS['egw']->db->update(self::TABLE, array(
|
||||||
|
'share_path' => $data['to']
|
||||||
|
), $share, __LINE__, __FILE__);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static::delete($share['share_id']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file_exists(__DIR__.'/../../../filemanager/inc/class.filemanager_ui.inc.php'))
|
if (file_exists(__DIR__.'/../../../filemanager/inc/class.filemanager_ui.inc.php'))
|
||||||
|
@ -17,8 +17,8 @@ namespace EGroupware\Api\Vfs;
|
|||||||
require_once __DIR__ . '/../LoggedInTest.php';
|
require_once __DIR__ . '/../LoggedInTest.php';
|
||||||
|
|
||||||
use EGroupware\Api;
|
use EGroupware\Api;
|
||||||
use EGroupware\Api\Vfs;
|
|
||||||
use EGroupware\Api\LoggedInTest as LoggedInTest;
|
use EGroupware\Api\LoggedInTest as LoggedInTest;
|
||||||
|
use EGroupware\Api\Vfs;
|
||||||
use EGroupware\Stylite\Vfs\Versioning;
|
use EGroupware\Stylite\Vfs\Versioning;
|
||||||
|
|
||||||
|
|
||||||
@ -421,6 +421,19 @@ class SharingBase extends LoggedInTest
|
|||||||
return $share;
|
return $share;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function readShare($share_id)
|
||||||
|
{
|
||||||
|
foreach ($GLOBALS['egw']->db->select(Sharing::TABLE, '*',
|
||||||
|
array(
|
||||||
|
'share_id' => (int)$share_id
|
||||||
|
),
|
||||||
|
__LINE__, __FILE__, false) as $share)
|
||||||
|
{
|
||||||
|
return $share;
|
||||||
|
}
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make an infolog entry
|
* Make an infolog entry
|
||||||
*/
|
*/
|
||||||
@ -428,9 +441,9 @@ class SharingBase extends LoggedInTest
|
|||||||
{
|
{
|
||||||
$bo = new \infolog_bo();
|
$bo = new \infolog_bo();
|
||||||
$element = array(
|
$element = array(
|
||||||
'info_subject' => "Test infolog for #{$this->getName()}",
|
'info_subject' => "Test infolog for #{$this->getName()}",
|
||||||
'info_des' => 'Test element for ' . $this->getName() ."\n". Api\DateTime::to(),
|
'info_des' => 'Test element for ' . $this->getName() . "\n" . Api\DateTime::to(),
|
||||||
'info_status' => 'open'
|
'info_status' => 'open'
|
||||||
);
|
);
|
||||||
|
|
||||||
$element_id = $bo->write($element, true, true, true, true);
|
$element_id = $bo->write($element, true, true, true, true);
|
||||||
|
108
api/tests/Vfs/SharingHooksTest.php
Normal file
108
api/tests/Vfs/SharingHooksTest.php
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for updating / deleting shares if underlying file is renamed or deleted
|
||||||
|
*
|
||||||
|
* We create files and delete them through the VFS, then check to see if the share is
|
||||||
|
* correctly deleted too.
|
||||||
|
*
|
||||||
|
* @link http://www.egroupware.org
|
||||||
|
* @author Nathan Gray
|
||||||
|
* @copyright (c) 2020 Nathan Gray
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace EGroupware\Api\Vfs;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/SharingBase.php';
|
||||||
|
|
||||||
|
use EGroupware\Api\Vfs;
|
||||||
|
|
||||||
|
|
||||||
|
class SharingHooksTest extends SharingBase
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that deleting a file deletes the share
|
||||||
|
*/
|
||||||
|
public function testDeleteFileDeletesShare()
|
||||||
|
{
|
||||||
|
$target = Vfs::get_home_dir();
|
||||||
|
|
||||||
|
$this->files = $this->addFiles($target);
|
||||||
|
$test_file = $this->files[0];
|
||||||
|
|
||||||
|
// Make sure there are no leftover shares
|
||||||
|
Sharing::delete(array('share_path' => $test_file));
|
||||||
|
|
||||||
|
// Create share
|
||||||
|
$this->shares[] = $created_share = Sharing::create($test_file, Sharing::READONLY, '', '');
|
||||||
|
|
||||||
|
$this->assertEquals(Vfs::PREFIX . $test_file, $created_share['share_path']);
|
||||||
|
|
||||||
|
// Now delete the file
|
||||||
|
Vfs::remove($test_file);
|
||||||
|
|
||||||
|
// Check for share for that file
|
||||||
|
$read_share = $this->readShare($created_share['share_id']);
|
||||||
|
|
||||||
|
$this->assertEquals(array(), $read_share, "Expected not to find the share, but something was found");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that deleting a directory deletes shares on any file in that directory
|
||||||
|
*/
|
||||||
|
public function testDeleteDirectoryDeletesShare()
|
||||||
|
{
|
||||||
|
$target = Vfs::get_home_dir();
|
||||||
|
|
||||||
|
$this->files = $this->addFiles($target);
|
||||||
|
$test_file = $target . '/sub_dir/subdir_test_file.txt';
|
||||||
|
|
||||||
|
// Make sure there are no leftover shares
|
||||||
|
Sharing::delete(array('share_path' => $test_file));
|
||||||
|
|
||||||
|
// Create share
|
||||||
|
$this->shares[] = $created_share = Sharing::create($test_file, Sharing::READONLY, '', '');
|
||||||
|
|
||||||
|
$this->assertEquals(Vfs::PREFIX . $test_file, $created_share['share_path']);
|
||||||
|
|
||||||
|
// Now delete the parent directory
|
||||||
|
Vfs::remove($target . '/sub_dir');
|
||||||
|
|
||||||
|
// Check for share for that file
|
||||||
|
$read_share = $this->readShare($created_share['share_id']);
|
||||||
|
|
||||||
|
$this->assertEquals(array(), $read_share, "Expected not to find the share, but something was found");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test renaming a file updates the share
|
||||||
|
*/
|
||||||
|
public function testRenameFileUpdatesShare()
|
||||||
|
{
|
||||||
|
$target = Vfs::get_home_dir();
|
||||||
|
|
||||||
|
$this->files = $this->addFiles($target);
|
||||||
|
$test_file = $this->files[0];
|
||||||
|
|
||||||
|
// Make sure there are no leftover shares
|
||||||
|
Sharing::delete(array('share_path' => $test_file));
|
||||||
|
|
||||||
|
// Create share
|
||||||
|
$this->shares[] = $created_share = Sharing::create($test_file, Sharing::READONLY, '', '');
|
||||||
|
|
||||||
|
$this->assertEquals(Vfs::PREFIX . $test_file, $created_share['share_path']);
|
||||||
|
|
||||||
|
// Now rename the file
|
||||||
|
$this->files[] = $moved = $target . '/moved.txt';
|
||||||
|
Vfs::rename($test_file, $moved);
|
||||||
|
|
||||||
|
// Check for share for that file
|
||||||
|
$read_share = $this->readShare($created_share['share_id']);
|
||||||
|
|
||||||
|
$this->assertEquals(Vfs::PREFIX . $moved, $read_share['share_path'], "Expected find the share with a different path");
|
||||||
|
$this->assertNotEquals(Vfs::PREFIX . $moved, $created_share['share_path'], "Expected find the share with a different path");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user