Skip to content

Commit a2e5011

Browse files
authored
Merge pull request #8390 from nextcloud/backport/8359/stable35
[stable35] enh(performance): get deck share permissions in one query
2 parents de9218f + 418de68 commit a2e5011

3 files changed

Lines changed: 69 additions & 17 deletions

File tree

‎lib/Db/AclMapper.php‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,33 @@ public function findAll(int $boardId, ?int $limit = null, ?int $offset = null) {
4444
return $this->findEntities($qb);
4545
}
4646

47+
/**
48+
* @return array<int, Acl[]> Acl entries grouped by card id
49+
* @throws \OCP\DB\Exception
50+
*/
51+
public function findInCards(array $cardIds, ?int $limit = null, ?int $offset = null): array {
52+
$qb = $this->db->getQueryBuilder();
53+
$qb->select('acl.id', 'acl.board_id', 'acl.type', 'acl.participant', 'acl.permission_edit', 'acl.permission_share', 'acl.permission_manage', 'acl.created_at', 'acl.last_modified_at', 'c.id AS card_id')
54+
->from('deck_board_acl', 'acl')
55+
->innerJoin('acl', 'deck_boards', 'b', 'acl.board_id = b.id')
56+
->innerJoin('b', 'deck_stacks', 's', 's.board_id = b.id')
57+
->innerJoin('s', 'deck_cards', 'c', 'c.stack_id = s.id')
58+
->where($qb->expr()->in('c.id', $qb->createParameter('cardIds')))
59+
->setMaxResults($limit)
60+
->setFirstResult($offset);
61+
62+
$aclsByCardId = [];
63+
foreach ($this->chunkQuery($cardIds, function (array $ids) use ($qb) {
64+
$qb->setParameter('cardIds', $ids, IQueryBuilder::PARAM_INT_ARRAY);
65+
return $qb->executeQuery()->fetchAll();
66+
}) as $row) {
67+
$cardId = (int)$row['card_id'];
68+
unset($row['card_id']);
69+
$aclsByCardId[$cardId][] = Acl::fromRow($row);
70+
}
71+
return $aclsByCardId;
72+
}
73+
4774
public function findIn(array $boardIds, ?int $limit = null, ?int $offset = null): array {
4875
$qb = $this->db->getQueryBuilder();
4976
$qb->select('id', 'board_id', 'type', 'participant', 'permission_edit', 'permission_share', 'permission_manage', 'created_at', 'last_modified_at')

‎lib/Service/PermissionService.php‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,31 @@ public function setAccessToken(string $token) {
6363
$this->accessToken = $token;
6464
}
6565

66+
/**
67+
* Get permissions for all supplied card ids
68+
* @param int[] $cardIds
69+
* @param ?string $userId
70+
* @param bool $allowDeleted
71+
* @return array<int, array<Acl::PERMISSION_*, bool>>
72+
*/
73+
public function getPermissionsForCards(array $cardIds, ?string $userId = null, bool $allowDeleted = false): array {
74+
if ($userId === null) {
75+
$userId = $this->userId;
76+
}
77+
$permissions = $this->aclMapper->findInCards($cardIds);
78+
return array_map(
79+
function (array $acls) use ($userId) {
80+
return [
81+
Acl::PERMISSION_READ => $this->userCan($acls, Acl::PERMISSION_READ, $userId),
82+
Acl::PERMISSION_EDIT => $this->userCan($acls, Acl::PERMISSION_EDIT, $userId),
83+
Acl::PERMISSION_MANAGE => $this->userCan($acls, Acl::PERMISSION_MANAGE, $userId),
84+
Acl::PERMISSION_SHARE => $this->userCan($acls, Acl::PERMISSION_SHARE, $userId),
85+
];
86+
},
87+
$permissions
88+
);
89+
}
90+
6691
/**
6792
* Get current user permissions for a board by id
6893
*

‎lib/Sharing/DeckShareProvider.php‎

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -269,22 +269,6 @@ private function createShareObject(array $data): IShare {
269269
return $share;
270270
}
271271

272-
private function applyBoardPermission($share, $permissions, $userId) {
273-
try {
274-
$this->permissionService->checkPermission($this->cardMapper, $share->getSharedWith(), Acl::PERMISSION_EDIT, $userId, true);
275-
} catch (NoPermissionException $e) {
276-
$permissions &= Constants::PERMISSION_ALL - Constants::PERMISSION_UPDATE;
277-
$permissions &= Constants::PERMISSION_ALL - Constants::PERMISSION_CREATE;
278-
$permissions &= Constants::PERMISSION_ALL - Constants::PERMISSION_DELETE;
279-
}
280-
281-
try {
282-
$this->permissionService->checkPermission($this->cardMapper, $share->getSharedWith(), Acl::PERMISSION_SHARE, $userId, true);
283-
} catch (NoPermissionException $e) {
284-
$permissions &= Constants::PERMISSION_ALL - Constants::PERMISSION_SHARE;
285-
}
286-
$share->setPermissions($permissions);
287-
}
288272
/**
289273
* @inheritDoc
290274
*/
@@ -652,11 +636,13 @@ private function resolveSharesForRecipient(array $shares, string $userId): array
652636

653637
/** @var int[] $ids */
654638
$ids = [];
639+
$cardIds = [];
655640
/** @var IShare[] $shareMap */
656641
$shareMap = [];
657642

658643
foreach ($shareSlice as $share) {
659644
$ids[] = (int)$share->getId();
645+
$cardIds[] = (int)$share->getSharedWith();
660646
$shareMap[$share->getId()] = $share;
661647
}
662648

@@ -673,8 +659,22 @@ private function resolveSharesForRecipient(array $shares, string $userId): array
673659

674660
$stmt = $query->executeQuery();
675661

662+
$permissions = $this->permissionService->getPermissionsForCards($cardIds, $userId);
663+
676664
while ($data = $stmt->fetch()) {
677-
$this->applyBoardPermission($shareMap[$data['parent']], (int)$data['permissions'], $userId);
665+
$parent = $shareMap[$data['parent']];
666+
$sharePermissions = (int)$data['permissions'];
667+
if (isset($permissions[(int)$parent->getSharedWith()])) {
668+
if ($permissions[(int)$parent->getSharedWith()][Acl::PERMISSION_EDIT] === false) {
669+
$sharePermissions &= Constants::PERMISSION_ALL - Constants::PERMISSION_UPDATE;
670+
$sharePermissions &= Constants::PERMISSION_ALL - Constants::PERMISSION_CREATE;
671+
$sharePermissions &= Constants::PERMISSION_ALL - Constants::PERMISSION_DELETE;
672+
}
673+
if ($permissions[(int)$parent->getSharedWith()][Acl::PERMISSION_SHARE] === false) {
674+
$sharePermissions &= Constants::PERMISSION_ALL - Constants::PERMISSION_SHARE;
675+
}
676+
}
677+
$shareMap[$data['parent']]->setPermissions($sharePermissions);
678678
$shareMap[$data['parent']]->setTarget($data['file_target']);
679679
}
680680

0 commit comments

Comments
 (0)