mirror of https://github.com/nextcloud/bookmarks
Fix shares
- adjust db schema - listen to group changes - Add repair steps
This commit is contained in:
parent
e7eb042d7c
commit
d17c7cb96d
|
@ -18,11 +18,16 @@ use OCA\Bookmarks\Events\BeforeDeleteEvent;
|
|||
use OCA\Bookmarks\Events\CreateEvent;
|
||||
use OCA\Bookmarks\Events\MoveEvent;
|
||||
use OCA\Bookmarks\Events\UpdateEvent;
|
||||
use OCA\Bookmarks\Hooks\UserGroupListener;
|
||||
use OCA\Bookmarks\Hooks\UserHooks;
|
||||
use OCA\Bookmarks\Service\HashManager;
|
||||
use OCP\AppFramework\App;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\Group\Events\UserAddedEvent;
|
||||
use OCP\Group\Events\UserRemovedEvent;
|
||||
use OCP\IContainer;
|
||||
use OCP\IUser;
|
||||
use OCP\User\Events\BeforeUserDeletedEvent;
|
||||
|
||||
class Application extends App {
|
||||
public function __construct(array $urlParams = []) {
|
||||
|
@ -46,5 +51,8 @@ class Application extends App {
|
|||
$dispatcher->addServiceListener(UpdateEvent::class, HashManager::class);
|
||||
$dispatcher->addServiceListener(BeforeDeleteEvent::class, HashManager::class);
|
||||
$dispatcher->addServiceListener(MoveEvent::class, HashManager::class);
|
||||
$dispatcher->addServiceListener(BeforeUserDeletedEvent::class, UserGroupListener::class);
|
||||
$dispatcher->addServiceListener(UserAddedEvent::class, UserGroupListener::class);
|
||||
$dispatcher->addServiceListener(UserRemovedEvent::class, UserGroupListener::class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,11 +11,27 @@ use OCP\IConfig;
|
|||
use OCP\IUserManager;
|
||||
|
||||
class PreviewsJob extends TimedJob {
|
||||
/**
|
||||
* @var BookmarkPreviewer
|
||||
*/
|
||||
private $bookmarkPreviewer;
|
||||
/**
|
||||
* @var FaviconPreviewer
|
||||
*/
|
||||
private $faviconPreviewer;
|
||||
/**
|
||||
* @var BookmarkMapper
|
||||
*/
|
||||
private $bookmarkMapper;
|
||||
/**
|
||||
* @var IConfig
|
||||
*/
|
||||
private $settings;
|
||||
|
||||
public function __construct(
|
||||
IConfig $settings, IUserManager $userManager, BookmarkMapper $bookmarkMapper, BookmarkPreviewer $bookmarkPreviewer, FaviconPreviewer $faviconPreviewer
|
||||
IConfig $settings, BookmarkMapper $bookmarkMapper, BookmarkPreviewer $bookmarkPreviewer, FaviconPreviewer $faviconPreviewer
|
||||
) {
|
||||
$this->settings = $settings;
|
||||
$this->userManager = $userManager;
|
||||
$this->bookmarkMapper = $bookmarkMapper;
|
||||
$this->bookmarkPreviewer = $bookmarkPreviewer;
|
||||
$this->faviconPreviewer = $faviconPreviewer;
|
||||
|
|
|
@ -81,7 +81,7 @@ class BookmarkMapper extends QBMapper {
|
|||
public function find(int $id): Entity {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb
|
||||
->select('*')
|
||||
->select(Bookmark::$columns)
|
||||
->from('bookmarks')
|
||||
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
|
||||
|
||||
|
@ -128,9 +128,10 @@ class BookmarkMapper extends QBMapper {
|
|||
->leftJoin('b', 'bookmarks_tags', 't', $qb->expr()->eq('t.bookmark_id', 'b.id'))
|
||||
->leftJoin('b', 'bookmarks_tree', 'tr', $qb->expr()->eq('tr.id', 'b.id'))
|
||||
->leftJoin('tr', 'bookmarks_shares', 's', $qb->expr()->eq('tr.parent_folder', 's.folder_id'))
|
||||
->leftJoin('s', 'bookmarks_shared_folders', 'p', $qb->expr()->eq('s.id', 'p.share_id'))
|
||||
->leftJoin('s', 'bookmarks_shared_to_shares', 't', $qb->expr()->eq('s.id', 't.share_id'))
|
||||
->leftJoin('t', 'bookmarks_shared_folders', 'sf', $qb->expr()->eq('t.shred_folder_id', 'sf.id'))
|
||||
->where($qb->expr()->eq('b.user_id', $qb->createPositionalParameter($userId)))
|
||||
->orWhere($qb->expr()->eq('p.user_id', $qb->createPositionalParameter($userId)));
|
||||
->orWhere($qb->expr()->eq('sf.user_id', $qb->createPositionalParameter($userId)));
|
||||
|
||||
|
||||
$this->_findBookmarksBuildFilter($qb, $filters, $params);
|
||||
|
@ -398,7 +399,7 @@ class BookmarkMapper extends QBMapper {
|
|||
*/
|
||||
public function findPendingPreviews(int $limit, int $stalePeriod): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*');
|
||||
$qb->select(Bookmark::$columns);
|
||||
$qb->from('bookmarks', 'b');
|
||||
$qb->where($qb->expr()->lt('last_preview', $qb->createPositionalParameter(time() - $stalePeriod)));
|
||||
$qb->orWhere($qb->expr()->isNull('last_preview'));
|
||||
|
|
|
@ -115,9 +115,10 @@ class ShareMapper extends QBMapper {
|
|||
return 's.' . $c;
|
||||
}, Share::$columns))
|
||||
->from('bookmarks_shares', 's')
|
||||
->leftJoin('s', 'bookmarks_shared_folders', 'p', 's.id = p.share_id')
|
||||
->leftJoin('s', 'bookmarks_shared_to_shares', 't', 's.id = t.share_id')
|
||||
->leftJoin('t', 'bookmarks_shared_folders', 'sf', 'sf.id = t.shared_folder_id')
|
||||
->where($qb->expr()->eq('s.folder_id', $qb->createPositionalParameter($folderId)))
|
||||
->andWhere($qb->expr()->eq('p.user_id', $qb->createPositionalParameter($userId)));
|
||||
->andWhere($qb->expr()->eq('sf.user_id', $qb->createPositionalParameter($userId)));
|
||||
return $this->findEntity($qb);
|
||||
}
|
||||
|
||||
|
@ -132,9 +133,10 @@ class ShareMapper extends QBMapper {
|
|||
return 's.' . $c;
|
||||
}, Share::$columns))
|
||||
->from('bookmarks_shares', 's')
|
||||
->leftJoin('s', 'bookmarks_shared_folders', 'p', 's.id = p.share_id')
|
||||
->leftJoin('s', 'bookmarks_shared_to_shares', 't', 's.id = t.share_id')
|
||||
->leftJoin('t', 'bookmarks_shared_folders', 'sf', 's.shared_folder_id = sf.id')
|
||||
->where($qb->expr()->eq('s.owner', $qb->createPositionalParameter($owner)))
|
||||
->andWhere($qb->expr()->eq('p.user_id', $qb->createPositionalParameter($userId)));
|
||||
->andWhere($qb->expr()->eq('sf.user_id', $qb->createPositionalParameter($userId)));
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,17 +22,16 @@ class SharedFolder extends Entity {
|
|||
protected $title;
|
||||
protected $index;
|
||||
|
||||
public static $columns = ['id', 'share_id', 'user_id', 'title'];
|
||||
public static $columns = ['id', 'user_id', 'title'];
|
||||
|
||||
public function __construct() {
|
||||
// add types in constructor
|
||||
$this->addType('id', 'integer');
|
||||
$this->addType('shareId', 'integer');
|
||||
$this->addType('userId', 'string');
|
||||
$this->addType('title', 'string');
|
||||
}
|
||||
|
||||
public function toArray() {
|
||||
return ['title' => $this->title, 'userId' => $this->userId, 'shareId' => $this->shareId];
|
||||
return ['title' => $this->title, 'userId' => $this->userId];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,8 +37,9 @@ class SharedFolderMapper extends QBMapper {
|
|||
public function findByShare(int $shareId): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select(SharedFolder::$columns)
|
||||
->from('bookmarks_shared_folders')
|
||||
->where($qb->expr()->eq('share_id', $qb->createPositionalParameter($shareId)));
|
||||
->from('bookmarks_shared_folders', 'sf')
|
||||
->join('sf', 'bookmarks_shared_to_shares', 't', $qb->expr()->eq('sf.id', 't.shared_folder_id'))
|
||||
->where($qb->expr()->eq('t.share_id', $qb->createPositionalParameter($shareId)));
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
|
@ -49,11 +50,10 @@ class SharedFolderMapper extends QBMapper {
|
|||
public function findByFolder(int $folderId): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select(array_map(static function ($c) {
|
||||
return 'p.' . $c;
|
||||
return 'sf.' . $c;
|
||||
}, SharedFolder::$columns))
|
||||
->from('bookmarks_shared_folders', 'p')
|
||||
->leftJoin('p', 'bookmarks_shares', 's', 'p.share_id = s.id')
|
||||
->where($qb->expr()->eq('s.folder_id', $qb->createPositionalParameter($folderId)));
|
||||
->from('bookmarks_shared_folders', 'sf')
|
||||
->where($qb->expr()->eq('sf.folder_id', $qb->createPositionalParameter($folderId)));
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,8 @@ class SharedFolderMapper extends QBMapper {
|
|||
return 'p.' . $c;
|
||||
}, SharedFolder::$columns))
|
||||
->from('bookmarks_shared_folders', 'p')
|
||||
->leftJoin('p', 'bookmarks_shares', 's', 'p.share_id = s.id')
|
||||
->leftJoin('p', 'bookmarks_shared_to_shares', 't', 't.shared_folder_id = p.id')
|
||||
->leftJoin('t', 'bookmarks_shares', 's', 't.share_id = s.id')
|
||||
->where($qb->expr()->eq('s.owner', $qb->createPositionalParameter($userId)));
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
@ -83,7 +84,8 @@ class SharedFolderMapper extends QBMapper {
|
|||
return 'p.' . $c;
|
||||
}, SharedFolder::$columns))
|
||||
->from('bookmarks_shared_folders', 'p')
|
||||
->leftJoin('p', 'bookmarks_shares', 's', 'p.share_id = s.id')
|
||||
->leftJoin('p', 'bookmarks_shared_to_shares', 't', 'p.id = t.shared_folder_id')
|
||||
->leftJoin('t', 'bookmarks_shares', 's', 't.share_id = s.id')
|
||||
->where($qb->expr()->eq('s.participant', $qb->createPositionalParameter($participant)))
|
||||
->andWhere($qb->expr()->eq('s.type', $qb->createPositionalParameter($type)));
|
||||
return $this->findEntities($qb);
|
||||
|
@ -103,8 +105,9 @@ class SharedFolderMapper extends QBMapper {
|
|||
return 'p.' . $c;
|
||||
}, SharedFolder::$columns))
|
||||
->from('bookmarks_shared_folders', 'p')
|
||||
->leftJoin('p', 'bookmarks_shares', 's', 'p.share_id = s.id')
|
||||
->where($qb->expr()->eq('folder_id', $qb->createPositionalParameter($folderId)))
|
||||
->leftJoin('p', 'bookmarks_shared_to_shares', 't', 't.shared_folder_id = p.id')
|
||||
->leftJoin('t', 'bookmarks_shares', 's', 't.share_id = s.id')
|
||||
->where($qb->expr()->eq('p.folder_id', $qb->createPositionalParameter($folderId)))
|
||||
->andWhere($qb->expr()->eq('participant', $qb->createPositionalParameter($participant)))
|
||||
->andWhere($qb->expr()->eq('type', $qb->createPositionalParameter($type)));
|
||||
return $this->findEntity($qb);
|
||||
|
@ -123,8 +126,7 @@ class SharedFolderMapper extends QBMapper {
|
|||
return 'p.' . $c;
|
||||
}, SharedFolder::$columns))
|
||||
->from('bookmarks_shared_folders', 'p')
|
||||
->leftJoin('p', 'bookmarks_shares', 's', 'p.share_id = s.id')
|
||||
->where($qb->expr()->eq('s.folder_id', $qb->createPositionalParameter($folderId)))
|
||||
->where($qb->expr()->eq('p.folder_id', $qb->createPositionalParameter($folderId)))
|
||||
->andWhere($qb->expr()->eq('p.user_id', $qb->createPositionalParameter($userId)));
|
||||
return $this->findEntity($qb);
|
||||
}
|
||||
|
@ -140,7 +142,8 @@ class SharedFolderMapper extends QBMapper {
|
|||
return 'p.' . $c;
|
||||
}, SharedFolder::$columns))
|
||||
->from('bookmarks_shared_folders', 'p')
|
||||
->leftJoin('p', 'bookmarks_shares', 's', 'p.share_id = s.id')
|
||||
->leftJoin('p', 'bookmarks_shared_to_shares', 't', 'p.id = t.shared_folder_id')
|
||||
->leftJoin('t', 'bookmarks_shares', 's', 't.share_id = s.id')
|
||||
->where($qb->expr()->eq('s.owner', $qb->createPositionalParameter($owner)))
|
||||
->andWhere($qb->expr()->eq('p.user_id', $qb->createPositionalParameter($userId)));
|
||||
return $this->findEntities($qb);
|
||||
|
@ -159,9 +162,23 @@ class SharedFolderMapper extends QBMapper {
|
|||
return 'p.' . $c;
|
||||
}, SharedFolder::$columns))
|
||||
->from('bookmarks_shared_folder', 'p')
|
||||
->leftJoin('p', 'bookmarks_shares', 's', 'p.share_id = s.id')
|
||||
->where($qb->expr()->eq('s.share_id', $qb->createPositionalParameter($shareId)))
|
||||
->leftJoin('p', 'bookmarks_shared_to_shares', 't', 't.shared_folder_id = p.id')
|
||||
->where($qb->expr()->eq('t.share_id', $qb->createPositionalParameter($shareId)))
|
||||
->andWhere($qb->expr()->eq('p.user_id', $qb->createPositionalParameter($userId)));
|
||||
return $this->findEntity($qb);
|
||||
}
|
||||
|
||||
public function findByParticipantAndUser(int $type, string $participant, string $userId) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select(array_map(static function ($c) {
|
||||
return 'p.' . $c;
|
||||
}, SharedFolder::$columns))
|
||||
->from('bookmarks_shared_folders', 'p')
|
||||
->leftJoin('p', 'bookmarks_shared_to_shares', 't', 't.shared_folder_id = p.id')
|
||||
->leftJoin('t', 'bookmarks_shares', 's', 't.share_id = s.id')
|
||||
->where($qb->expr()->eq('s.participant', $qb->createPositionalParameter($participant)))
|
||||
->andWhere($qb->expr()->eq('s.type', $qb->createPositionalParameter($type)))
|
||||
->andWhere($qb->expr()->eq('p.user_id', $qb->createPositionalParameter($userId)));
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -479,17 +479,16 @@ class TreeMapper extends QBMapper {
|
|||
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb
|
||||
->select('folder_id', 'f.id')
|
||||
->from('bookmarks_shares', 's')
|
||||
->innerJoin('s', 'bookmarks_shared_folders', 'f', $qb->expr()->eq('f.share_id', 's.id'))
|
||||
->innerJoin('f', 'bookmarks_tree', 't', $qb->expr()->eq('t.id', 'f.id'))
|
||||
->select('folder_id', 'id')
|
||||
->from('bookmarks_shared_folder', 's')
|
||||
->innerJoin('s', 'bookmarks_tree', 't', $qb->expr()->eq('t.id', 's.id'))
|
||||
->where($qb->expr()->eq('t.parent_folder', $qb->createPositionalParameter($folderId)))
|
||||
->andWhere($qb->expr()->eq('t.type', $qb->createPositionalParameter(self::TYPE_SHARE)))
|
||||
->orderBy('t.index', 'ASC');
|
||||
$childShares = $qb->execute()->fetchAll();
|
||||
|
||||
$foldersToShares = array_reduce($childShares, static function ($dict, $shareRec) {
|
||||
$dict[$shareRec['folder_id']] = $shareRec['f.id'];
|
||||
$dict[$shareRec['folder_id']] = $shareRec['id'];
|
||||
return $dict;
|
||||
}, []);
|
||||
|
||||
|
@ -534,9 +533,8 @@ class TreeMapper extends QBMapper {
|
|||
$qb = $this->db->getQueryBuilder();
|
||||
$qb
|
||||
->select('folder_id', 'index')
|
||||
->from('bookmarks_shares', 's')
|
||||
->innerJoin('s', 'bookmarks_shared_folders', 'f', $qb->expr()->eq('f.share_id', 's.id'))
|
||||
->innerJoin('f', 'bookmarks_tree', 't', $qb->expr()->eq('t.id', 'f.id'))
|
||||
->from('bookmarks_shared_folders', 'sf')
|
||||
->innerJoin('f', 'bookmarks_tree', 't', $qb->expr()->eq('t.id', 'sf.id'))
|
||||
->where($qb->expr()->eq('t.parent_folder', $qb->createPositionalParameter($folderId)))
|
||||
->andWhere($qb->expr()->eq('t.type', $qb->createPositionalParameter(self::TYPE_SHARE)))
|
||||
->orderBy('t.index', 'ASC');
|
||||
|
@ -659,10 +657,9 @@ class TreeMapper extends QBMapper {
|
|||
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb
|
||||
->select('folder_id', 'f.title', 'user_id', 'index', 't.type')
|
||||
->from('bookmarks_shares', 's')
|
||||
->innerJoin('s', 'bookmarks_shared_folders', 'f', $qb->expr()->eq('f.share_id', 's.id'))
|
||||
->innerJoin('f', 'bookmarks_tree', 't', $qb->expr()->eq('t.id', 'f.id'))
|
||||
->select('folder_id', 's.title', 'user_id', 'index', 't.type')
|
||||
->from('bookmarks_shared_folders', 's')
|
||||
->innerJoin('f', 'bookmarks_tree', 't', $qb->expr()->eq('t.id', 's.id'))
|
||||
->where($qb->expr()->eq('t.parent_folder', $qb->createPositionalParameter($folderId)))
|
||||
->andWhere($qb->expr()->eq('t.type', $qb->createPositionalParameter(self::TYPE_SHARE)))
|
||||
->orderBy('t.index', 'ASC');
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
<?php
|
||||
|
||||
namespace OCA\Bookmarks\Hooks;
|
||||
|
||||
use OCA\Bookmarks\Db\Folder;
|
||||
use OCA\Bookmarks\Db\FolderMapper;
|
||||
use OCA\Bookmarks\Db\Share;
|
||||
use OCA\Bookmarks\Db\SharedFolderMapper;
|
||||
use OCA\Bookmarks\Db\ShareMapper;
|
||||
use OCA\Bookmarks\Db\TreeMapper;
|
||||
use OCA\Bookmarks\Service\BookmarkService;
|
||||
use OCA\Bookmarks\Service\FolderService;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventListener;
|
||||
use OCP\Group\Events\BeforeGroupDeletedEvent;
|
||||
use OCP\Group\Events\UserAddedEvent;
|
||||
use OCP\Group\Events\UserRemovedEvent;
|
||||
use OCP\IGroup;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserManager;
|
||||
use OCP\Share\IShare;
|
||||
use OCP\User\Events\BeforeUserDeletedEvent;
|
||||
|
||||
class UserGroupListener implements IEventListener {
|
||||
|
||||
private $userManager;
|
||||
/**
|
||||
* @var ShareMapper
|
||||
*/
|
||||
private $shareMapper;
|
||||
/**
|
||||
* @var SharedFolderMapper
|
||||
*/
|
||||
private $sharedFolderMapper;
|
||||
/**
|
||||
* @var FolderService
|
||||
*/
|
||||
private $folders;
|
||||
/**
|
||||
* @var FolderMapper
|
||||
*/
|
||||
private $folderMapper;
|
||||
/**
|
||||
* @var TreeMapper
|
||||
*/
|
||||
private $treeMapper;
|
||||
/**
|
||||
* @var BookmarkService
|
||||
*/
|
||||
private $bookmarks;
|
||||
|
||||
public function __construct(ShareMapper $shareMapper, SharedFolderMapper $sharedFolderMapper, FolderService $folders, FolderMapper $folderMapper, TreeMapper $treeMapper, BookmarkService $bookmarks) {
|
||||
$this->shareMapper = $shareMapper;
|
||||
$this->sharedFolderMapper = $sharedFolderMapper;
|
||||
$this->folders = $folders;
|
||||
$this->folderMapper = $folderMapper;
|
||||
$this->treeMapper = $treeMapper;
|
||||
$this->bookmarks = $bookmarks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Event $event
|
||||
* @throws \OCA\Bookmarks\Exception\UnsupportedOperation
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
*/
|
||||
public function handle(Event $event): void {
|
||||
if ($event instanceof BeforeUserDeletedEvent) {
|
||||
$this->preDeleteUser($event->getUser());
|
||||
}
|
||||
if ($event instanceof UserAddedEvent) {
|
||||
$this->postAddUser($event->getGroup(), $event->getUser());
|
||||
}
|
||||
if ($event instanceof UserRemovedEvent) {
|
||||
$this->preRemoveUser($event->getGroup(), $event->getUser());
|
||||
}
|
||||
if ($event instanceof BeforeGroupDeletedEvent) {
|
||||
$this->preDeleteGroup($event->getGroup());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IUser $user
|
||||
* @throws \OCA\Bookmarks\Exception\UnsupportedOperation
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
*/
|
||||
public function preDeleteUser(IUser $user): void {
|
||||
$this->bookmarks->deleteAll($user->getUID());
|
||||
// delete dangling shares
|
||||
$sharesToDelete = $this->shareMapper->findByParticipant(IShare::TYPE_USER, $user->getUID());
|
||||
foreach ($sharesToDelete as $share) {
|
||||
$this->shareMapper->delete($share);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IGroup $group
|
||||
*/
|
||||
public function preDeleteGroup(IGroup $group): void {
|
||||
$sharesToDelete = $this->shareMapper->findByParticipant(IShare::TYPE_GROUP, $group->getGID());
|
||||
foreach ($sharesToDelete as $share) {
|
||||
$this->shareMapper->delete($share);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IGroup $group
|
||||
* @param IUser $user
|
||||
* @throws \OCA\Bookmarks\Exception\UnsupportedOperation
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
*/
|
||||
public function preRemoveUser(IGroup $group, IUser $user): void {
|
||||
$sharedFoldersToDelete = $this->sharedFolderMapper->findByParticipantAndUser(IShare::TYPE_GROUP, $group->getGID(), $user->getUID());
|
||||
foreach ($sharedFoldersToDelete as $sharedFolder) {
|
||||
$this->treeMapper->deleteEntry(TreeMapper::TYPE_SHARE, $sharedFolder->getId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IGroup $group
|
||||
* @param IUser $user
|
||||
* @throws \OCA\Bookmarks\Exception\UnsupportedOperation
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
*/
|
||||
public function postAddUser(IGroup $group, IUser $user): void {
|
||||
/**
|
||||
* @var Share[] $shares
|
||||
*/
|
||||
$shares = $this->shareMapper->findByParticipant(IShare::TYPE_GROUP, $group->getGID());
|
||||
foreach ($shares as $share) {
|
||||
if ($share->getOwner() === $user->getUID()) {
|
||||
continue;
|
||||
}
|
||||
/**
|
||||
* @var Folder $folder
|
||||
*/
|
||||
$folder = $this->folderMapper->find($share->getFolderId());
|
||||
$this->folders->addSharedFolder($share, $folder, $user->getUID());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace OCA\Bookmarks\Migration;
|
||||
|
||||
|
||||
use OCA\Bookmarks\Db\Folder;
|
||||
use OCA\Bookmarks\Db\FolderMapper;
|
||||
use OCA\Bookmarks\Db\Share;
|
||||
use OCA\Bookmarks\Db\SharedFolder;
|
||||
use OCA\Bookmarks\Db\SharedFolderMapper;
|
||||
use OCA\Bookmarks\Db\ShareMapper;
|
||||
use OCA\Bookmarks\Db\TreeMapper;
|
||||
use OCA\Bookmarks\Service\FolderService;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IUser;
|
||||
use OCP\Migration\IOutput;
|
||||
use OCP\Migration\IRepairStep;
|
||||
use OCP\Share\IShare;
|
||||
|
||||
class GroupSharesUpdateRepairStep implements IRepairStep {
|
||||
/**
|
||||
* @var IDBConnection
|
||||
*/
|
||||
private $db;
|
||||
/**
|
||||
* @var \OCP\IGroupManager
|
||||
*/
|
||||
private $groupManager;
|
||||
/**
|
||||
* @var FolderService
|
||||
*/
|
||||
private $folders;
|
||||
/**
|
||||
* @var ShareMapper
|
||||
*/
|
||||
private $shareMapper;
|
||||
/**
|
||||
* @var FolderMapper
|
||||
*/
|
||||
private $folderMapper;
|
||||
/**
|
||||
* @var SharedFolderMapper
|
||||
*/
|
||||
private $sharedFolderMapper;
|
||||
|
||||
public function __construct(IDBConnection $db, \OCP\IGroupManager $groupManager, FolderService $folders, ShareMapper $shareMapper, FolderMapper $folderMapper, SharedFolderMapper $sharedFolderMapper) {
|
||||
$this->db = $db;
|
||||
$this->groupManager = $groupManager;
|
||||
$this->folders = $folders;
|
||||
$this->shareMapper = $shareMapper;
|
||||
$this->folderMapper = $folderMapper;
|
||||
$this->sharedFolderMapper = $sharedFolderMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the step's name
|
||||
*/
|
||||
public function getName() {
|
||||
return 'Update bookmark group shares';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @throws \OCA\Bookmarks\Exception\UnsupportedOperation
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
*/
|
||||
public function run(IOutput $output) {
|
||||
$deleted = 0;
|
||||
$added = 0;
|
||||
$groups = 0;
|
||||
$deletedShares = 0;
|
||||
|
||||
// find group shares
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('s.id', 's.participant', 's.folder_id', 's.owner')
|
||||
->from('bookmarks_shares', 's')
|
||||
->where($qb->expr()->eq('s.type', $qb->createPositionalParameter(IShare::TYPE_GROUP)));
|
||||
$groupShares = $qb->execute();
|
||||
|
||||
while ($groupShare = $groupShares->fetch()) {
|
||||
|
||||
// find users in share
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('sf.user_id')
|
||||
->from('bookmarks_shared_folders', 'sf')
|
||||
->join('bookmarks_shared_to_shares', 't', $qb->expr()->eq('t.shared_folder_id', 'sf.id'))
|
||||
->where($qb->expr()->eq('t.share_id', $qb->createPositionalParameter($groupShare['id'])));
|
||||
$usersInShare = $qb->execute()->fetchAll(\PDO::FETCH_COLUMN);
|
||||
|
||||
$group = $this->groupManager->get($groupShare['participant']);
|
||||
if ($group === null) {
|
||||
$this->folders->deleteShare($groupShare['id']);
|
||||
$deletedShares++;
|
||||
continue;
|
||||
}
|
||||
$usersInGroup = array_filter(array_map(static function ($user) {
|
||||
return $user->getUID();
|
||||
}, $group->getUsers()), static function ($userId) use ($groupShare) {
|
||||
return $userId !== $groupShare['owner'];
|
||||
});
|
||||
|
||||
$notInShareUsers = array_diff($usersInGroup, $usersInShare);
|
||||
$notInGroupUsers = array_diff($usersInShare, $usersInGroup);
|
||||
|
||||
foreach ($notInGroupUsers as $userId) {
|
||||
$this->folders->deleteSharedFolderOrFolder($userId, $groupShare['folder_id']);
|
||||
$sharedFolder = $this->sharedFolderMapper->findByFolderAndUser($groupShare['folder_id'], $userId);
|
||||
$this->sharedFolderMapper->delete($sharedFolder);
|
||||
$deleted++;
|
||||
}
|
||||
|
||||
foreach ($notInShareUsers as $userId) {
|
||||
/**
|
||||
* @var Share $share
|
||||
*/
|
||||
$share = $this->shareMapper->find($groupShare['id']);
|
||||
/**
|
||||
* @var Folder $folder
|
||||
*/
|
||||
$folder = $this->folderMapper->find($groupShare['folder_id']);
|
||||
$this->folders->addSharedFolder($share, $folder, $userId);
|
||||
|
||||
$added++;
|
||||
}
|
||||
$groups++;
|
||||
}
|
||||
$output->info("Removed $deleted users and added $added users to $groups groups");
|
||||
$output->info("Removed $deletedShares shares");
|
||||
}
|
||||
}
|
|
@ -39,7 +39,8 @@ class OrphanedSharesRepairStep implements IRepairStep {
|
|||
$qb = $this->db->getQueryBuilder();
|
||||
$folders = $qb->select('f.id')
|
||||
->from('bookmarks_shared_folders', 'f')
|
||||
->where($qb->expr()->eq('f.share_id', $qb->createPositionalParameter($share)))
|
||||
->join('f', 'bookmarks_shared_to_shares', 't', $qb->expr()->eq('f.id', 't.shared_folder_id'))
|
||||
->where($qb->expr()->eq('t.share_id', $qb->createPositionalParameter($share)))
|
||||
->execute()
|
||||
->fetchAll(\PDO::FETCH_COLUMN);
|
||||
foreach ($folders as $folderId) {
|
||||
|
@ -50,9 +51,7 @@ class OrphanedSharesRepairStep implements IRepairStep {
|
|||
->execute();
|
||||
}
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->delete('bookmarks_shared_folders')
|
||||
->where($qb->expr()->eq('share_id', $qb->createPositionalParameter($share)))
|
||||
->execute();
|
||||
$this->db->executeQuery('DELETE sf FROM *PREFIX*bookmarks_shared_folders sf JOIN *PREFIX*bookmarks_shared_to_shares t ON sf.id = t.shared_folder_id WHERE t.share_id = ?', [$share]);
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->delete('bookmarks_shares')
|
||||
->where($qb->expr()->eq('id', $qb->createPositionalParameter($share)))
|
||||
|
|
|
@ -22,7 +22,7 @@ class OrphanedTreeItemsRepairStep implements IRepairStep {
|
|||
* Returns the step's name
|
||||
*/
|
||||
public function getName() {
|
||||
return 'Remove orphaned tree items';
|
||||
return 'Remove orphaned bookmark tree items';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,7 +22,7 @@ class SuperfluousSharedFoldersRepairStep implements IRepairStep {
|
|||
* Returns the step's name
|
||||
*/
|
||||
public function getName() {
|
||||
return 'Remove superfluous shared folders';
|
||||
return 'Remove superfluous shared bookmark folders';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,7 +33,8 @@ class SuperfluousSharedFoldersRepairStep implements IRepairStep {
|
|||
$qb->select('t.id')
|
||||
->from('bookmarks_tree', 't')
|
||||
->join('t', 'bookmarks_shared_folders', 'sf', $qb->expr()->eq('t.id', 'sf.id'))
|
||||
->join('sf', 'bookmarks_shares', 's', $qb->expr()->eq('sf.share_id', 's.id'))
|
||||
->join('sf', 'bookmarks_shared_to_shares', 't', $qb->expr()->eq('sf.id', 't.shared_folder_id'))
|
||||
->join('t', 'bookmarks_shares', 's', $qb->expr()->eq('t.share_id', 's.id'))
|
||||
->where($qb->expr()->eq('t.type', $qb->createPositionalParameter('share')))
|
||||
->andWhere($qb->expr()->eq('s.owner', 'sf.user_id'));
|
||||
$superfluousSharedFolders = $qb->execute();
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
namespace OCA\Bookmarks\Migration;
|
||||
|
||||
use Doctrine\DBAL\Types\BigIntType;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use OCP\DB\ISchemaWrapper;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\Migration\IOutput;
|
||||
use OCP\Migration\SimpleMigrationStep;
|
||||
|
||||
/**
|
||||
* Auto-generated migration step: Please modify to your needs!
|
||||
*/
|
||||
class Version003001000Date20200526094721 extends SimpleMigrationStep {
|
||||
private $db;
|
||||
|
||||
public function __construct(IDBConnection $db) {
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
*/
|
||||
public function preSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
* @return null|ISchemaWrapper
|
||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
||||
*/
|
||||
public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
/** @var ISchemaWrapper $schema */
|
||||
$schema = $schemaClosure();
|
||||
if (!$schema->hasTable('bookmarks_shared_to_shares')) {
|
||||
$table = $schema->createTable('bookmarks_shared_to_shares');
|
||||
$table->addColumn('shared_folder_id', 'bigint', [
|
||||
'notnull' => true,
|
||||
'length' => 64,
|
||||
]);
|
||||
$table->addColumn('share_id', 'bigint', [
|
||||
'notnull' => true,
|
||||
'length' => 64,
|
||||
]);
|
||||
$table->setPrimaryKey(['shared_folder_id', 'share_id']);
|
||||
$table->addIndex(['shared_folder_id'], 'bookmarks_shares_to_shares');
|
||||
$table->addIndex(['share_id'], 'bookmarks_share_to_shared');
|
||||
}
|
||||
$table = $schema->getTable('bookmarks_shared_folders');
|
||||
if (!$table->hasColumn('folder_id')) {
|
||||
$table->addColumn('folder_id', 'bigint', [
|
||||
'notnull' => true,
|
||||
'length' => 64,
|
||||
'default' => 0
|
||||
]);
|
||||
$table->addIndex(['folder_id'], 'bookmarks_shared_folder');
|
||||
}
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
*/
|
||||
public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
// Find all shared folders
|
||||
$sharedFolders = $qb->select('sf.share_id', 'sf.id', 's.folder_id', 'sf.user_id')
|
||||
->from('bookmarks_shared_folders', 'sf')
|
||||
->leftJoin('sf', 'bookmarks_shares', 's', $qb->expr()->eq('sf.share_id', 's.id'))
|
||||
->execute();
|
||||
while($sharedFolder = $sharedFolders->fetch()) {
|
||||
// Find a shared folder with folder_id already set. This is gonna be the only one we will have for this folder from now on.
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$canonicalSharedFolder = $qb->select('sf.id', 'sf.folder_id')
|
||||
->from('bookmarks_shared_folders', 'sf')
|
||||
->where($qb->expr()->eq('sf.folder_id', $qb->createPositionalParameter($sharedFolder['folder_id'])))
|
||||
->andWhere($qb->expr()->eq('sf.user_id', $qb->createPositionalParameter($sharedFolder['user_id'])))
|
||||
->execute()
|
||||
->fetch();
|
||||
if (!$canonicalSharedFolder) {
|
||||
// If there's no canonical shared folder, we make this one it.
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->update('bookmarks_shared_folders')
|
||||
->set('folder_id', $qb->createPositionalParameter($sharedFolder['folder_id']))
|
||||
->where($qb->expr()->eq('id', $qb->createPositionalParameter($sharedFolder['id'])))
|
||||
->execute();
|
||||
$canonicalSharedFolder = $sharedFolder;
|
||||
}else{
|
||||
// ...otherwise delete this shared folder.
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->delete('bookmarks_shared_folders')
|
||||
->where($qb->expr()->eq('id', $qb->createPositionalParameter($sharedFolder['id'])))
|
||||
->execute();
|
||||
}
|
||||
|
||||
// Insert into pivot table
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->insert('bookmarks_shared_to_shares')
|
||||
->values([
|
||||
'shared_folder_id' => $qb->createPositionalParameter($canonicalSharedFolder['id']),
|
||||
'share_id' => $qb->createPositionalParameter($sharedFolder['share_id'])
|
||||
])
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace OCA\Bookmarks\Migration;
|
||||
|
||||
use Doctrine\DBAL\Types\BigIntType;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use OCP\DB\ISchemaWrapper;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\Migration\IOutput;
|
||||
use OCP\Migration\SimpleMigrationStep;
|
||||
|
||||
/**
|
||||
* Auto-generated migration step: Please modify to your needs!
|
||||
*/
|
||||
class Version003001000Date20200526124721 extends SimpleMigrationStep {
|
||||
private $db;
|
||||
|
||||
public function __construct(IDBConnection $db) {
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
*/
|
||||
public function preSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
* @return null|ISchemaWrapper
|
||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
||||
*/
|
||||
public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
/** @var ISchemaWrapper $schema */
|
||||
$schema = $schemaClosure();
|
||||
if ($schema->hasTable('bookmarks_shared_folders')) {
|
||||
$table = $schema->getTable('bookmarks_shared_folders');
|
||||
$table->dropColumn('share_id');
|
||||
}
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
*/
|
||||
public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
}
|
||||
}
|
|
@ -183,7 +183,7 @@ class FolderService {
|
|||
* @var $sharedFolder SharedFolder
|
||||
*/
|
||||
$sharedFolder = $this->sharedFolderMapper->findByFolderAndUser($folder->getId(), $userId);
|
||||
$this->sharedFolderMapper->delete($sharedFolder);
|
||||
$this->treeMapper->deleteEntry(TreeMapper::TYPE_SHARE, $sharedFolder->getId());
|
||||
return;
|
||||
} catch (DoesNotExistException $e) {
|
||||
// noop
|
||||
|
@ -300,7 +300,7 @@ class FolderService {
|
|||
if ($participant === $folder->getUserId()) {
|
||||
throw new UnsupportedOperation('Cannot share with oneself');
|
||||
}
|
||||
$this->_addSharedFolder($share, $folder, $participant);
|
||||
$this->addSharedFolder($share, $folder, $participant);
|
||||
} else if ($type === IShare::TYPE_GROUP) {
|
||||
$group = $this->groupManager->get($participant);
|
||||
if ($group === null) {
|
||||
|
@ -320,7 +320,7 @@ class FolderService {
|
|||
// do nothing
|
||||
}
|
||||
|
||||
$this->_addSharedFolder($share, $folder, $user->getUID());
|
||||
$this->addSharedFolder($share, $folder, $user->getUID());
|
||||
}
|
||||
}
|
||||
return $share;
|
||||
|
@ -333,7 +333,7 @@ class FolderService {
|
|||
* @throws MultipleObjectsReturnedException
|
||||
* @throws UnsupportedOperation
|
||||
*/
|
||||
private function _addSharedFolder(Share $share, Folder $folder, string $userId): void {
|
||||
public function addSharedFolder(Share $share, Folder $folder, string $userId): void {
|
||||
$sharedFolder = new SharedFolder();
|
||||
$sharedFolder->setShareId($share->getId());
|
||||
$sharedFolder->setTitle($folder->getTitle());
|
||||
|
|
Loading…
Reference in New Issue