Quellcode durchsuchen

Move post_removeFromGroup to shareManager

The last sharing hook to be moved over.

* Added unit tests
* Removed old tests that relied on old behaviour
* Removed old hooks.php
Roeland Jago Douma vor 8 Jahren
Ursprung
Commit
6144ced7a0

+ 11 - 0
apps/federatedfilesharing/lib/federatedshareprovider.php

@@ -590,4 +590,15 @@ class FederatedShareProvider implements IShareProvider {
 		// We don't handle groups here
 		return;
 	}
+
+	/**
+	 * This provider does not handle groups
+	 *
+	 * @param string $uid
+	 * @param string $gid
+	 */
+	public function userDeletedFromGroup($uid, $gid) {
+		// We don't handle groups here
+		return;
+	}
 }

+ 1 - 1
lib/base.php

@@ -778,7 +778,7 @@ class OC {
 	public static function registerShareHooks() {
 		if (\OC::$server->getSystemConfig()->getValue('installed')) {
 			OC_Hook::connect('OC_User', 'post_deleteUser', 'OC\Share20\Hooks', 'post_deleteUser');
-			OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OC\Share\Hooks', 'post_removeFromGroup');
+			OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OC\Share20\Hooks', 'post_removeFromGroup');
 			OC_Hook::connect('OC_User', 'post_deleteGroup', 'OC\Share20\Hooks', 'post_deleteGroup');
 		}
 	}

+ 38 - 0
lib/private/Share20/DefaultShareProvider.php

@@ -910,4 +910,42 @@ class DefaultShareProvider implements IShareProvider {
 			->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
 		$qb->execute();
 	}
+
+	/**
+	 * Delete custom group shares to this group for this user
+	 *
+	 * @param string $uid
+	 * @param string $gid
+	 */
+	public function userDeletedFromGroup($uid, $gid) {
+		/*
+		 * Get all group shares
+		 */
+		$qb = $this->dbConn->getQueryBuilder();
+		$qb->select('id')
+			->from('share')
+			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP)))
+			->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
+
+		$cursor = $qb->execute();
+		$ids = [];
+		while($row = $cursor->fetch()) {
+			$ids[] = (int)$row['id'];
+		}
+		$cursor->closeCursor();
+
+		if (!empty($ids)) {
+			$chunks = array_chunk($ids, 100);
+			foreach ($chunks as $chunk) {
+				/*
+				 * Delete all special shares wit this users for the found group shares
+				 */
+				$qb->delete('share')
+					->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
+					->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($uid)))
+					->andWhere($qb->expr()->in('parent', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)));
+				$qb->execute();
+			}
+		}
+	}
 }

+ 4 - 0
lib/private/Share20/Hooks.php

@@ -28,4 +28,8 @@ class Hooks {
 	public static function post_deleteGroup($arguments) {
 		\OC::$server->getShareManager()->groupDeleted($arguments['gid']);
 	}
+
+	public static function post_removeFromGroup($arguments) {
+		\OC::$server->getShareManager()->userDeletedFromGroup($arguments['uid'], $arguments['gid']);
+	}
 }

+ 8 - 0
lib/private/Share20/Manager.php

@@ -1056,6 +1056,14 @@ class Manager implements IManager {
 		$provider->groupDeleted($gid);
 	}
 
+	/**
+	 * @inheritdoc
+	 */
+	public function userDeletedFromGroup($uid, $gid) {
+		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
+		$provider->userDeletedFromGroup($uid, $gid);
+	}
+
 	/**
 	 * Get access list to a path. This means
 	 * all the users and groups that can access a given path.

+ 0 - 46
lib/private/share/hooks.php

@@ -1,46 +0,0 @@
-<?php
-/**
- * @author Björn Schießle <schiessle@owncloud.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <rullzer@owncloud.com>
- *
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Share;
-
-class Hooks extends \OC\Share\Constants {
-	/**
-	 * Function that is called after a user is removed from a group. Shares are cleaned up.
-	 * @param array $arguments
-	 */
-	public static function post_removeFromGroup($arguments) {
-		$sql = 'SELECT `id`, `share_type` FROM `*PREFIX*share`'
-			.' WHERE (`share_type` = ? AND `share_with` = ?) OR (`share_type` = ? AND `share_with` = ?)';
-		$result = \OC_DB::executeAudited($sql, array(self::SHARE_TYPE_GROUP, $arguments['gid'],
-			self::$shareTypeGroupUserUnique, $arguments['uid']));
-		while ($item = $result->fetchRow()) {
-			if ($item['share_type'] == self::SHARE_TYPE_GROUP) {
-				// Delete all reshares by this user of the group share
-				Helper::delete($item['id'], true, $arguments['uid']);
-			} else {
-				Helper::delete($item['id']);
-			}
-		}
-	}
-}

+ 11 - 1
lib/public/Share/IManager.php

