'user_test', 'account_firstname' => 'ShareAccess', 'account_lastname' => 'Test', 'account_passwd' => 'passw0rd', 'account_passwd_2' => 'passw0rd' ); protected function setUp() : void { if(($account_id = $GLOBALS['egw']->accounts->name2id($this->account['account_lid']))) { // Delete if there in case something went wrong $GLOBALS['egw']->accounts->delete($account_id); } // Execute $command = new \admin_cmd_edit_user(false, $this->account); $command->comment = 'Needed for unit test ' . $this->getName(); $command->run(); $this->account_id = $command->account; } protected function tearDown() : void { parent::tearDown(); if($this->account_id) { $GLOBALS['egw']->accounts->delete($this->account_id); } } public function setupShare(&$dir, $extra = array(), $create = 'createShare') { // First, create the files to be shared $this->files[] = $dir = Vfs::get_home_dir() . '/share/'; Vfs::mkdir($dir); $this->files = $this->addFiles($dir); // Also create one that should not be accessed $this->files[] = $this->no_access = Vfs::get_home_dir() . '/not_shared_file.txt'; $this->assertTrue( file_put_contents(Vfs::PREFIX . $this->no_access, "This file is not shared") !== FALSE, 'Unable to write test file "' . Vfs::PREFIX . $this->no_access . '" - check file permissions for CLI user' ); // Create and use link $this->getShareExtra($dir, Sharing::READONLY, $extra); $share = call_user_func([$this,$create],$dir, Sharing::READONLY, $extra); $link = Vfs\Sharing::share2link($share); // Now log out and log in as someone else Vfs::clearstatcache(); Vfs::init_static(); Vfs\StreamWrapper::init_static(); LoggedInTest::tearDownAfterClass(); return $link; } /** * Create a hidden upload share * * @param $path * @param $mode * @param array $extra * @return array * @throws \EGroupware\Api\Exception\AssertionFailed */ protected function createHiddenUploadShare($path, $mode, $extra = array()) { // Make sure the path is there if(!Vfs::is_readable($path)) { $this->assertTrue( Vfs::is_dir($path) ? Vfs::mkdir($path,0750,true) : Vfs::touch($path), "Share path $path does not exist" ); } // Create share $this->shares[] = $share = TestHiddenSharing::create('', $path, $mode, $name, $recipients, $extra); return $share; } /** * Test that a share of a directory only gives access to that directory, and any other * directories that the sharer has are unavailable * * This checks an existing user that is logged in when they follow the share link. * * ** CURRENTLY we make a new session anyway, so no changes should be visible on VFS ** */ public function testShareKeepSession() { $dir = ''; $link = $this->setupShare($dir); LoggedInTest::load_egw($this->account['account_lid'],$this->account['account_passwd']); Vfs::init_static(); Vfs\StreamWrapper::init_static(); // Check that we can't access the no_access file $this->assertFalse(Vfs::is_readable($this->no_access), "Could access the not-readable file even before we started."); // What's our VFS like? $pre_fstab = Vfs::mount(); $vfs_options = array( 'maxdepth' => 3, // Exclude a lot of the stuff we're not interested in 'path_preg' => '#^' . Vfs::PREFIX . '\/(?!apps|templates|etemplates|apps-backup).*#' ); //$pre_files = Vfs::find('/', $vfs_options); $data = array(); $form = $this->getShare($link, $data, true); $this->assertNotNull($form, "Could not read the share link"); $rows = array_values($data['data']['content']['nm']['rows']); $post_mount_vfs = Vfs::mount(); //$post_files = Vfs::find('/', $vfs_options); // Check that our fstab was not changed $this->assertEquals(count($pre_fstab), count($post_mount_vfs), "fstab mounts changed"); // Check we can't find the non-shared file in VFS $this->assertFalse(Vfs::is_readable($this->no_access), "Could access the not-readable file '$this->no_access' after accessing the share." ); // Check we can't find the non-shared file in results $result = array_filter($rows, function($v) { return $v['name'] == $this->no_access; }); $this->assertEmpty($result, "Found the file we shouldn't have access to ({$this->no_access})"); // Check that we can find the shared file(s) in the form / nm list // Don't test the no-access one (done above), and no good way to get the sub-dir file either, // since nm only has top-level files and we can't switch the filter $this->checkNextmatch($dir, array_diff($this->files, [$this->no_access, $dir."sub_dir/subdir_test_file.txt"]), $rows); } /** * Test that a share of a directory only gives access to that directory, and any other * directories that the sharer has are unavailable * * This checks from one logged in user to anonymous with a new session */ public function testShareNewSession() { $dir = ''; $link = $this->setupShare($dir); // Now follow the link - this _should_ be enough to get it added //$mimetype = Vfs::mime_content_type($dir); //$this->checkSharedFile($link, $mimetype); // Read the etemplate $data = array(); $form = $this->getShare($link, $data, false); $this->assertNotNull($form, "Could not read the share link"); $rows = $data['data']['content']['nm']['rows']; Vfs::clearstatcache(); Vfs::init_static(); Vfs\StreamWrapper::init_static(); // Check we can't find the non-shared file $result = array_filter($rows, function($v) { return $v['name'] == $this->no_access; }); $this->assertEmpty($result, "Found the file we shouldn't have access to ({$this->no_access})"); // Check that we can find the shared file(s) in the form / nm list // Don't test the no-access one (done above), and no good way to get the sub-dir file either, // since nm only has top-level files and we can't switch the filter $this->checkNextmatch($dir, array_diff($this->files, [$this->no_access, $dir."sub_dir/subdir_test_file.txt"]), $rows); } /** * Test that a share of a directory with hidden upload subdirectory only gives access to that directory, * and the upload directory as well as any other directories that the sharer has are unavailable * * This checks from one logged in user to anonymous with a new session */ public function testShareHiddenUploadNewSession() { $dir = ''; $link = $this->setupShare($dir, [], 'createHiddenUploadShare'); // Now follow the link - this _should_ be enough to get it added //$mimetype = Vfs::mime_content_type($dir); //$this->checkSharedFile($link, $mimetype); // Read the etemplate $data = array(); $form = $this->getShare($link, $data, false); $this->assertNotNull($form, "Could not read the share link"); $rows = array_values($data['data']['content']['nm']['rows']); Vfs::clearstatcache(); Vfs::init_static(); Vfs\StreamWrapper::init_static(); // Check we can't find the non-shared file $result = array_filter($rows, function($v) { return $v['name'] == $this->no_access; }); $this->assertEmpty($result, "Found the file we shouldn't have access to ({$this->no_access})"); // Test that we can't see the hidden upload directory $result = array_filter($rows, function($v) { return $v['name'] == 'Upload'; }); $this->assertEmpty($result, "Hidden upload directory is visible"); // Check that we can find the shared file(s) in the form / nm list // Don't test the no-access one (done above), and no good way to get the sub-dir file either, // since nm only has top-level files and we can't switch the filter $this->checkNextmatch($dir, array_diff($this->files, [$this->no_access, $dir."sub_dir/subdir_test_file.txt"]), $rows); } /** * Check the nextmatch rows to see if all the expected files (in the given directory) are present * * @param $dir Current working directory, share target * @param $check_files List of files that should be there * @param $rows Nextmatch rows */ protected function checkNextmatch($dir, $check_files, $rows) { foreach($check_files as $file) { $relative_file = str_replace($dir,'',$file); if($relative_file[strlen($relative_file)-1] == '/') { $relative_file = substr($relative_file, 0, -1); } $result = array_filter($rows, function($v) use ($relative_file) { return $v['name'] == $relative_file; }); $this->assertNotEmpty($result, "Couldn't find shared file '$file'"); } } /** * Test that a share of a single file gives the file (uses WebDAV) */ public function testSingleFile() { $dir = Vfs::get_home_dir().'/'; // Plain text file $file = $dir.'test_file.txt'; $content = 'Testing that sharing a single (non-editable) file gives us the file.'; $this->assertTrue( file_put_contents(Vfs::PREFIX.$file, $content) !== FALSE, 'Unable to write test file "' . Vfs::PREFIX . $file .'" - check file permissions for CLI user' ); $this->files[] = $file; $mimetype = Vfs::mime_content_type($file); // Create and use link $extra = array(); $this->getShareExtra($file, Sharing::READONLY, $extra); $share = $this->createShare($file, Sharing::READONLY, $extra); $link = Vfs\Sharing::share2link($share); // Re-init, since they look at user, fstab, etc. // Also, further tests that access the filesystem fail if we don't Vfs::clearstatcache(); Vfs::init_static(); Vfs\StreamWrapper::init_static(); // Log out & clear cache LoggedInTest::tearDownAfterClass(); $this->checkSharedFile($link, $mimetype); } }