Skip to content

Commit

Permalink
perf(sharing): Optimize getSharedWith to fetch permissions right away
Browse files Browse the repository at this point in the history
Signed-off-by: Julius Härtl <[email protected]>
  • Loading branch information
juliusknorr committed Dec 16, 2024
1 parent faab808 commit 117d4a3
Showing 1 changed file with 33 additions and 8 deletions.
41 changes: 33 additions & 8 deletions lib/Sharing/DeckShareProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,13 @@ private function createShareObject(array $data): IShare {
return $share;
}

private function applyBoardPermission($share, $permissions, $userId) {
private function applyBoardPermission($share, $permissions, $userId, ?array $shareToPermissionMap = null): void {
$cardId = (int)$share->getSharedWith();
if ($shareToPermissionMap !== null && isset($shareToPermissionMap[$cardId])) {
$share->setPermissions($this->permissionService->boardToFilePermission($shareToPermissionMap[$cardId]));
return;
}

try {
$this->permissionService->checkPermission($this->cardMapper, $share->getSharedWith(), Acl::PERMISSION_EDIT, $userId);
} catch (NoPermissionException $e) {
Expand Down Expand Up @@ -612,7 +618,7 @@ public function getShareById($id, $recipientId = null) {
* @param string $userId
* @return IShare[]
*/
private function resolveSharesForRecipient(array $shares, string $userId): array {
private function resolveSharesForRecipient(array $shares, string $userId, ?array $cardPermissionMap = null): array {
$result = [];

$start = 0;
Expand Down Expand Up @@ -649,7 +655,7 @@ private function resolveSharesForRecipient(array $shares, string $userId): array
$stmt = $query->execute();

while ($data = $stmt->fetch()) {
$this->applyBoardPermission($shareMap[$data['parent']], (int)$data['permissions'], $userId);
$this->applyBoardPermission($shareMap[$data['parent']], (int)$data['permissions'], $userId, $cardPermissionMap);
$shareMap[$data['parent']]->setTarget($data['file_target']);
}

Expand Down Expand Up @@ -698,14 +704,18 @@ public function getSharesByPath(Node $path): array {
* @return IShare[]
*/
public function getSharedWith($userId, $shareType, $node, $limit, $offset): array {
$allBoards = $this->boardMapper->findBoardIds($userId);

// We query all boards fully as we can reuse that to match permissions later on
$allBoards = $this->boardMapper->findAllForUser($userId);
$cardToBoardMapping = [];
/** @var IShare[] $shares */
$shares = [];

$start = 0;
while (true) {
$boards = array_slice($allBoards, $start, 1000);
$boardIds = array_map(function ($board) {
return $board->getId();
}, $boards);
$start += 1000;

if ($boards === []) {
Expand All @@ -719,13 +729,16 @@ public function getSharedWith($userId, $shareType, $node, $limit, $offset): arra
'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
)
->selectAlias('st.id', 'storage_string_id')
->selectAlias('db.id', 'board_id')
->from('share', 's')
->orderBy('s.id')
->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'))
->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'))
->leftJoin('s', 'deck_cards', 'dc', $qb->expr()->eq($qb->expr()->castColumn('dc.id', IQueryBuilder::PARAM_STR), 's.share_with'))
->leftJoin('dc', 'deck_stacks', 'ds', $qb->expr()->eq('dc.stack_id', 'ds.id'))
->leftJoin('ds', 'deck_boards', 'db', $qb->expr()->eq('ds.board_id', 'db.id'));
->leftJoin('ds', 'deck_boards', 'db', $qb->expr()->eq('ds.board_id', 'db.id'))
->where($qb->expr()->eq('dc.deleted_at', $qb->createNamedParameter(0)))
->andWhere($qb->expr()->eq('db.deleted_at', $qb->createNamedParameter(0)));

if ($limit !== -1) {
$qb->setMaxResults($limit);
Expand All @@ -738,7 +751,7 @@ public function getSharedWith($userId, $shareType, $node, $limit, $offset): arra

$qb->andWhere($qb->expr()->eq('s.share_type', $qb->createNamedParameter(IShare::TYPE_DECK)))
->andWhere($qb->expr()->in('db.id', $qb->createNamedParameter(
$boards,
$boardIds,
IQueryBuilder::PARAM_STR_ARRAY
)))
->andWhere($qb->expr()->orX(
Expand All @@ -757,11 +770,23 @@ public function getSharedWith($userId, $shareType, $node, $limit, $offset): arra
continue;
}
$shares[] = $this->createShareObject($data);
$cardToBoardMapping[(int)$data['share_with']] = $data['board_id'];
}
$cursor->closeCursor();
}

$shares = $this->resolveSharesForRecipient($shares, $userId);
$boardPermissions = [];
foreach ($allBoards as $board) {
$permissions = $this->permissionService->matchPermissions($board);
$boardPermissions[$board->getId()] = $permissions;
}

$cardPermissionMap = [];
foreach ($cardToBoardMapping as $cardId => $boardId) {
$cardPermissionMap[$cardId] = $boardPermissions[$boardId] ?? false;
}

$shares = $this->resolveSharesForRecipient($shares, $userId, $cardPermissionMap);

return $shares;
}
Expand Down

0 comments on commit 117d4a3

Please sign in to comment.