@@ -164,11 +164,21 @@ interface IManager {
 	 * The group with $gid is deleted
 	 * We need to clear up all shares to this group
 	 *
-	 * @param $gid
+	 * @param string $gid
 	 * @since 9.1.0
 	 */
 	public function groupDeleted($gid);
 
+	/**
+	 * The user $uid is deleted from the group $gid
+	 * All user specific group shares have to be removed
+	 *
+	 * @param string $uid
+	 * @param string $gid
+	 * @since 9.1.0
+	 */
+	public function userDeletedFromGroup($uid, $gid);
+
 	/**
 	 * Instantiates a new share object. This is to be passed to
 	 * createShare.

+ 11 - 0
lib/public/Share/IShareProvider.php

@@ -166,4 +166,15 @@ interface IShareProvider {
 	 * @since 9.1.0
 	 */
 	public function groupDeleted($gid);
+
+	/**
+	 * A user is deleted from a group
+	 * We have to clean up all the related user specific group shares
+	 * Providers not handling group shares should just return
+	 *
+	 * @param string $uid
+	 * @param string $gid
+	 * @since 9.1.0
+	 */
+	public function userDeletedFromGroup($uid, $gid);
 }

+ 0 - 156
tests/lib/share/share.php

@@ -611,162 +611,6 @@ class Test_Share extends \Test\TestCase {
 		);
 	}
 
