Skip to content

Commit dd7f265

Browse files
committed
feat: Implement a team resource provider
Signed-off-by: Julius Härtl <jus@bitgrid.net>
1 parent 0cbe129 commit dd7f265

5 files changed

Lines changed: 140 additions & 1 deletion

File tree

img/deck-current.svg

Lines changed: 8 additions & 0 deletions
Loading

lib/AppInfo/Application.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
use OCA\Deck\Service\PermissionService;
6363
use OCA\Deck\Sharing\DeckShareProvider;
6464
use OCA\Deck\Sharing\Listener;
65+
use OCA\Deck\Teams\DeckTeamResourceProvider;
6566
use OCA\Text\Event\LoadEditor;
6667
use OCP\AppFramework\App;
6768
use OCP\AppFramework\Bootstrap\IBootContext;
@@ -179,6 +180,8 @@ public function register(IRegistrationContext $context): void {
179180

180181
$context->registerNotifierService(Notifier::class);
181182
$context->registerEventListener(LoadAdditionalScriptsEvent::class, ResourceAdditionalScriptsListener::class);
183+
184+
$context->registerTeamResourceProvider(DeckTeamResourceProvider::class);
182185
}
183186

184187
public function registerCommentsEntity(IEventDispatcher $eventDispatcher): void {

lib/Db/BoardMapper.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@
2525

2626
use OCA\Deck\Service\CirclesService;
2727
use OCP\AppFramework\Db\DoesNotExistException;
28+
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
2829
use OCP\AppFramework\Db\QBMapper;
2930
use OCP\Cache\CappedMemoryCache;
31+
use OCP\DB\Exception;
3032
use OCP\DB\QueryBuilder\IQueryBuilder;
3133
use OCP\IDBConnection;
3234
use OCP\IGroupManager;
@@ -400,6 +402,51 @@ public function findAllByCircles(string $userId, ?int $limit = null, ?int $offse
400402
return $entries;
401403
}
402404

405+
public function findAllByTeam(string $teamId): array {
406+
$qb = $this->db->getQueryBuilder();
407+
$qb->select('b.id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified')
408+
->from('deck_boards', 'b')
409+
->innerJoin('b', 'deck_board_acl', 'acl', $qb->expr()->eq('b.id', 'acl.board_id'))
410+
->where($qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_CIRCLE, IQueryBuilder::PARAM_INT)))
411+
->andWhere($qb->expr()->eq('acl.participant', $qb->createNamedParameter($teamId, IQueryBuilder::PARAM_STR)));
412+
$entries = $this->findEntities($qb);
413+
foreach ($entries as $entry) {
414+
$entry->setShared(2);
415+
}
416+
return $entries;
417+
}
418+
419+
public function findTeamsForBoard(int $boardId): array {
420+
$qb = $this->db->getQueryBuilder();
421+
$qb->select('acl.participant')
422+
->from('deck_boards', 'b')
423+
->innerJoin('b', 'deck_board_acl', 'acl', $qb->expr()->eq('b.id', 'acl.board_id'))
424+
->where($qb->expr()->eq('b.id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
425+
->andWhere($qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_CIRCLE, IQueryBuilder::PARAM_INT)));
426+
427+
$result = $qb->executeQuery();
428+
return array_map(function($entry) {
429+
return $entry['participant'];
430+
}, $result->fetchAll());
431+
}
432+
433+
public function isSharedWithTeam(int $boardId, string $teamId): bool {
434+
$qb = $this->db->getQueryBuilder();
435+
$qb->select('b.id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified')
436+
->from('deck_boards', 'b')
437+
->innerJoin('b', 'deck_board_acl', 'acl', $qb->expr()->eq('b.id', 'acl.board_id'))
438+
->where($qb->expr()->eq('b.id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
439+
->andWhere($qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_CIRCLE, IQueryBuilder::PARAM_INT)))
440+
->andWhere($qb->expr()->eq('acl.participant', $qb->createNamedParameter($teamId, IQueryBuilder::PARAM_STR)));
441+
try {
442+
$this->findEntity($qb);
443+
return true;
444+
} catch (DoesNotExistException $e) {
445+
// Expected return falue
446+
}
447+
return false;
448+
}
449+
403450
public function findAll(): array {
404451
$qb = $this->db->getQueryBuilder();
405452
$qb->select('id')
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace OCA\Deck\Teams;
5+
6+
use OCA\Deck\AppInfo\Application;
7+
use OCA\Deck\Db\AclMapper;
8+
use OCA\Deck\Db\Board;
9+
use OCA\Deck\Db\BoardMapper;
10+
use OCP\IURLGenerator;
11+
use OCP\Teams\TeamResource;
12+
13+
/**
14+
* @copyright Copyright (c) 2024 Julius Härtl <jus@bitgrid.net>
15+
*
16+
* @author Julius Härtl <jus@bitgrid.net>
17+
*
18+
* @license GNU AGPL version 3 or any later version
19+
*
20+
* This program is free software: you can redistribute it and/or modify
21+
* it under the terms of the GNU Affero General Public License as
22+
* published by the Free Software Foundation, either version 3 of the
23+
* License, or (at your option) any later version.
24+
*
25+
* This program is distributed in the hope that it will be useful,
26+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
27+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28+
* GNU Affero General Public License for more details.
29+
*
30+
* You should have received a copy of the GNU Affero General Public License
31+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
32+
*/
33+
34+
class DeckTeamResourceProvider implements \OCP\Teams\ITeamResourceProvider {
35+
36+
public function __construct(
37+
private BoardMapper $boardMapper,
38+
private IURLGenerator $urlGenerator,
39+
) {
40+
}
41+
42+
43+
public function getId(): string {
44+
return Application::APP_ID;
45+
}
46+
47+
public function getName(): string {
48+
return 'Deck';
49+
}
50+
51+
public function getIconSvg(): string {
52+
return file_get_contents(__DIR__ . '/../../img/deck-current.svg');
53+
}
54+
55+
public function getSharedWith($teamId): array {
56+
$boards = $this->boardMapper->findAllByTeam($teamId);
57+
return array_map(function (Board $board) {
58+
return new TeamResource(
59+
$this,
60+
(string)$board->getId(),
61+
$board->getTitle(),
62+
$this->urlGenerator->linkToRouteAbsolute('deck.page.index') . '#/board/' . $board->getId(),
63+
$this->getBoardBulletIcon($board),
64+
$this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('deck', 'deck-current.svg')),
65+
);
66+
}, $boards);
67+
}
68+
69+
public function isSharedWithTeam(string $teamId, string $resourceId): bool {
70+
return $this->boardMapper->isSharedWithTeam((int)$resourceId, $teamId);
71+
}
72+
73+
public function getTeamsForResource(string $resourceId) {
74+
$teamIds = $this->boardMapper->findTeamsForBoard((int)$resourceId);
75+
return $teamIds;
76+
}
77+
78+
public function getBoardBulletIcon(Board $board): string {
79+
return '<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" viewBox="0 0 16 16"><g fill="#' . $board->getColor(). '"><rect ry="15" height="14" width="14" y="1" x="1"/></g></svg>';
80+
}
81+
}

tests/integration/config/behat.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ default:
55
- '%paths.base%/../features/'
66
contexts:
77
- ServerContext:
8-
baseUrl: http://localhost:8080/
8+
baseUrl: http://nextcloud.local
99
- RequestContext
1010
- BoardContext
1111
- CommentContext

0 commit comments

Comments
 (0)