Skip to content
11 changes: 11 additions & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,17 @@
['name' => 'board_api#preflighted_cors', 'url' => '/api/v{apiVersion}/{path}','verb' => 'OPTIONS', 'requirements' => ['path' => '.+']],
],
'ocs' => [
['name' => 'new_board#index', 'url' => '/api/v{apiVersion}/boards', 'verb' => 'GET'],
['name' => 'new_board#read', 'url' => '/api/v{apiVersion}/board/{boardId}', 'verb' => 'GET'],
['name' => 'new_board#stacks', 'url' => '/api/v{apiVersion}/stacks/{boardId}', 'verb' => 'GET'],
['name' => 'new_board#create', 'url' => '/api/v{apiVersion}/boards', 'verb' => 'POST'],
['name' => 'new_board#addAcl', 'url' => '/api/v{apiVersion}/boards/{boardId}/acl', 'verb' => 'POST'],

['name' => 'new_card#create', 'url' => '/api/v{apiVersion}/cards', 'verb' => 'POST'],

['name' => 'new_stack#create', 'url' => '/api/v{apiVersion}/stacks', 'verb' => 'POST'],
['name' => 'new_stack#delete', 'url' => '/api/v{apiVersion}/stacks/{stackId}/{boardId}', 'verb' => 'DELETE', 'defaults' => ['boardId' => null]],

['name' => 'Config#get', 'url' => '/api/v{apiVersion}/config', 'verb' => 'GET'],
['name' => 'Config#setValue', 'url' => '/api/v{apiVersion}/config/{key}', 'verb' => 'POST'],

Expand Down
19 changes: 19 additions & 0 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use OCA\Deck\Event\SessionClosedEvent;
use OCA\Deck\Event\SessionCreatedEvent;
use OCA\Deck\Listeners\AclCreatedRemovedListener;
use OCA\Deck\Federation\DeckFederationProvider;
use OCA\Deck\Listeners\BeforeTemplateRenderedListener;
use OCA\Deck\Listeners\CommentEventListener;
use OCA\Deck\Listeners\FullTextSearchEventListener;
Expand All @@ -37,6 +38,7 @@
use OCA\Deck\Listeners\ResourceListener;
use OCA\Deck\Middleware\DefaultBoardMiddleware;
use OCA\Deck\Middleware\ExceptionMiddleware;
use OCA\Deck\Middleware\FederationMiddleware;
use OCA\Deck\Notification\Notifier;
use OCA\Deck\Reference\BoardReferenceProvider;
use OCA\Deck\Reference\CardReferenceProvider;
Expand All @@ -60,13 +62,17 @@
use OCP\Comments\CommentsEntityEvent;
use OCP\Comments\CommentsEvent;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Federation\ICloudFederationProviderManager;
use OCP\Group\Events\GroupDeletedEvent;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\OCM\Events\ResourceTypeRegisterEvent;
use OCP\Server;
use OCP\Share\IManager;
use OCP\User\Events\UserDeletedEvent;
use OCP\Util;
use Psr\Container\ContainerInterface;
use ResourceTypeRegisterListener;

class Application extends App implements IBootstrap {
public const APP_ID = 'deck';
Expand Down Expand Up @@ -102,6 +108,7 @@ public function boot(IBootContext $context): void {
$context->injectFn(function (Listener $listener, IEventDispatcher $eventDispatcher) {
$listener->register($eventDispatcher);
});
$context->injectFn($this->registerCloudFederationProvider(...));
}

public function register(IRegistrationContext $context): void {
Expand All @@ -110,6 +117,7 @@ public function register(IRegistrationContext $context): void {
}

$context->registerCapability(Capabilities::class);
$context->registerMiddleWare(FederationMiddleware::class);
$context->registerMiddleWare(ExceptionMiddleware::class);
$context->registerMiddleWare(DefaultBoardMiddleware::class);

Expand All @@ -134,6 +142,7 @@ public function register(IRegistrationContext $context): void {
$context->registerReferenceProvider(CommentReferenceProvider::class);

$context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class);
$context->registerEventListener(ResourceTypeRegisterEvent::class, ResourceTypeRegisterListener::class);

// Event listening to emit UserShareAccessUpdatedEvent for files_sharing
$context->registerEventListener(AclCreatedEvent::class, AclCreatedRemovedListener::class);
Expand Down Expand Up @@ -194,4 +203,14 @@ protected function registerCollaborationResources(IProviderManager $resourceMana
$resourceManager->registerResourceProvider(ResourceProvider::class);
$resourceManager->registerResourceProvider(ResourceProviderCard::class);
}

public function registerCloudFederationProvider(
ICloudFederationProviderManager $manager,
): void {
$manager->addCloudFederationProvider(
DeckFederationProvider::PROVIDER_ID,
"Deck Federation",
static fn () => Server::get(DeckFederationProvider::class),
);
}
}
6 changes: 4 additions & 2 deletions lib/Controller/BoardController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use OCA\Deck\Db\Board;
use OCA\Deck\NoPermissionException;
use OCA\Deck\Service\BoardService;
use OCA\Deck\Service\ExternalBoardService;
use OCA\Deck\Service\Importer\BoardImportService;
use OCA\Deck\Service\PermissionService;
use OCP\AppFramework\ApiController;
Expand All @@ -25,6 +26,7 @@
$appName,
IRequest $request,
private BoardService $boardService,
private ExternalBoardService $externalBoardService,
private PermissionService $permissionService,
private BoardImportService $boardImportService,
private IL10N $l10n,
Expand Down Expand Up @@ -83,8 +85,8 @@
* @param $participant
*/
#[NoAdminRequired]
public function addAcl(int $boardId, int $type, $participant, bool $permissionEdit, bool $permissionShare, bool $permissionManage): Acl {
return $this->boardService->addAcl($boardId, $type, $participant, $permissionEdit, $permissionShare, $permissionManage);
public function addAcl(int $boardId, int $type, $participant, bool $permissionEdit, bool $permissionShare, bool $permissionManage, ?string $remote = null): Acl {
return $this->boardService->addAcl($boardId, $type, $participant, $permissionEdit, $permissionShare, $permissionManage, $remote);

Check failure on line 89 in lib/Controller/BoardController.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

TooManyArguments

lib/Controller/BoardController.php:89:31: TooManyArguments: Too many arguments for method OCA\Deck\Service\BoardService::addacl - saw 7 (see https://psalm.dev/026)
}

/**
Expand Down
74 changes: 74 additions & 0 deletions lib/Controller/NewBoardController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

namespace OCA\Deck\Controller;

use OCA\Deck\Service\BoardService;
use OCA\Deck\Service\StackService;
use OCA\Deck\Service\ExternalBoardService;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCSController;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\Attribute\PublicPage;
use OCP\AppFramework\Http\Attribute\RequestHeader;
use OCP\IRequest;
use Psr\Log\LoggerInterface;

class NewBoardController extends OCSController{
public function __construct(
string $appName,
IRequest $request,
private BoardService $boardService,
private ExternalBoardService $externalBoardService,
private LoggerInterface $logger,
private StackService $stackService,
private $userId,
) {
parent::__construct($appName, $request);
}

#[NoAdminRequired]
public function index(): DataResponse {
$internalBoards = $this->boardService->findAll();
return new DataResponse($internalBoards);
}

#[NoAdminRequired]
#[PublicPage]
#[NoCSRFRequired]

Check failure on line 37 in lib/Controller/NewBoardController.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

UndefinedAttributeClass

lib/Controller/NewBoardController.php:37:4: UndefinedAttributeClass: Attribute class OCA\Deck\Controller\NoCSRFRequired does not exist (see https://psalm.dev/241)
#[RequestHeader(name: 'x-nextcloud-federation', description: 'Set to 1 when the request is performed by another Nextcloud Server to indicate a federation request', indirect: true)]
public function read(int $boardId): DataResponse {
// Board on this instance -> get it from database
$localBoard = $this->boardService->find($boardId, true, true, $this->request->getParam('accessToken'));

Check failure on line 41 in lib/Controller/NewBoardController.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

TooManyArguments

lib/Controller/NewBoardController.php:41:38: TooManyArguments: Too many arguments for method OCA\Deck\Service\BoardService::find - saw 4 (see https://psalm.dev/026)
if($localBoard->getExternalId() !== null) {
return $this->externalBoardService->getExternalBoardFromRemote($localBoard);
}
// Board on other instance -> get it from other instance
return new DataResponse($localBoard);
}

#[NoAdminrequired]
#[NoCSRFRequired]

Check failure on line 50 in lib/Controller/NewBoardController.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

UndefinedAttributeClass

lib/Controller/NewBoardController.php:50:4: UndefinedAttributeClass: Attribute class OCA\Deck\Controller\NoCSRFRequired does not exist (see https://psalm.dev/241)
public function create(string $title, string $color,): DataResponse {
return new DataResponse( $this->boardService->create($title, $this->userId, $color));
}

#[NoAdminRequired]
#[PublicPage]
#[NoCSRFRequired]

Check failure on line 57 in lib/Controller/NewBoardController.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

UndefinedAttributeClass

lib/Controller/NewBoardController.php:57:4: UndefinedAttributeClass: Attribute class OCA\Deck\Controller\NoCSRFRequired does not exist (see https://psalm.dev/241)
#[RequestHeader(name: 'x-nextcloud-federation', description: 'Set to 1 when the request is performed by another Nextcloud Server to indicate a federation request', indirect: true)]
public function stacks(int $boardId): DataResponse{
$localBoard = $this->boardService->find($boardId, true, true, $this->request->getParam('accessToken'));

Check failure on line 60 in lib/Controller/NewBoardController.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

TooManyArguments

lib/Controller/NewBoardController.php:60:38: TooManyArguments: Too many arguments for method OCA\Deck\Service\BoardService::find - saw 4 (see https://psalm.dev/026)
// Board on other instance -> get it from other instance
if($localBoard->getExternalId() !== null) {
return $this->externalBoardService->getExternalStacksFromRemote($localBoard);
} else {
return new DataResponse($this->stackService->findAll($boardId));
}
}

#[NoAdminRequired]
#[NoCSRFRequired]

Check failure on line 70 in lib/Controller/NewBoardController.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

UndefinedAttributeClass

lib/Controller/NewBoardController.php:70:4: UndefinedAttributeClass: Attribute class OCA\Deck\Controller\NoCSRFRequired does not exist (see https://psalm.dev/241)
public function addAcl(int $boardId, int $type, $participant, bool $permissionEdit, bool $permissionShare, bool $permissionManage, ?string $remote = null): DataResponse {
return new DataResponse($this->boardService->addAcl($boardId, $type, $participant, $permissionEdit, $permissionShare, $permissionManage, $remote));

Check failure on line 72 in lib/Controller/NewBoardController.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

TooManyArguments

lib/Controller/NewBoardController.php:72:48: TooManyArguments: Too many arguments for method OCA\Deck\Service\BoardService::addacl - saw 7 (see https://psalm.dev/026)
}
}
60 changes: 60 additions & 0 deletions lib/Controller/NewCardController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace OCA\Deck\Controller;

use OCP\AppFramework\OCSController;
use OCA\Deck\Service\StackService;
use OCA\Deck\Service\CardService;
use OCA\Deck\Service\BoardService;
use OCA\Deck\Service\ExternalBoardService;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\Attribute\PublicPage;
use OCP\AppFramework\Http\Attribute\RequestHeader;
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
use OCP\IRequest;


class NewCardController extends OCSController {
public function __construct(
string $appName,
IRequest $request,
private CardService $cardService,
private StackService $stackService,
private BoardService $boardService,
private ExternalBoardService $externalBoardService,
private ?string $userId,
) {
parent::__construct($appName, $request);
}

#[NoAdminRequired]
#[PublicPage]
#[NoCSRFRequired]
#[RequestHeader(name: 'x-nextcloud-federation', description: 'Set to 1 when the request is performed by another Nextcloud Server to indicate a federation request', indirect: true)]
public function create(string $title, int $stackId, ?int $boardId=null, ?string $type = 'plain',?string $owner = null,?int $order = 999, ?string $description = '', $duedate = null, ?array $labels = [], ?array $users = []) {
if ($boardId) {
$board = $this->boardService->find($boardId, false);
if ($board->getExternalId()) {
$card = $this->externalBoardService->createCardOnRemote($board, $title, $stackId, $type, $order, $description, $duedate, $users);
return new DataResponse($card);
}
}

if (!$owner) {
$owner = $this->userId;
}
$card = $this->cardService->create($title, $stackId, $type, $order, $owner, $description, $duedate);

// foreach ($labels as $label) {
// $this->assignLabel($card->getId(), $label);
// }

// foreach ($users as $user) {
// $this->assignmentService->assignUser($card->getId(), $user['id'], $user['type']);
// }

return new DataResponse($card);
}

}
58 changes: 58 additions & 0 deletions lib/Controller/NewStackController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php
namespace OCA\Deck\Controller;


use OCP\AppFramework\OCSController;
use OCA\Deck\Service\ExternalBoardService;
use OCA\Deck\Service\BoardService;
use OCA\Deck\Service\StackService;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\Attribute\PublicPage;
use OCP\AppFramework\Http\Attribute\RequestHeader;
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
use OCP\IRequest;

class NewStackController extends OCSController {
public function __construct(
string $appName,
IRequest $request,
private ExternalBoardService $externalBoardService,
private BoardService $boardService,
private StackService $stackService,
){
parent::__construct($appName, $request);
}

#[NoAdminRequired]
#[PublicPage]
#[NoCSRFRequired]
#[RequestHeader(name: 'x-nextcloud-federation', description: 'Set to 1 when the request is performed by another Nextcloud Server to indicate a federation request', indirect: true)]
public function create(string $title, int $boardId, int $order = 0) {
$board = $this->boardService->find($boardId, false);
if ($board->getExternalId()) {
$stack = $this->externalBoardService->createStackOnRemote($board, $title, $order);
return new DataResponse($stack);
} else {
$stack = $this->stackService->create($title, $boardId, $order);
return new DataResponse($stack);
};
}

#[NoAdminRequired]
#[PublicPage]
#[NoCSRFRequired]
#[RequestHeader(name: 'x-nextcloud-federation', description: 'Set to 1 when the request is performed by another Nextcloud Server to indicate a federation request', indirect: true)]
public function delete(int $stackId, ?int $boardId = null) {
if ($boardId) {
$board = $this->boardService->find($boardId, false);
if ($board->getExternalId()) {
$result = $this->externalBoardService->deleteStackOnRemote($board, $stackId);
return new DataResponse($result);
}
}
$result = $this->stackService->delete($stackId);
return new DataResponse($result);
}

}
6 changes: 5 additions & 1 deletion lib/Controller/PageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use OCA\Deck\Db\Acl;
use OCA\Deck\Db\CardMapper;
use OCA\Deck\Service\BoardService;
use OCA\Deck\Service\ExternalBoardService;
use OCA\Deck\Service\CardService;
use OCA\Deck\Service\ConfigService;
use OCA\Deck\Service\PermissionService;
Expand All @@ -36,6 +37,7 @@ public function __construct(
private PermissionService $permissionService,
private IInitialState $initialState,
private BoardService $boardService,
private ExternalBoardService $externalBoardService,
private ConfigService $configService,
private IEventDispatcher $eventDispatcher,
private CardMapper $cardMapper,
Expand All @@ -53,7 +55,9 @@ public function index(): TemplateResponse {
$this->initialState->provideInitialState('canCreate', $this->permissionService->canCreate());
$this->initialState->provideInitialState('config', $this->configService->getAll());

$this->initialState->provideInitialState('initialBoards', $this->boardService->findAll());
$this->initialState->provideInitialState('initialBoards', [
$this->boardService->findAll(),
]);

$this->eventDispatcher->dispatchTyped(new LoadSidebar());
$this->eventDispatcher->dispatchTyped(new CollaborationResourcesEvent());
Expand Down
5 changes: 5 additions & 0 deletions lib/Db/Acl.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
* @method void setType(int $type)
* @method bool isOwner()
* @method void setOwner(int $owner)
* @method void setToken(string $token)
* @method string getToken()
*
*/
class Acl extends RelationalEntity {
Expand All @@ -29,6 +31,7 @@ class Acl extends RelationalEntity {

public const PERMISSION_TYPE_USER = 0;
public const PERMISSION_TYPE_GROUP = 1;
public const PERMISSION_TYPE_REMOTE = 6;
public const PERMISSION_TYPE_CIRCLE = 7;

protected $participant;
Expand All @@ -38,6 +41,7 @@ class Acl extends RelationalEntity {
protected $permissionShare = false;
protected $permissionManage = false;
protected $owner = false;
protected $token = null;

public function __construct() {
$this->addType('id', 'integer');
Expand All @@ -47,6 +51,7 @@ public function __construct() {
$this->addType('permissionManage', 'boolean');
$this->addType('type', 'integer');
$this->addType('owner', 'boolean');
$this->addType('token', 'string');
$this->addRelation('owner');
$this->addResolvable('participant');
}
Expand Down
12 changes: 11 additions & 1 deletion lib/Db/AclMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,23 @@ public function __construct(IDBConnection $db) {
parent::__construct($db, 'deck_board_acl', Acl::class);
}

public function findByAccessToken(string $accessToken){
$qb = $this->db->getQueryBuilder();
$qb->select('id', 'board_id', 'type', 'participant', 'permission_edit', 'permission_share', 'permission_manage', 'token')
->from('deck_board_acl')
->where($qb->expr()->eq('token', $qb->createNamedParameter($accessToken, IQueryBuilder::PARAM_STR)))
->setMaxResults(1);

return $this->findEntity($qb);
}

/**
* @return Acl[]
* @throws \OCP\DB\Exception
*/
public function findAll(int $boardId, ?int $limit = null, ?int $offset = null) {
$qb = $this->db->getQueryBuilder();
$qb->select('id', 'board_id', 'type', 'participant', 'permission_edit', 'permission_share', 'permission_manage')
$qb->select('id', 'board_id', 'type', 'participant', 'permission_edit', 'permission_share', 'permission_manage', 'token')
->from('deck_board_acl')
->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
->setMaxResults($limit)
Expand Down
Loading
Loading