-	public function testShareWithGroup() {
-		// Invalid shares
-		$message = 'Sharing test.txt failed, because the group foobar does not exist';
-		try {
-			OCP\Share::shareItem('test', 'test.txt', OCP\Share::SHARE_TYPE_GROUP, 'foobar', \OCP\Constants::PERMISSION_READ);
-			$this->fail('Exception was expected: '.$message);
-		} catch (Exception $exception) {
-			$this->assertEquals($message, $exception->getMessage());
-		}
-		$policy = \OC::$server->getAppConfig()->getValue('core', 'shareapi_only_share_with_group_members', 'no');
-		\OC::$server->getAppConfig()->setValue('core', 'shareapi_only_share_with_group_members', 'yes');
-		$message = 'Sharing test.txt failed, because '.$this->user1.' is not a member of the group '.$this->group2;
-		try {
-			OCP\Share::shareItem('test', 'test.txt', OCP\Share::SHARE_TYPE_GROUP, $this->group2, \OCP\Constants::PERMISSION_READ);
-			$this->fail('Exception was expected: '.$message);
-		} catch (Exception $exception) {
-			$this->assertEquals($message, $exception->getMessage());
-		}
-		\OC::$server->getAppConfig()->setValue('core', 'shareapi_only_share_with_group_members', $policy);
-
-		// Valid share
-		$this->shareUserOneTestFileWithGroupOne();
-
-		// check if only the group share was created and not a single db-entry for each user
-		$statement = \OCP\DB::prepare('select `id` from `*PREFIX*share`');
-		$query = $statement->execute();
-		$result = $query->fetchAll();
-		$this->assertSame(1, count($result));
-
-
-		// Attempt to share again
-		OC_User::setUserId($this->user1);
-		$message = 'Sharing test.txt failed, because this item is already shared with '.$this->group1;
-		try {
-			OCP\Share::shareItem('test', 'test.txt', OCP\Share::SHARE_TYPE_GROUP, $this->group1, \OCP\Constants::PERMISSION_READ);
-			$this->fail('Exception was expected: '.$message);
-		} catch (Exception $exception) {
-			$this->assertEquals($message, $exception->getMessage());
-		}
-
-		// Attempt to share back to owner of group share
-		OC_User::setUserId($this->user2);
-		$message = 'Sharing failed, because the user '.$this->user1.' is the original sharer';
-		try {
-			OCP\Share::shareItem('test', 'test.txt', OCP\Share::SHARE_TYPE_USER, $this->user1, \OCP\Constants::PERMISSION_READ);
-			$this->fail('Exception was expected: '.$message);
-		} catch (Exception $exception) {
-			$this->assertEquals($message, $exception->getMessage());
-		}
-
-		// Attempt to share back to group
-		$message = 'Sharing test.txt failed, because this item is already shared with '.$this->group1;
-		try {
-			OCP\Share::shareItem('test', 'test.txt', OCP\Share::SHARE_TYPE_GROUP, $this->group1, \OCP\Constants::PERMISSION_READ);
-			$this->fail('Exception was expected: '.$message);
-		} catch (Exception $exception) {
-			$this->assertEquals($message, $exception->getMessage());
-		}
-
-		// Attempt to share back to member of group
-		$message ='Sharing test.txt failed, because this item is already shared with '.$this->user3;
-		try {
-			OCP\Share::shareItem('test', 'test.txt', OCP\Share::SHARE_TYPE_USER, $this->user3, \OCP\Constants::PERMISSION_READ);
-			$this->fail('Exception was expected: '.$message);
-		} catch (Exception $exception) {
-			$this->assertEquals($message, $exception->getMessage());
-		}
-
-		// Unshare
-		OC_User::setUserId($this->user1);
-		$this->assertTrue(OCP\Share::unshare('test', 'test.txt', OCP\Share::SHARE_TYPE_GROUP, $this->group1));
-
-		// Valid share with same person - user then group
-		$this->assertTrue(OCP\Share::shareItem('test', 'test.txt', OCP\Share::SHARE_TYPE_USER, $this->user2, \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_SHARE));
-		$this->assertTrue(OCP\Share::shareItem('test', 'test.txt', OCP\Share::SHARE_TYPE_GROUP, $this->group1, \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE));
-		OC_User::setUserId($this->user2);
-		$this->assertEquals(array('test.txt'), OCP\Share::getItemsSharedWith('test', Test_Share_Backend::FORMAT_TARGET));
-		$this->assertEquals(array(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_SHARE), OCP\Share::getItemSharedWith('test', 'test.txt', Test_Share_Backend::FORMAT_PERMISSIONS));
-		OC_User::setUserId($this->user3);
-		$this->assertEquals(array('test.txt'), OCP\Share::getItemsSharedWith('test', Test_Share_Backend::FORMAT_TARGET));
-		$this->assertEquals(array(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE), OCP\Share::getItemSharedWith('test', 'test.txt', Test_Share_Backend::FORMAT_PERMISSIONS));
-
-		// Valid reshare
-		OC_User::setUserId($this->user2);
-		$this->assertTrue(OCP\Share::shareItem('test', 'test.txt', OCP\Share::SHARE_TYPE_USER, $this->user4, \OCP\Constants::PERMISSION_READ));
-		OC_User::setUserId($this->user4);
-		$this->assertEquals(array('test.txt'), OCP\Share::getItemsSharedWith('test', Test_Share_Backend::FORMAT_TARGET));
-
-		// Unshare from user only
-		OC_User::setUserId($this->user1);
-		$this->assertTrue(OCP\Share::unshare('test', 'test.txt', OCP\Share::SHARE_TYPE_USER, $this->user2));
-		OC_User::setUserId($this->user2);
-		$this->assertEquals(array(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE), OCP\Share::getItemSharedWith('test', 'test.txt', Test_Share_Backend::FORMAT_PERMISSIONS));
-		OC_User::setUserId($this->user4);
-		$this->assertEquals(array('test.txt'), OCP\Share::getItemsSharedWith('test', Test_Share_Backend::FORMAT_TARGET));
-
-		// Valid share with same person - group then user
-		OC_User::setUserId($this->user1);
-		$this->assertTrue(OCP\Share::shareItem('test', 'test.txt', OCP\Share::SHARE_TYPE_USER, $this->user2, \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_DELETE));
-		OC_User::setUserId($this->user2);
-		$this->assertEquals(array('test.txt'), OCP\Share::getItemsSharedWith('test', Test_Share_Backend::FORMAT_TARGET));
-		$this->assertEquals(array(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE), OCP\Share::getItemSharedWith('test', 'test.txt', Test_Share_Backend::FORMAT_PERMISSIONS));
-
-		// Unshare from group only
-		OC_User::setUserId($this->user1);
-		$this->assertTrue(OCP\Share::unshare('test', 'test.txt', OCP\Share::SHARE_TYPE_GROUP, $this->group1));
-		OC_User::setUserId($this->user2);
-		$this->assertEquals(array(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_DELETE), OCP\Share::getItemSharedWith('test', 'test.txt', Test_Share_Backend::FORMAT_PERMISSIONS));
-
-		// Attempt user specific target conflict
-		OC_User::setUserId($this->user3);
-		\OCP\Util::connectHook('OCP\\Share', 'post_shared', 'DummyHookListener', 'listen');
-
-		$this->assertTrue(OCP\Share::shareItem('test', 'share.txt', OCP\Share::SHARE_TYPE_GROUP, $this->group1, \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_SHARE));
-		$this->assertEquals(OCP\Share::SHARE_TYPE_GROUP, DummyHookListener::$shareType);
-		OC_User::setUserId($this->user2);
-		$to_test = OCP\Share::getItemsSharedWith('test', Test_Share_Backend::FORMAT_TARGET);
-		$this->assertEquals(2, count($to_test));
-		$this->assertTrue(in_array('test.txt', $to_test));
-		$this->assertTrue(in_array('test1.txt', $to_test));
-
-		// Valid reshare
-		$this->assertTrue(OCP\Share::shareItem('test', 'share.txt', OCP\Share::SHARE_TYPE_USER, $this->user4, \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_SHARE));
-		OC_User::setUserId($this->user4);
-		$this->assertEquals(array('test1.txt'), OCP\Share::getItemsSharedWith('test', Test_Share_Backend::FORMAT_TARGET));
-
-		// Remove user from group
-		OC_Group::removeFromGroup($this->user2, $this->group1);
-		OC_User::setUserId($this->user2);
-		$this->assertEquals(array('test.txt'), OCP\Share::getItemsSharedWith('test', Test_Share_Backend::FORMAT_TARGET));
-		OC_User::setUserId($this->user4);
-		$this->assertEquals(array(), OCP\Share::getItemsSharedWith('test', Test_Share_Backend::FORMAT_TARGET));
-
-		// Add user to group
-		OC_Group::addToGroup($this->user4, $this->group1);
-		$this->assertEquals(array('test.txt'), OCP\Share::getItemsSharedWith('test', Test_Share_Backend::FORMAT_TARGET));
-
-		// Unshare from self
-		$this->assertTrue(OCP\Share::unshareFromSelf('test', 'test.txt'));
-		$this->assertEquals(array(), OCP\Share::getItemsSharedWith('test', Test_Share_Backend::FORMAT_TARGET));
-		OC_User::setUserId($this->user2);
-		$this->assertEquals(array('test.txt'), OCP\Share::getItemsSharedWith('test', Test_Share_Backend::FORMAT_TARGET));
-
-		// Unshare from self via source
-		OC_User::setUserId($this->user1);
-		$this->assertTrue(OCP\Share::unshareFromSelf('test', 'share.txt', true));
-		$this->assertEquals(array(), OCP\Share::getItemsSharedWith('test', Test_Share_Backend::FORMAT_TARGET));
-
-		// Remove group
-		OC_Group::deleteGroup($this->group1);
-		OC_User::setUserId($this->user4);
-		$this->assertEquals(array(), OCP\Share::getItemsSharedWith('test', Test_Share_Backend::FORMAT_TARGET));
-		OC_User::setUserId($this->user3);
-		$this->assertEquals(array(), OCP\Share::getItemsShared('test'));
-	}
-
 	/**
 	 * Test that unsharing from group will also delete all
 	 * child entries

+ 58 - 0
tests/lib/share20/defaultshareprovidertest.php

@@ -2093,4 +2093,62 @@ class DefaultShareProviderTest extends \Test\TestCase {
 
 		$this->assertCount($shouldBeDeleted ? 0 : count($ids), $data);
 	}
+
+	public function dataUserDeletedFromGroup() {
+		return [
+			['group1', 'user1', true],
+			['group1', 'user2', false],
+			['group2', 'user1', false],
+		];
+	}
+
+	/**
+	 * Given a group share with 'group1'
+	 * And a user specific group share with 'user1'.
+	 * User $user is deleted from group $gid.
+	 *
+	 * @dataProvider dataUserDeletedFromGroup
+	 *
+	 * @param string $group
+	 * @param string $user
+	 * @param bool $toDelete
+	 */
+	public function testUserDeletedFromGroup($group, $user, $toDelete) {
+		$qb = $this->dbConn->getQueryBuilder();
+		$qb->insert('share')
+			->setValue('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP))
+			->setValue('uid_owner', $qb->createNamedParameter('owner'))
+			->setValue('uid_initiator', $qb->createNamedParameter('initiator'))
+			->setValue('share_with', $qb->createNamedParameter('group1'))
+			->setValue('item_type', $qb->createNamedParameter('file'))
+			->setValue('item_source', $qb->createNamedParameter(42))
+			->setValue('file_source', $qb->createNamedParameter(42));
+		$qb->execute();
+		$id1 = $qb->getLastInsertId();
+
+		$qb = $this->dbConn->getQueryBuilder();
+		$qb->insert('share')
+			->setValue('share_type', $qb->createNamedParameter(2))
+			->setValue('uid_owner', $qb->createNamedParameter('owner'))
+			->setValue('uid_initiator', $qb->createNamedParameter('initiator'))
+			->setValue('share_with', $qb->createNamedParameter('user1'))
+			->setValue('item_type', $qb->createNamedParameter('file'))
+			->setValue('item_source', $qb->createNamedParameter(42))
+			->setValue('file_source', $qb->createNamedParameter(42))
+			->setValue('parent', $qb->createNamedParameter($id1));
+		$qb->execute();
+		$id2 = $qb->getLastInsertId();
+
+		$this->provider->userDeletedFromGroup($user, $group);
+
+		$qb = $this->dbConn->getQueryBuilder();
+		$qb->select('*')
+			->from('share')
+			->where($qb->expr()->eq('id', $qb->createNamedParameter($id2)));
+		$cursor = $qb->execute();
+		$data = $cursor->fetchAll();
+		$cursor->closeCursor();
+
+		$this->assertCount($toDelete ? 0 : 1, $data);
+	}
 }