Merge pull request #535 from nextcloud/feature/83/json-api

REST API
This commit is contained in:
Julius Härtl
2018-08-15 21:21:25 +02:00
committed by GitHub
29 changed files with 2434 additions and 91 deletions

View File

@@ -3,6 +3,7 @@
* @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
* @author Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @license GNU AGPL version 3 or any later version
*
@@ -76,5 +77,43 @@ return [
['name' => 'label#update', 'url' => '/labels/{labelId}', 'verb' => 'PUT'],
['name' => 'label#delete', 'url' => '/labels/{labelId}', 'verb' => 'DELETE'],
// api
['name' => 'board_api#index', 'url' => '/api/v1.0/boards', 'verb' => 'GET'],
['name' => 'board_api#get', 'url' => '/api/v1.0/boards/{boardId}', 'verb' => 'GET'],
['name' => 'board_api#create', 'url' => '/api/v1.0/boards', 'verb' => 'POST'],
['name' => 'board_api#delete', 'url' => '/api/v1.0/boards/{boardId}', 'verb' => 'DELETE'],
['name' => 'board_api#update', 'url' => '/api/v1.0/boards/{boardId}', 'verb' => 'PUT'],
['name' => 'board_api#undo_delete', 'url' => '/api/v1.0/boards/{boardId}/undo_delete', 'verb' => 'POST'],
['name' => 'stack_api#index', 'url' => '/api/v1.0/boards/{boardId}/stacks', 'verb' => 'GET'],
['name' => 'stack_api#getArchived', 'url' => '/api/v1.0/boards/{boardId}/stacks/archived', 'verb' => 'GET'],
['name' => 'stack_api#get', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}', 'verb' => 'GET'],
['name' => 'stack_api#create', 'url' => '/api/v1.0/boards/{boardId}/stacks', 'verb' => 'POST'],
['name' => 'stack_api#update', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}', 'verb' => 'PUT'],
['name' => 'stack_api#delete', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}', 'verb' => 'DELETE'],
['name' => 'card_api#get', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}', 'verb' => 'GET'],
['name' => 'card_api#create', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards', 'verb' => 'POST'],
['name' => 'card_api#update', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}', 'verb' => 'PUT'],
['name' => 'card_api#assignLabel', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/assignLabel', 'verb' => 'PUT'],
['name' => 'card_api#removeLabel', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/removeLabel', 'verb' => 'PUT'],
['name' => 'card_api#assignUser', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/assignUser', 'verb' => 'PUT'],
['name' => 'card_api#unassignUser', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/unassignUser', 'verb' => 'PUT'],
['name' => 'card_api#reorder', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/reorder', 'verb' => 'PUT'],
['name' => 'card_api#delete', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}', 'verb' => 'DELETE'],
['name' => 'label_api#get', 'url' => '/api/v1.0/boards/{boardId}/labels/{labelId}', 'verb' => 'GET'],
['name' => 'label_api#create', 'url' => '/api/v1.0/boards/{boardId}/labels', 'verb' => 'POST'],
['name' => 'label_api#update', 'url' => '/api/v1.0/boards/{boardId}/labels/{labelId}', 'verb' => 'PUT'],
['name' => 'label_api#delete', 'url' => '/api/v1.0/boards/{boardId}/labels/{labelId}', 'verb' => 'DELETE'],
['name' => 'attachment_api#getAll', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments', 'verb' => 'GET'],
['name' => 'attachment_api#display', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments/{attachmentId}', 'verb' => 'GET'],
['name' => 'attachment_api#create', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments', 'verb' => 'POST'],
['name' => 'attachment_api#update', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments/{attachmentId}', 'verb' => 'PUT'],
['name' => 'attachment_api#delete', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments/{attachmentId}', 'verb' => 'DELETE'],
['name' => 'attachment_api#restore', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments/{attachmentId}/restore', 'verb' => 'PUT'],
['name' => 'board_api#preflighted_cors', 'url' => '/api/v1.0/{path}','verb' => 'OPTIONS', 'requirements' => ['path' => '.+']],
]
];

View File

@@ -0,0 +1,36 @@
<?php
/**
* @copyright Copyright (c) 2018 Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @author Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Deck;
use OCP\AppFramework\Http;
class BadRequestException extends StatusException {
public function __construct($message) {
parent::__construct($message);
}
public function getStatus() {
return HTTP::STATUS_BAD_REQUEST;
}
}

View File

@@ -0,0 +1,105 @@
<?php
/**
* @copyright Copyright (c) 2018 Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @author Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Deck\Controller;
use OCP\AppFramework\ApiController;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\IRequest;
use OCA\Deck\Service\AttachmentService;
class AttachmentApiController extends ApiController {
private $attachmentService;
public function __construct($appName, IRequest $request, AttachmentService $attachmentService) {
parent::__construct($appName, $request);
$this->attachmentService = $attachmentService;
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
*/
public function getAll() {
$attachment = $this->attachmentService->findAll($this->request->getParam('cardId'));
return new DataResponse($attachment, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
*/
public function display() {
$attachment = $this->attachmentService->display($this->request->getParam('cardId'), $this->request->getParam('attachmentId'));
return new DataResponse($attachment, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
*/
public function create($type, $data) {
$attachment = $this->attachmentService->create($this->request->getParam('cardId'), $type, $data);
return new DataResponse($attachment, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
*/
public function update($data) {
$attachment = $this->attachmentService->update($this->request->getParam('cardId'), $this->request->getParam('attachmentId'), $data);
return new DataResponse($attachment, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
*/
public function delete() {
$attachment = $this->attachmentService->delete($this->request->getParam('cardId'), $this->request->getParam('attachmentId'));
return new DataResponse($attachment, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
*/
public function restore() {
$attachment = $this->attachmentService->restore($this->request->getParam('cardId'), $this->request->getParam('attachmentId'));
return new DataResponse($attachment, HTTP::STATUS_OK);
}
}

View File

@@ -0,0 +1,137 @@
<?php
/**
* @copyright Copyright (c) 2017 Steven R. Baker <steven@stevenrbaker.com>
*
* @author Steven R. Baker <steven@stevenrbaker.com>
* @author Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Deck\Controller;
use OCP\AppFramework\ApiController;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\IRequest;
use OCA\Deck\Service\BoardService;
/**
* Class BoardApiController
*
* @package OCA\Deck\Controller
*/
class BoardApiController extends ApiController {
private $service;
/**
* @param string $appName
* @param IRequest $request
* @param BoardService $service
* @param $userId
*/
public function __construct($appName, IRequest $request, BoardService $service, $userId) {
parent::__construct($appName, $request);
$this->service = $service;
$this->userId = $userId;
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* Return all of the boards that the current user has access to.
*/
public function index() {
$boards = $this->service->findAll();
return new DataResponse($boards, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
*
* Return the board specified by $this->request->getParam('boardId').
*/
public function get() {
$board = $this->service->find($this->request->getParam('boardId'));
return new DataResponse($board, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* @params $title
* @params $color
*
* Create a board with the specified title and color.
*/
public function create($title, $color) {
$board = $this->service->create($title, $this->userId, $color);
return new DataResponse($board, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* @params $title
* @params $color
* @params $archived
*
* Update a board with the specified boardId, title and color, and archived state.
*/
public function update($title, $color, $archived = false) {
$board = $this->service->update($this->request->getParam('boardId'), $title, $color, $archived);
return new DataResponse($board, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
*
* Delete the board specified by $boardId. Return the board that was deleted.
*/
public function delete() {
$board = $this->service->delete($this->request->getParam('boardId'));
return new DataResponse($board, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
*
* Undo the deletion of the board specified by $boardId.
*/
public function undoDelete() {
$board = $this->service->deleteUndo($this->request->getParam('boardId'));
return new DataResponse($board, HTTP::STATUS_OK);
}
}

View File

@@ -35,40 +35,20 @@ use OCP\IGroupManager;
class BoardController extends ApiController {
private $userId;
private $boardService;
private $userManager;
private $groupManager;
private $permissionService;
private $userInfo;
public function __construct($appName, IRequest $request, IUserManager $userManager, IGroupManager $groupManager, BoardService $boardService, PermissionService $permissionService, $userId) {
public function __construct($appName, IRequest $request, BoardService $boardService, PermissionService $permissionService, $userId) {
parent::__construct($appName, $request);
$this->userId = $userId;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
$this->boardService = $boardService;
$this->permissionService = $permissionService;
$this->userInfo = $this->getBoardPrerequisites();
}
/**
* TODO: move to boardservice
* @return array
*/
private function getBoardPrerequisites() {
$groups = $this->groupManager->getUserGroupIds(
$this->userManager->get($this->userId)
);
return [
'user' => $this->userId,
'groups' => $groups
];
}
/**
* @NoAdminRequired
*/
public function index() {
return $this->boardService->findAll($this->userInfo);
return $this->boardService->findAll();
}
/**

View File

@@ -0,0 +1,158 @@
<?php
/**
* @copyright Copyright (c) 2018 Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @author Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Deck\Controller;
use OCP\AppFramework\ApiController;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\IRequest;
use OCA\Deck\Service\CardService;
/**
* Class BoardApiController
*
* @package OCA\Deck\Controller
*/
class CardApiController extends ApiController {
private $cardService;
private $userId;
/**
* @param string $appName
* @param IRequest $request
* @param CardService $cardService
* @param $userId
*/
public function __construct($appName, IRequest $request, CardService $cardService, $userId) {
parent::__construct($appName, $request);
$this->cardService = $cardService;
$this->userId = $userId;
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* Get a specific card.
*/
public function get() {
$card = $this->cardService->find($this->request->getParam('cardId'));
return new DataResponse($card, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* @params $title
* @params $type
* @params $order
*
* Get a specific card.
*/
public function create($title, $type = 'plain', $order = 999) {
$card = $this->cardService->create($title, $this->request->getParam('stackId'), $type, $order, $this->userId);
return new DataResponse($card, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
*
* Update a card
*/
public function update($title, $type, $order = 0, $description = '', $owner, $duedate = null) {
$card = $this->cardService->update($this->request->getParam('cardId'), $title, $this->request->getParam('stackId'), $type, $order, $description, $owner, $duedate, 0);
return new DataResponse($card, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* Delete a specific card.
*/
public function delete() {
$card = $this->cardService->delete($this->request->getParam('cardId'));
return new DataResponse($card, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* Assign a label to a card.
*/
public function assignLabel($labelId) {
$card = $this->cardService->assignLabel($this->request->getParam('cardId'), $labelId);
return new DataResponse($card, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* Assign a label to a card.
*/
public function removeLabel($labelId) {
$card = $this->cardService->removeLabel($this->request->getParam('cardId'), $labelId);
return new DataResponse($card, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* Unassign a label to a card.
*/
public function unassignUser($userId) {
$card = $this->cardService->unassignUser($this->request->getParam('cardId'), $userId);
return new DataResponse($card, HTTP::STATUS_OK);
}
public function assignUser($userId) {
$card = $this->cardService->assignUser($this->request->getParam('cardId'), $userId);;
return new DataResponse($card, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* Unassign a label to a card.
*/
public function reorder($stackId, $order) {
$card = $this->cardService->reorder($this->request->getParam('cardId'), $stackId, $order);
return new DataResponse($card, HTTP::STATUS_OK);
}
}

View File

@@ -0,0 +1,107 @@
<?php
/**
* @copyright Copyright (c) 2018 Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @author Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Deck\Controller;
use OCP\AppFramework\ApiController;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\IRequest;
use OCA\Deck\Service\LabelService;
use OCA\Deck\Controller\Helper\ApiHelper;
/**
* Class BoardApiController
*
* @package OCA\Deck\Controller
*/
class LabelApiController extends ApiController {
private $labelService;
private $userId;
/**
* @param string $appName
* @param IRequest $request
* @param LabelService $labelService
* @param $userId
*/
public function __construct($appName, IRequest $request, LabelService $labelService, $userId) {
parent::__construct($appName, $request);
$this->labelService = $labelService;
$this->userId = $userId;
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* Get a specific label.
*/
public function get() {
$label = $this->labelService->find($this->request->getParam('labelId'));
return new DataResponse($label, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* @params $title
* @params $color
* Create a new label
*/
public function create($title, $color) {
$label = $this->labelService->create($title, $color, $this->request->getParam('boardId'));
return new DataResponse($label, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* @params $title
* @params $color
* Update a specific label
*/
public function update($title, $color) {
$label = $this->labelService->update($this->request->getParam('labelId'), $title, $color);
return new DataResponse($label, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* Delete a specific label
*/
public function delete() {
$label = $this->labelService->delete($this->request->getParam('labelId'));
return new DataResponse($label, HTTP::STATUS_OK);
}
}

View File

@@ -0,0 +1,132 @@
<?php
/**
* @copyright Copyright (c) 2017 Steven R. Baker <steven@stevenrbaker.com>
*
* @author Steven R. Baker <steven@stevenrbaker.com>
* @author Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Deck\Controller;
use OCP\AppFramework\ApiController;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\IRequest;
use OCA\Deck\Service\StackService;
use OCA\Deck\Service\BoardService;
/**
* Class StackApiController
*
* @package OCA\Deck\Controller
*/
class StackApiController extends ApiController {
private $boardService;
private $stackService;
/**
* @param string $appName
* @param IRequest $request
* @param StackService $stackService
*/
public function __construct($appName, IRequest $request, StackService $stackService, BoardService $boardService) {
parent::__construct($appName, $request);
$this->stackService = $stackService;
$this->boardService = $boardService;
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* Return all of the stacks in the specified board.
*/
public function index() {
$stacks = $this->stackService->findAll($this->request->getParam('boardId'));
return new DataResponse($stacks, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* Return all of the stacks in the specified board.
*/
public function get() {
$stack = $this->stackService->find($this->request->getParam('stackId'));
return new DataResponse($stack, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* @params $title
* @params $order
*
* Create a stack with the specified title and order.
*/
public function create($title, $order) {
$stack = $this->stackService->create($title, $this->request->getParam('boardId'), $order);
return new DataResponse($stack, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* @params $title
* @params $order
*
* Update a stack by the specified stackId and boardId with the values that were put.
*/
public function update($title, $order) {
$stack = $this->stackService->update($this->request->getParam('stackId'), $title, $this->request->getParam('boardId'), $order, 0);
return new DataResponse($stack, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* Delete the stack specified by $this->request->getParam('stackId').
*/
public function delete() {
$stack = $this->stackService->delete($this->request->getParam('stackId'));
return new DataResponse($stack, HTTP::STATUS_OK);
}
/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
*
* get the stacks that have been archived.
*/
public function getArchived() {
$stacks = $this->stackService->findAllArchived($this->request->getParam('boardId'));
return new DataResponse($stacks, HTTP::STATUS_OK);
}
}

View File

@@ -40,6 +40,12 @@ class AssignedUsersMapper extends DeckMapper implements IPermissionMapper {
$this->userManager = $userManager;
}
/**
* FIXME: rename this since it returns multiple entities otherwise the naming is confusing with Entity::find
*
* @param $cardId
* @return array|Entity
*/
public function find($cardId) {
$sql = 'SELECT * FROM `*PREFIX*deck_assigned_users` ' .
'WHERE `card_id` = ?';

View File

@@ -39,6 +39,13 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
private $userManager;
private $qb;
/**
* AttachmentMapper constructor.
*
* @param IDBConnection $db
* @param CardMapper $cardMapper
* @param IUserManager $userManager
*/
public function __construct(IDBConnection $db, CardMapper $cardMapper, IUserManager $userManager) {
parent::__construct($db, 'deck_attachment', Attachment::class);
$this->cardMapper = $cardMapper;
@@ -60,7 +67,17 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
$cursor = $qb->execute();
$row = $cursor->fetch(PDO::FETCH_ASSOC);
if($row === false) {
$cursor->closeCursor();
throw new DoesNotExistException('Did expect one result but found none when executing' . $qb);
}
$row2 = $cursor->fetch();
$cursor->closeCursor();
if($row2 !== false ) {
throw new MultipleObjectsReturnedException('Did not expect more than one result when executing' . $query);
}
return $this->mapRowToEntity($row);
}
@@ -87,6 +104,11 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
return $entities;
}
/**
* @param null $cardId
* @param bool $withOffset
* @return array
*/
public function findToDelete($cardId = null, $withOffset = true) {
// add buffer of 5 min
$timeLimit = time() - (60 * 5);

View File

@@ -24,6 +24,8 @@
namespace OCA\Deck\Middleware;
use OCA\Deck\StatusException;
use OCA\Deck\BadRequestException;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Middleware;
use OCP\AppFramework\Http\JSONResponse;
use OCP\ILogger;
@@ -68,6 +70,17 @@ class SharingMiddleware extends Middleware {
'message' => $exception->getMessage()
], $exception->getStatus());
}
// uncatched DoesNotExistExceptions will be thrown when the main entity is not found
// we return a 403 so we don't leak information over existing entries
// TODO: At some point those should properly be catched in the service classes
if ($exception instanceof DoesNotExistException) {
return new JSONResponse([
'status' => 403,
'message' => 'Permission denied'
], 403);
}
throw $exception;
}

View File

@@ -104,8 +104,14 @@ class AttachmentService {
* @param $cardId
* @return array
* @throws \OCA\Deck\NoPermissionException
* @throws BadRequestException
*/
public function findAll($cardId, $withDeleted = false) {
if (is_numeric($cardId) === false) {
throw new BadRequestException('card id must be a number');
}
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
$attachments = $this->attachmentMapper->findAll($cardId);
@@ -123,7 +129,17 @@ class AttachmentService {
return $attachments;
}
/**
* @param $cardId
* @return int|mixed
* @throws BadRequestException
*/
public function count($cardId) {
if (is_numeric($cardId) === false) {
throw new BadRequestException('card id must be a number');
}
$count = $this->cache->get('card-' . $cardId);
if (!$count) {
$count = count($this->attachmentMapper->findAll($cardId));
@@ -132,7 +148,29 @@ class AttachmentService {
return $count;
}
/**
* @param $cardId
* @param $type
* @param $data
* @return Attachment|\OCP\AppFramework\Db\Entity
* @throws NoPermissionException
* @throws StatusException
* @throws BadRequestException
*/
public function create($cardId, $type, $data) {
if (is_numeric($cardId) === false) {
throw new BadRequestException('card id must be a number');
}
if ($type === false || $type === null) {
throw new BadRequestException('type must be provided');
}
if ($data === false || $data === null) {
throw new BadRequestException('data must be provided');
}
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
$this->cache->clear('card-' . $cardId);
@@ -172,11 +210,24 @@ class AttachmentService {
* @param $cardId
* @param $attachmentId
* @return Response
* @throws \OCA\Deck\NotFoundException
* @throws NoPermissionException
* @throws NotFoundException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\
* @throws BadRequestException
*/
public function display($cardId, $attachmentId) {
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
if (is_numeric($cardId) === false) {
throw new BadRequestException('card id must be a number');
}
if (is_numeric($attachmentId) === false) {
throw new BadRequestException('attachment id must be a number');
}
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
$attachment = $this->attachmentMapper->find($attachmentId);
try {
@@ -197,10 +248,23 @@ class AttachmentService {
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function update($cardId, $attachmentId, $data) {
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
if (is_numeric($cardId) === false) {
throw new BadRequestException('card id must be a number');
}
if (is_numeric($attachmentId) === false) {
throw new BadRequestException('attachment id must be a number');
}
if ($data === false || $data === null) {
throw new BadRequestException('data must be provided');
}
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
$this->cache->clear('card-' . $cardId);
$attachment = $this->attachmentMapper->find($attachmentId);
@@ -233,10 +297,19 @@ class AttachmentService {
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function delete($cardId, $attachmentId) {
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
if (is_numeric($cardId) === false) {
throw new BadRequestException('card id must be a number');
}
if (is_numeric($attachmentId) === false) {
throw new BadRequestException('attachment id must be a number');
}
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
$this->cache->clear('card-' . $cardId);
$attachment = $this->attachmentMapper->find($attachmentId);
@@ -254,8 +327,16 @@ class AttachmentService {
}
public function restore($cardId, $attachmentId) {
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
if (is_numeric($cardId) === false) {
throw new BadRequestException('card id must be a number');
}
if (is_numeric($attachmentId) === false) {
throw new BadRequestException('attachment id must be a number');
}
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
$this->cache->clear('card-' . $cardId);
$attachment = $this->attachmentMapper->find($attachmentId);

View File

@@ -30,10 +30,13 @@ use OCA\Deck\Db\IPermissionMapper;
use OCA\Deck\Db\Label;
use OCA\Deck\Notification\NotificationHelper;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\IGroupManager;
use OCP\IL10N;
use OCA\Deck\Db\Board;
use OCA\Deck\Db\BoardMapper;
use OCA\Deck\Db\LabelMapper;
use OCP\IUserManager;
use OCA\Deck\BadRequestException;
class BoardService {
@@ -45,6 +48,9 @@ class BoardService {
private $permissionService;
private $notificationHelper;
private $assignedUsersMapper;
private $userManager;
private $groupManager;
private $userId;
public function __construct(
BoardMapper $boardMapper,
@@ -53,7 +59,10 @@ class BoardService {
AclMapper $aclMapper,
PermissionService $permissionService,
NotificationHelper $notificationHelper,
AssignedUsersMapper $assignedUsersMapper
AssignedUsersMapper $assignedUsersMapper,
IUserManager $userManager,
IGroupManager $groupManager,
$userId
) {
$this->boardMapper = $boardMapper;
$this->labelMapper = $labelMapper;
@@ -62,9 +71,16 @@ class BoardService {
$this->permissionService = $permissionService;
$this->notificationHelper = $notificationHelper;
$this->assignedUsersMapper = $assignedUsersMapper;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
$this->userId = $userId;
}
public function findAll($userInfo) {
/**
* @return array
*/
public function findAll() {
$userInfo = $this->getBoardPrerequisites();
$userBoards = $this->boardMapper->findAllByUser($userInfo['user']);
$groupBoards = $this->boardMapper->findAllByGroups($userInfo['user'], $userInfo['groups']);
$complete = array_merge($userBoards, $groupBoards);
@@ -90,7 +106,20 @@ class BoardService {
return array_values($result);
}
/**
* @param $boardId
* @return Board
* @throws DoesNotExistException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function find($boardId) {
if ( is_numeric($boardId) === false ) {
throw new BadRequestException('board id must be a number');
}
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
/** @var Board $board */
$board = $this->boardMapper->find($boardId, true, true);
@@ -112,7 +141,34 @@ class BoardService {
return $board;
}
/**
* @return array
*/
private function getBoardPrerequisites() {
$groups = $this->groupManager->getUserGroupIds(
$this->userManager->get($this->userId)
);
return [
'user' => $this->userId,
'groups' => $groups
];
}
/**
* @param $mapper
* @param $id
* @return bool
* @throws DoesNotExistException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function isArchived($mapper, $id) {
if (is_numeric($id) === false) {
throw new BadRequestException('id must be a number');
}
try {
$boardId = $id;
if ($mapper instanceof IPermissionMapper) {
@@ -128,7 +184,25 @@ class BoardService {
return $board->getArchived();
}
/**
* @param $mapper
* @param $id
* @return bool
* @throws DoesNotExistException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function isDeleted($mapper, $id) {
if ($mapper === false || $mapper === null) {
throw new BadRequestException('mapper must be provided');
}
if (is_numeric($id) === false) {
throw new BadRequestException('id must be a number');
}
try {
$boardId = $id;
if ($mapper instanceof IPermissionMapper) {
@@ -145,13 +219,32 @@ class BoardService {
}
/**
* @param $title
* @param $userId
* @param $color
* @return \OCP\AppFramework\Db\Entity
* @throws BadRequestException
*/
public function create($title, $userId, $color) {
if ($title === false || $title === null) {
throw new BadRequestException('title must be provided');
}
if ($userId === false || $userId === null) {
throw new BadRequestException('userId must be provided');
}
if ($color === false || $color === null) {
throw new BadRequestException('color must be provided');
}
$board = new Board();
$board->setTitle($title);
$board->setOwner($userId);
$board->setColor($color);
$new_board = $this->boardMapper->insert($board);
$new_board = $this->boardMapper->insert($board);
// create new labels
$default_labels = [
@@ -181,7 +274,20 @@ class BoardService {
}
/**
* @param $id
* @return Board
* @throws DoesNotExistException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function delete($id) {
if (is_numeric($id) === false) {
throw new BadRequestException('board id must be a number');
}
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_READ);
$board = $this->find($id);
$board->setDeletedAt(time());
@@ -189,20 +295,72 @@ class BoardService {
return $board;
}
/**
* @param $id
* @return \OCP\AppFramework\Db\Entity
* @throws DoesNotExistException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
*/
public function deleteUndo($id) {
if (is_numeric($id) === false) {
throw new BadRequestException('board id must be a number');
}
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_READ);
$board = $this->find($id);
$board->setDeletedAt(0);
return $this->boardMapper->update($board);
}
public function deleteForce($id) {
/**
* @param $id
* @return \OCP\AppFramework\Db\Entity
* @throws DoesNotExistException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function deleteForce($id) {
if (is_numeric($id) === false) {
throw new BadRequestException('id must be a number');
}
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_READ);
$board = $this->find($id);
return $this->boardMapper->delete($board);
}
/**
* @param $id
* @param $title
* @param $color
* @param $archived
* @return \OCP\AppFramework\Db\Entity
* @throws DoesNotExistException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function update($id, $title, $color, $archived) {
if (is_numeric($id) === false) {
throw new BadRequestException('board id must be a number');
}
if ($title === false || $title === null) {
throw new BadRequestException('color must be provided');
}
if ($color === false || $color === null) {
throw new BadRequestException('color must be provided');
}
if ( is_bool($archived) === false ) {
throw new BadRequestException('archived must be a boolean');
}
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE);
$board = $this->find($id);
$board->setTitle($title);
@@ -213,7 +371,43 @@ class BoardService {
}
/**
* @param $boardId
* @param $type
* @param $participant
* @param $edit
* @param $share
* @param $manage
* @return \OCP\AppFramework\Db\Entity
* @throws \OCA\Deck\
* @throws BadRequestException
*/
public function addAcl($boardId, $type, $participant, $edit, $share, $manage) {
if (is_numeric($boardId) === false) {
throw new BadRequestException('board id must be a number');
}
if ($type === false || $type === null) {
throw new BadRequestException('type must be provided');
}
if ($participant === false || $participant === null) {
throw new BadRequestException('participant must be provided');
}
if ($edit === false || $edit === null) {
throw new BadRequestException('edit must be provided');
}
if ($share === false || $share === null) {
throw new BadRequestException('share must be provided');
}
if ($manage === false || $manage === null) {
throw new BadRequestException('manage must be provided');
}
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_SHARE);
$acl = new Acl();
$acl->setBoardId($boardId);
@@ -231,7 +425,35 @@ class BoardService {
return $newAcl;
}
/**
* @param $id
* @param $edit
* @param $share
* @param $manage
* @return \OCP\AppFramework\Db\Entity
* @throws DoesNotExistException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function updateAcl($id, $edit, $share, $manage) {
if (is_numeric($id) === false) {
throw new BadRequestException('id must be a number');
}
if ($edit === null) {
throw new BadRequestException('edit must be provided');
}
if ($share === null) {
throw new BadRequestException('share must be provided');
}
if ($manage === null) {
throw new BadRequestException('manage must be provided');
}
$this->permissionService->checkPermission($this->aclMapper, $id, Acl::PERMISSION_SHARE);
/** @var Acl $acl */
$acl = $this->aclMapper->find($id);
@@ -242,7 +464,20 @@ class BoardService {
return $this->aclMapper->update($acl);
}
/**
* @param $id
* @return \OCP\AppFramework\Db\Entity
* @throws DoesNotExistException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function deleteAcl($id) {
if (is_numeric($id) === false) {
throw new BadRequestException('id must be a number');
}
$this->permissionService->checkPermission($this->aclMapper, $id, Acl::PERMISSION_SHARE);
/** @var Acl $acl */
$acl = $this->aclMapper->find($id);

View File

@@ -34,7 +34,7 @@ use OCA\Deck\Db\BoardMapper;
use OCA\Deck\Db\LabelMapper;
use OCA\Deck\NotFoundException;
use OCA\Deck\StatusException;
use OCA\Deck\BadRequestException;
class CardService {
@@ -89,7 +89,20 @@ class CardService {
return $cards;
}
/**
* @param $cardId
* @return \OCA\Deck\Db\RelationalEntity
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function find($cardId) {
if (is_numeric($cardId) === false) {
throw new BadRequestException('card id must be a number');
}
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
$card = $this->cardMapper->find($cardId);
$assignedUsers = $this->assignedUsersMapper->find($card->getId());
@@ -100,9 +113,40 @@ class CardService {
}
/**
* @param $title
* @param $stackId
* @param $type
* @param integer $order
* @param $owner
* @return \OCP\AppFramework\Db\Entity
* @throws StatusException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadrequestException
*/
public function create($title, $stackId, $type, $order, $owner) {
if ($title === 'false' || $title === null) {
throw new BadRequestException('title must be provided');
}
if (is_numeric($stackId) === false) {
throw new BadRequestException('stack id must be a number');
}
if ($type === 'false' || $type === null) {
throw new BadRequestException('type must be provided');
}
if (is_numeric($order) === false) {
throw new BadRequestException('order must be a number');
}
if ($owner === false || $owner === null) {
throw new BadRequestException('owner must be provided');
}
$this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->stackMapper, $stackId)) {
throw new StatusException('Operation not allowed. This board is archived.');
@@ -114,10 +158,23 @@ class CardService {
$card->setOrder($order);
$card->setOwner($owner);
return $this->cardMapper->insert($card);
}
/**
* @param $id
* @return \OCP\AppFramework\Db\Entity
* @throws StatusException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function delete($id) {
if (is_numeric($id) === false) {
throw new BadRequestException('card id must be a number');
}
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $id)) {
throw new StatusException('Operation not allowed. This board is archived.');
@@ -128,7 +185,44 @@ class CardService {
return $card;
}
public function update($id, $title, $stackId, $type, $order, $description, $owner, $duedate, $deletedAt) {
/**
* @param $id
* @param $title
* @param $stackId
* @param $type
* @param $order
* @param $description
* @param $owner
* @param $duedate
* @return \OCP\AppFramework\Db\Entity
* @throws StatusException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function update($id, $title, $stackId, $type, $order = 0, $description = '', $owner, $duedate = null, $deletedAt) {
if (is_numeric($id) === false) {
throw new BadRequestException('card id must be a number');
}
if ($title === false || $title === null) {
throw new BadRequestException('title must be provided');
}
if (is_numeric($stackId) === false) {
throw new BadRequestException('stack id must be a number $$$');
}
if ($type === false || $type === null) {
throw new BadRequestException('type must be provided');
}
if ($owner === false || $owner === null) {
throw new BadRequestException('owner must be provided');
}
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $id)) {
throw new StatusException('Operation not allowed. This board is archived.');
@@ -148,7 +242,26 @@ class CardService {
return $this->cardMapper->update($card);
}
/**
* @param $id
* @param $title
* @return \OCP\AppFramework\Db\Entity
* @throws StatusException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function rename($id, $title) {
if (is_numeric($id) === false) {
throw new BadRequestException('id must be a number');
}
if ($title === false || $title === null) {
throw new BadRequestException('title must be provided');
}
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $id)) {
throw new StatusException('Operation not allowed. This board is archived.');
@@ -161,7 +274,31 @@ class CardService {
return $this->cardMapper->update($card);
}
/**
* @param $id
* @param $stackId
* @param $order
* @return array
* @throws StatusException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function reorder($id, $stackId, $order) {
if (is_numeric($id) === false) {
throw new BadRequestException('card id must be a number');
}
if (is_numeric($stackId) === false) {
throw new BadRequestException('stack id must be a number');
}
if (is_numeric($order) === false) {
throw new BadRequestException('order must be a number');
}
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $id)) {
throw new StatusException('Operation not allowed. This board is archived.');
@@ -192,7 +329,21 @@ class CardService {
return $result;
}
/**
* @param $id
* @return \OCP\AppFramework\Db\Entity
* @throws StatusException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\
* @throws BadRequestException
*/
public function archive($id) {
if (is_numeric($id) === false) {
throw new BadRequestException('id must be a number');
}
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $id)) {
throw new StatusException('Operation not allowed. This board is archived.');
@@ -202,7 +353,21 @@ class CardService {
return $this->cardMapper->update($card);
}
/**
* @param $id
* @return \OCP\AppFramework\Db\Entity
* @throws StatusException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function unarchive($id) {
if (is_numeric($id) === false) {
throw new BadRequestException('id must be a number');
}
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $id)) {
throw new StatusException('Operation not allowed. This board is archived.');
@@ -212,7 +377,25 @@ class CardService {
return $this->cardMapper->update($card);
}
/**
* @param $cardId
* @param $labelId
* @throws StatusException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function assignLabel($cardId, $labelId) {
if (is_numeric($cardId) === false) {
throw new BadRequestException('card id must be a number');
}
if (is_numeric($labelId) === false) {
throw new BadRequestException('label id must be a number');
}
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $cardId)) {
throw new StatusException('Operation not allowed. This board is archived.');
@@ -224,7 +407,25 @@ class CardService {
$this->cardMapper->assignLabel($cardId, $labelId);
}
/**
* @param $cardId
* @param $labelId
* @throws StatusException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function removeLabel($cardId, $labelId) {
if (is_numeric($cardId) === false) {
throw new BadRequestException('card id must be a number');
}
if (is_numeric($labelId) === false) {
throw new BadRequestException('label id must be a number');
}
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $cardId)) {
throw new StatusException('Operation not allowed. This board is archived.');
@@ -236,7 +437,24 @@ class CardService {
$this->cardMapper->removeLabel($cardId, $labelId);
}
/**
* @param $cardId
* @param $userId
* @return bool|null|\OCP\AppFramework\Db\Entity
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function assignUser($cardId, $userId) {
if (is_numeric($cardId) === false) {
throw new BadRequestException('card id must be a number');
}
if ($userId === false || $userId === null) {
throw new BadRequestException('user id must be provided');
}
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
$assignments = $this->assignedUsersMapper->find($cardId);
foreach ($assignments as $assignment) {
@@ -257,8 +475,26 @@ class CardService {
return $this->assignedUsersMapper->insert($assignment);
}
/**
* @param $cardId
* @param $userId
* @return \OCP\AppFramework\Db\Entity
* @throws NotFoundException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function unassignUser($cardId, $userId) {
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
if (is_numeric($cardId) === false) {
throw new BadRequestException('card id must be a number');
}
if ($userId === false || $userId === null) {
throw new BadRequestException('user must be provided');
}
$assignments = $this->assignedUsersMapper->find($cardId);
foreach ($assignments as $assignment) {
if ($assignment->getParticipant() === $userId) {

View File

@@ -29,6 +29,7 @@ use OCA\Deck\Service\StackService;
use OCA\Deck\Service\CardService;
use OCP\IConfig;
use OCP\IL10N;
use OCA\Deck\BadRequestException;
class DefaultBoardService {
@@ -55,8 +56,14 @@ class DefaultBoardService {
$this->boardMapper = $boardMapper;
$this->l10n = $l10n;
}
public function checkFirstRun($userId, $appName) {
/**
* @param $userId
* @param $appName
* @return bool
* @throws \OCP\PreConditionNotMetException
*/
public function checkFirstRun($userId, $appName) {
$firstRun = $this->config->getUserValue($userId, $appName, 'firstRun', 'yes');
$userBoards = $this->boardMapper->findAllByUser($userId);
@@ -68,7 +75,31 @@ class DefaultBoardService {
return false;
}
public function createDefaultBoard($title, $userId, $color) {
/**
* @param $title
* @param $userId
* @param $color
* @return \OCP\AppFramework\Db\Entity
* @throws \OCA\Deck\NoPermissionException
* @throws \OCA\Deck\StatusException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function createDefaultBoard($title, $userId, $color) {
if ($title === false || $title === null) {
throw new BadRequestException('title must be provided');
}
if ($userId === false || $userId === null) {
throw new BadRequestException('userId must be provided');
}
if ($color === false || $color === null) {
throw new BadRequestException('color must be provided');
}
$defaultBoard = $this->boardService->create($title, $userId, $color);
$defaultStacks = [];
$defaultCards = [];

View File

@@ -142,6 +142,11 @@ class FileService implements IAttachmentService {
return $file;
}
/**
* @param Attachment $attachment
* @throws NotPermittedException
* @throws StatusException
*/
public function create(Attachment $attachment) {
$file = $this->getUploadedFile();
$folder = $this->getFolder($attachment);
@@ -176,6 +181,10 @@ class FileService implements IAttachmentService {
$attachment->setLastModified(time());
}
/**
* @param Attachment $attachment
* @throws NotPermittedException
*/
public function delete(Attachment $attachment) {
try {
$file = $this->getFileForAttachment($attachment);
@@ -202,6 +211,11 @@ class FileService implements IAttachmentService {
return $cardFolder->get($attachment->getData());
}
/**
* @param Attachment $attachment
* @return FileDisplayResponse|\OCP\AppFramework\Http\Response|StreamResponse
* @throws \Exception
*/
public function display(Attachment $attachment) {
$file = $this->getFileFromRootFolder($attachment);
if (method_exists($file, 'fopen')) {

View File

@@ -27,6 +27,7 @@ use OCA\Deck\Db\Label;
use OCA\Deck\Db\Acl;
use OCA\Deck\Db\LabelMapper;
use OCA\Deck\StatusException;
use OCA\Deck\BadRequestException;
class LabelService {
@@ -44,12 +45,47 @@ class LabelService {
$this->boardService = $boardService;
}
/**
* @param $labelId
* @return \OCP\AppFramework\Db\Entity
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function find($labelId) {
if (is_numeric($labelId) === false) {
throw new BadRequestException('label id must be a number');
}
$this->permissionService->checkPermission($this->labelMapper, $labelId, Acl::PERMISSION_READ);
return $this->labelMapper->find($labelId);
}
/**
* @param $title
* @param $color
* @param $boardId
* @return \OCP\AppFramework\Db\Entity
* @throws StatusException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function create($title, $color, $boardId) {
if ($title === false || $title === null) {
throw new BadRequestException('title must be provided');
}
if ($color === false || $color === null) {
throw new BadRequestException('color must be provided');
}
if (is_numeric($boardId) === false) {
throw new BadRequestException('board id must be a number');
}
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_MANAGE);
if ($this->boardService->isArchived(null, $boardId)) {
throw new StatusException('Operation not allowed. This board is archived.');
@@ -61,7 +97,21 @@ class LabelService {
return $this->labelMapper->insert($label);
}
/**
* @param $id
* @return \OCP\AppFramework\Db\Entity
* @throws StatusException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function delete($id) {
if (is_numeric($id) === false) {
throw new BadRequestException('label id must be a number');
}
$this->permissionService->checkPermission($this->labelMapper, $id, Acl::PERMISSION_MANAGE);
if ($this->boardService->isArchived($this->labelMapper, $id)) {
throw new StatusException('Operation not allowed. This board is archived.');
@@ -69,7 +119,31 @@ class LabelService {
return $this->labelMapper->delete($this->find($id));
}
/**
* @param $id
* @param $title
* @param $color
* @return \OCP\AppFramework\Db\Entity
* @throws StatusException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function update($id, $title, $color) {
if (is_numeric($id) === false) {
throw new BadRequestException('label id must be a number');
}
if ($title === false || $title === null) {
throw new BadRequestException('title must be provided');
}
if ($color === false || $color === null) {
throw new BadRequestException('color must be provided');
}
$this->permissionService->checkPermission($this->labelMapper, $id, Acl::PERMISSION_MANAGE);
if ($this->boardService->isArchived($this->labelMapper, $id)) {
throw new StatusException('Operation not allowed. This board is archived.');

View File

@@ -31,6 +31,8 @@ use OCA\Deck\Db\IPermissionMapper;
use OCA\Deck\Db\User;
use OCA\Deck\NoPermissionException;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\Entity;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\IGroupManager;
use OCP\ILogger;
use OCP\IUserManager;
@@ -114,42 +116,41 @@ class PermissionService {
* @throws NoPermissionException
*/
public function checkPermission($mapper, $id, $permission) {
try {
$boardId = $id;
if ($mapper instanceof IPermissionMapper) {
$boardId = $mapper->findBoardId($id);
}
if ($boardId === null) {
// Throw NoPermission to not leak information about existing entries
throw new NoPermissionException('Permission denied');
}
if ($this->userIsBoardOwner($boardId)) {
return true;
}
$acls = $this->aclMapper->findAll($boardId);
$result = $this->userCan($acls, $permission);
if ($result) {
return true;
}
} catch (DoesNotExistException $exception) {
$boardId = $id;
if ($mapper instanceof IPermissionMapper) {
$boardId = $mapper->findBoardId($id);
}
if ($boardId === null) {
// Throw NoPermission to not leak information about existing entries
throw new NoPermissionException('Permission denied');
}
throw new NoPermissionException('Permission denied.');
if ($this->userIsBoardOwner($boardId)) {
return true;
}
$acls = $this->aclMapper->findAll($boardId);
$result = $this->userCan($acls, $permission);
if ($result) {
return true;
}
// Throw NoPermission to not leak information about existing entries
throw new NoPermissionException('Permission denied');
}
/**
* @param $boardId
* @return bool
* @throws \OCP\AppFramework\Db\DoesNotExistException
*/
public function userIsBoardOwner($boardId) {
$board = $this->boardMapper->find($boardId);
return $board && $this->userId === $board->getOwner();
try {
$board = $this->boardMapper->find($boardId);
return $board && $this->userId === $board->getOwner();
} catch (DoesNotExistException $e) {
} catch (MultipleObjectsReturnedException $e) {
return false;
}
}
/**
@@ -192,19 +193,34 @@ class PermissionService {
$board = $this->boardMapper->find($boardId);
} catch (DoesNotExistException $e) {
return [];
} catch (MultipleObjectsReturnedException $e) {
return [];
}
$owner = $this->userManager->get($board->getOwner());
$users = [];
$users[$owner->getUID()] = new User($owner);
if ($owner === null) {
$this->logger->info('No owner found for board ' . $board->getId());
} else {
$users = [];
$users[$owner->getUID()] = new User($owner);
}
$acls = $this->aclMapper->findAll($boardId);
/** @var Acl $acl */
foreach ($acls as $acl) {
if ($acl->getType() === Acl::PERMISSION_TYPE_USER) {
$user = $this->userManager->get($acl->getParticipant());
if ($user === null) {
$this->logger->info('No user found for acl rule ' . $acl->getId());
continue;
}
$users[$user->getUID()] = new User($user);
}
if ($acl->getType() === Acl::PERMISSION_TYPE_GROUP) {
$group = $this->groupManager->get($acl->getParticipant());
if ($group === null) {
$this->logger->info('No group found for acl rule ' . $acl->getId());
continue;
}
foreach ($group->getUsers() as $user) {
$users[$user->getUID()] = new User($user);
}

View File

@@ -31,8 +31,7 @@ use OCA\Deck\Db\AssignedUsersMapper;
use OCA\Deck\Db\Stack;
use OCA\Deck\Db\StackMapper;
use OCA\Deck\StatusException;
use OCP\ICache;
use OCP\ICacheFactory;
use OCA\Deck\BadRequestException;
class StackService {
@@ -89,7 +88,40 @@ class StackService {
}
}
/**
* @param $stackId
* @return \OCP\AppFramework\Db\Entity
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function find($stackId) {
if (is_numeric($stackId) === false) {
throw new BadRequestException('stack id must be a number');
}
$stack = $this->stackMapper->find($stackId);
$cards = $this->cardMapper->findAll($stackId);
foreach ($cards as $cardIndex => $card) {
$assignedUsers = $this->assignedUsersMapper->find($card->getId());
$card->setAssignedUsers($assignedUsers);
$card->setAttachmentCount($this->attachmentService->count($card->getId()));
}
$stack->setCards($cards);
return $stack;
}
/**
* @param $boardId
* @return array
* @throws \OCA\Deck\NoPermissionException
* @throws BadRequestException
*/
public function findAll($boardId) {
if (is_numeric($boardId) === false) {
throw new BadRequestException('boardId must be a number');
}
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_READ);
$stacks = $this->stackMapper->findAll($boardId);
$this->enrichStacksWithCards($stacks);
@@ -103,7 +135,18 @@ class StackService {
return $stacks;
}
/**
* @param $boardId
* @return array
* @throws \OCA\Deck\NoPermissionException
* @throws BadRequestException
*/
public function findAllArchived($boardId) {
if (is_numeric($boardId) === false) {
throw new BadRequestException('board id must be a number');
}
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_READ);
$stacks = $this->stackMapper->findAll($boardId);
$labels = $this->labelMapper->getAssignedLabelsForBoard($boardId);
@@ -120,9 +163,30 @@ class StackService {
}
/**
* @param $title
* @param $boardId
* @param integer $order
* @return \OCP\AppFramework\Db\Entity
* @throws StatusException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function create($title, $boardId, $order) {
if ($title === false || $title === null) {
throw new BadRequestException('title must be provided');
}
if (is_numeric($order) === false) {
throw new BadRequestException('order must be a number');
}
if (is_numeric($boardId) === false) {
throw new BadRequestException('board id must be a number');
}
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_MANAGE);
if ($this->boardService->isArchived(null, $boardId)) {
throw new StatusException('Operation not allowed. This board is archived.');
@@ -135,7 +199,20 @@ class StackService {
}
/**
* @param $id
* @return \OCP\AppFramework\Db\Entity
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function delete($id) {
if ( is_numeric($id) === false ) {
throw new BadRequestException('stack id must be a number');
}
$this->permissionService->checkPermission($this->stackMapper, $id, Acl::PERMISSION_MANAGE);
$stack = $this->stackMapper->find($id);
@@ -147,8 +224,37 @@ class StackService {
return $stack;
}
/**
* @param $id
* @param $title
* @param $boardId
* @param $order
* @param $deletedAt
* @return \OCP\AppFramework\Db\Entity
* @throws StatusException
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function update($id, $title, $boardId, $order, $deletedAt) {
if (is_numeric($id) === false) {
throw new BadRequestException('stack id must be a number');
}
if ($title === false || $title === null) {
throw new BadRequestException('title must be provided');
}
if (is_numeric($boardId) === false) {
throw new BadRequestException('board id must be a number');
}
if (is_numeric($order) === false) {
throw new BadRequestException('order must be a number');
}
$this->permissionService->checkPermission($this->stackMapper, $id, Acl::PERMISSION_MANAGE);
if ($this->boardService->isArchived($this->stackMapper, $id)) {
throw new StatusException('Operation not allowed. This board is archived.');
@@ -161,7 +267,25 @@ class StackService {
return $this->stackMapper->update($stack);
}
/**
* @param $id
* @param $order
* @return array
* @throws \OCA\Deck\NoPermissionException
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws BadRequestException
*/
public function reorder($id, $order) {
if (is_numeric($id) === false) {
throw new BadRquestException('id must be a number');
}
if ($order === false || $order === null) {
throw new BadRequestException('order must be provided');
}
$this->permissionService->checkPermission($this->stackMapper, $id, Acl::PERMISSION_EDIT);
$stackToSort = $this->stackMapper->find($id);
$stacks = $this->stackMapper->findAll($stackToSort->getBoardId());

View File

@@ -33,6 +33,8 @@ use OCA\Deck\Db\BoardMapper;
use OCA\Deck\Db\LabelMapper;
use OCA\Deck\Notification\NotificationHelper;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IGroupManager;
use \Test\TestCase;
class BoardServiceTest extends TestCase {
@@ -53,8 +55,12 @@ class BoardServiceTest extends TestCase {
private $notificationHelper;
/** @var AssignedUsersMapper */
private $assignedUsersMapper;
/** @var IUserManager */
private $userManager;
/** @var IUserManager */
private $groupManager;
private $userId = 'admin';
private $userId = 'admin';
public function setUp() {
parent::setUp();
@@ -65,6 +71,8 @@ class BoardServiceTest extends TestCase {
$this->permissionService = $this->createMock(PermissionService::class);
$this->notificationHelper = $this->createMock(NotificationHelper::class);
$this->assignedUsersMapper = $this->createMock(AssignedUsersMapper::class);
$this->userManager = $this->createMock(IUserManager::class);
$this->groupManager = $this->createMock(IGroupManager::class);
$this->service = new BoardService(
$this->boardMapper,
@@ -73,11 +81,14 @@ class BoardServiceTest extends TestCase {
$this->aclMapper,
$this->permissionService,
$this->notificationHelper,
$this->assignedUsersMapper
$this->assignedUsersMapper,
$this->userManager,
$this->groupManager,
$this->userId
);
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('admin');
$user->method('getUID')->willReturn('admin');
}
public function testFindAll() {
@@ -95,11 +106,14 @@ class BoardServiceTest extends TestCase {
->method('findAllByGroups')
->with('admin', ['a', 'b', 'c'])
->willReturn([$b2, $b3]);
$userinfo = [
'user' => 'admin',
'groups' => ['a', 'b', 'c']
];
$result = $this->service->findAll($userinfo);
$user = $this->createMock(IUser::class);
$this->groupManager->method('getUserGroupIds')
->willReturn(['a', 'b', 'c']);
$this->userManager->method('get')
->with($this->userId)
->willReturn($user);
$result = $this->service->findAll();
sort($result);
$this->assertEquals([$b1, $b2, $b3], $result);
}

View File

@@ -151,7 +151,7 @@ class CardServiceTest extends TestCase {
$card->setArchived(true);
$this->cardMapper->expects($this->once())->method('find')->willReturn($card);
$this->cardMapper->expects($this->never())->method('update');
$this->setExpectedException(StatusException::class);
$this->expectException(StatusException::class);
$this->cardService->update(123, 'newtitle', 234, 'text', 999, 'foo', 'admin', '2017-01-01 00:00:00', null);
}
@@ -171,7 +171,7 @@ class CardServiceTest extends TestCase {
$card->setArchived(true);
$this->cardMapper->expects($this->once())->method('find')->willReturn($card);
$this->cardMapper->expects($this->never())->method('update');
$this->setExpectedException(StatusException::class);
$this->expectException(StatusException::class);
$this->cardService->rename(123, 'newtitle');
}
@@ -211,7 +211,7 @@ class CardServiceTest extends TestCase {
$card->setArchived(true);
$this->cardMapper->expects($this->once())->method('findAll')->willReturn([$card]);
$this->cardMapper->expects($this->never())->method('update')->willReturnCallback(function($c) { return $c; });
$this->setExpectedException(StatusException::class);
$this->expectException(StatusException::class);
$actual = $this->cardService->reorder(123, 234, 1);
}
public function testArchive() {
@@ -247,7 +247,7 @@ class CardServiceTest extends TestCase {
$card->setArchived(true);
$this->cardMapper->expects($this->once())->method('find')->willReturn($card);
$this->cardMapper->expects($this->never())->method('assignLabel');
$this->setExpectedException(StatusException::class);
$this->expectException(StatusException::class);
$this->cardService->assignLabel(123, 999);
}
@@ -263,8 +263,8 @@ class CardServiceTest extends TestCase {
$card = new Card();
$card->setArchived(true);
$this->cardMapper->expects($this->once())->method('find')->willReturn($card);
$this->cardMapper->expects($this->never())->method('removeLabel');
$this->setExpectedException(StatusException::class);
$this->cardMapper->expects($this->never())->method('removeLabel');
$this->expectException(StatusException::class);
$this->cardService->removeLabel(123, 999);
}
@@ -320,7 +320,10 @@ class CardServiceTest extends TestCase {
}
/**
* @expectedException \OCA\Deck\NotFoundException
* @expectException \OCA\Deck\NotFoundException
*
*
*
*/
public function testUnassignUserNotExisting() {
$assignment = new AssignedUsers();
@@ -333,8 +336,8 @@ class CardServiceTest extends TestCase {
->method('find')
->with(123)
->willReturn($assignments);
$actual = $this->cardService->unassignUser(123, 'user');
$this->assertEquals($assignment, $actual);
$this->expectException(NotFoundException::class);
$actual = $this->cardService->unassignUser(123, 'user');
}

View File

@@ -66,7 +66,8 @@ class DefaultBoardServiceTest extends TestCase {
$this->stackService = $this->createMock(StackService::class);
$this->cardService = $this->createMock(CardService::class);
$this->config = $this->createMock(IConfig::class);
$this->l10n = $this->createMock(IL10N::class);
$this->l10n = $this->createMock(IL10N::class);
$this->userId = 'admin';
$this->service = new DefaultBoardService(
$this->l10n,

View File

@@ -231,7 +231,7 @@ class PermissionServiceTest extends \Test\TestCase {
$actual = $this->service->checkPermission($mapper, 1234, $permission);
$this->assertTrue($actual);
} else {
$this->setExpectedException(NoPermissionException::class);
$this->expectException(NoPermissionException::class);
$this->service->checkPermission($mapper, 1234, $permission);
}
@@ -255,7 +255,7 @@ class PermissionServiceTest extends \Test\TestCase {
$actual = $this->service->checkPermission($mapper, 1234, $permission);
$this->assertTrue($actual);
} else {
$this->setExpectedException(NoPermissionException::class);
$this->expectException(NoPermissionException::class);
$this->service->checkPermission($mapper, 1234, $permission);
}
@@ -263,8 +263,8 @@ class PermissionServiceTest extends \Test\TestCase {
public function testCheckPermissionNotFound() {
$mapper = $this->getMockBuilder(IPermissionMapper::class)->getMock();
$mapper->expects($this->once())->method('findBoardId')->willThrowException(new NoPermissionException(null));
$this->setExpectedException(NoPermissionException::class);
$mapper->expects($this->once())->method('findBoardId')->willThrowException(new NoPermissionException(null));
$this->expectException(NoPermissionException::class);
$this->service->checkPermission($mapper, 1234, Acl::PERMISSION_READ);
}

View File

@@ -0,0 +1,172 @@
<?php
/**
* @copyright Copyright (c) 2018 Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @author Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Deck\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\IRequest;
use OCA\Deck\Service\AttachmentService;
use OCA\Deck\Db\Attachment;
class AttachmentApiControllerTest extends \Test\TestCase {
private $appName = 'deck';
private $controller;
private $request;
private $attachmentExample;
private $cardId;
private $attachmentService;
public function setUp() {
parent::setUp();
$this->attachmentExample = new Attachment();
$this->attachmentExample->setId(1);
$this->cardId = 1;
$this->request = $this->createMock(IRequest::class);
$this->attachmentService = $this->createMock(AttachmentService::class);
$this->controller = new AttachmentApiController(
$this->appName,
$this->request,
$this->attachmentService
);
}
public function testGetAll() {
$allAttachments = [$this->attachmentExample];
$this->attachmentService->expects($this->once())
->method('findAll')
->willReturn($allAttachments);
$this->request->expects($this->once())
->method('getParam')
->with('cardId')
->willReturn($allAttachments);
$expected = new DataResponse($allAttachments, HTTP::STATUS_OK);
$actual = $this->controller->getAll();
$this->assertEquals($expected, $actual);
}
public function testDisplay() {
$this->attachmentService->expects($this->once())
->method('display')
->willReturn($this->attachmentExample);
$this->request->expects($this->exactly(2))
->method('getParam')
->withConsecutive(
['cardId'],
['attachmentId']
)->willReturnonConsecutiveCalls(
$this->cardId,
$this->attachmentExample->getId());
$expected = new DataResponse($this->attachmentExample, HTTP::STATUS_OK);
$actual = $this->controller->display();
$this->assertEquals($expected, $actual);
}
public function testCreate() {
$type = 'not null';
$data = ['not null'];
$this->attachmentService->expects($this->once())
->method('create')
->willReturn($this->attachmentExample);
$this->request->expects($this->once())
->method('getParam')
->with('cardId')
->willReturn($this->cardId);
$expected = new DataResponse($this->attachmentExample, HTTP::STATUS_OK);
$actual = $this->controller->create($type, $data);
$this->assertEquals($expected, $actual);
}
public function testUpdate() {
// FIXME: what is data supposed to be in this context?
$data = ['not empty data'];
$this->attachmentService->expects($this->once())
->method('update')
->willReturn($this->attachmentExample);
$this->request->expects($this->exactly(2))
->method('getParam')
->withConsecutive(
['cardId'],
['attachmentId']
)->willReturnonConsecutiveCalls(
$this->cardId,
$this->attachmentExample->getId());
$expected = new DataResponse($this->attachmentExample, HTTP::STATUS_OK);
$actual = $this->controller->update($data);
$this->assertEquals($expected, $actual);
}
public function testDelete() {
$this->attachmentService->expects($this->once())
->method('delete')
->willReturn($this->attachmentExample);
$this->request->expects($this->exactly(2))
->method('getParam')
->withConsecutive(
['cardId'],
['attachmentId']
)->willReturnonConsecutiveCalls(
$this->cardId,
$this->attachmentExample->getId());
$expected = new DataResponse($this->attachmentExample, HTTP::STATUS_OK);
$actual = $this->controller->delete();
$this->assertEquals($expected, $actual);
}
public function testRestore() {
$this->attachmentService->expects($this->once())
->method('restore')
->willReturn($this->attachmentExample);
$this->request->expects($this->exactly(2))
->method('getParam')
->withConsecutive(
['cardId'],
['attachmentId']
)->willReturnonConsecutiveCalls(
$this->cardId,
$this->attachmentExample->getId());
$expected = new DataResponse($this->attachmentExample, HTTP::STATUS_OK);
$actual = $this->controller->restore();
$this->assertEquals($expected, $actual);
}
}

View File

@@ -0,0 +1,169 @@
<?php
/**
* @copyright Copyright (c) 2018 Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @author Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Deck\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\IRequest;
use OCA\Deck\Service\BoardService;
use OCA\Deck\Db\Board;
class BoardApiControllerTest extends \Test\TestCase {
private $appName = 'deck';
private $userId = 'admin';
private $controller;
private $boardService;
private $exampleBoard;
private $deniedBoard;
public function setUp() {
parent::setUp();
$this->request = $this->createMock(IRequest::class);
$this->boardService = $this->createMock(BoardService::class);
$this->controller = new BoardApiController(
$this->appName,
$this->request,
$this->boardService,
$this->userId
);
$this->exampleBoard['id'] = 1;
$this->exampleBoard['title'] = 'titled';
$this->exampleBoard['color'] = '000000';
$this->deniedBoard['id'] = 2;
$this->deniedBoard['owner'] = 'someone else';
$this->deniedBoard['title'] = 'titled';
$this->deniedBoard['color'] = '000000';
}
public function testIndex() {
$board = new Board();
$board->setId('1');
$board->setTitle('test');
$board->setOwner($this->userId);
$board->setColor('000000');
$boards = [$board];
$this->boardService->expects($this->once())
->method('findAll')
->willReturn($boards);
$expected = new DataResponse($boards, HTTP::STATUS_OK);
$actual = $this->controller->index();
$this->assertEquals($expected, $actual);
}
public function testGet() {
$boardId = 25;
$board = new Board();
$board->setId($boardId);
$this->boardService->expects($this->once())
->method('find')
->willReturn($board);
$this->request->expects($this->any())
->method('getParam')
->with('boardId')
->will($this->returnValue($boardId));
$expected = new DataResponse($board, HTTP::STATUS_OK);
$actual = $this->controller->get();
$this->assertEquals($expected, $actual);
}
public function testCreate() {
$board = new Board();
$board->setId($this->exampleBoard['id']);
$board->setTitle($this->exampleBoard['title']);
$board->setColor($this->exampleBoard['color']);
$this->boardService->expects($this->once())
->method('create')
->willReturn($board);
$expected = new DataResponse($board, HTTP::STATUS_OK);
$actual = $this->controller->create($this->exampleBoard['title'], $this->exampleBoard['color']);
$this->assertEquals($expected, $actual);
}
public function testUpdate() {
$board = new Board();
$board->setId($this->exampleBoard['id']);
$board->setTitle($this->exampleBoard['title']);
$board->setColor($this->exampleBoard['color']);
$this->boardService->expects($this->once())
->method('update')
->willReturn($board);
$this->request->expects($this->any())
->method('getParam')
->with('boardId')
->will($this->returnValue($this->exampleBoard['id']));
$expected = new DataResponse($board, HTTP::STATUS_OK);
$actual = $this->controller->update($this->exampleBoard['title'], $this->exampleBoard['color']);
$this->assertEquals($expected, $actual);
}
public function testDelete() {
$board = new Board();
$board->setId($this->exampleBoard['id']);
$board->setTitle($this->exampleBoard['title']);
$board->setColor($this->exampleBoard['color']);
$this->boardService->expects($this->once())
->method('delete')
->willReturn($board);
$this->request->expects($this->any())
->method('getParam')
->with('boardId')
->will($this->returnValue($this->exampleBoard['id']));
$expected = new DataResponse($board, HTTP::STATUS_OK);
$actual = $this->controller->delete();
$this->assertEquals($expected, $actual);
}
public function testUndoDelete() {
$board = new board();
$board->setId($this->exampleBoard['id']);
$board->setTitle($this->exampleBoard['title']);
$board->setColor($this->exampleBoard['color']);
$this->boardService->expects($this->once())
->method('deleteUndo')
->willReturn($board);
$this->request->expects($this->any())
->method('getParam')
->with('boardId')
->will($this->returnValue($this->exampleBoard['id']));
$expected = new DataResponse($board, HTTP::STATUS_OK);
$actual = $this->controller->undoDelete();
$this->assertEquals($expected, $actual);
}
}

View File

@@ -71,9 +71,7 @@ class BoardControllerTest extends \Test\TestCase {
$this->controller = new BoardController(
'deck',
$this->request,
$this->userManager,
$this->groupManager,
$this->request,
$this->boardService,
$this->permissionService,
$this->userId

View File

@@ -0,0 +1,138 @@
<?php
/**
* @copyright Copyright (c) 2018 Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @author Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Deck\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\IRequest;
use OCA\Deck\Db\Card;
use OCA\Deck\Service\CardService;
class CardApiControllerTest extends \Test\TestCase {
private $controller;
private $request;
private $cardService;
private $userId = 'admin';
private $cardExample;
private $stackExample;
public function setUp() {
parent::setUp();
$this->request = $this->createMock(IRequest::class);
$this->cardService = $this->createMock(CardService::class);
$this->cardExample['id'] = 1;
$this->stackExample['id'] = 1;
$this->controller = new CardApiController (
$appName = 'deck',
$this->request,
$this->cardService,
$this->userId
);
}
public function testGet() {
$card = new Card();
$card->setId($this->cardExample['id']);
$this->request->expects($this->once())
->method('getParam')
->with('cardId')
->will($this->returnValue($this->cardExample['id']));
$this->cardService->expects($this->once())
->method('find')
->willReturn($card);
$expected = new DataResponse($card, HTTP::STATUS_OK);
$actual = $this->controller->get();
$this->assertEquals($expected, $actual);
}
public function testCreate() {
$card = new Card();
$card->setId($this->cardExample['id']);
$card->setStackId($this->stackExample['id']);
$this->request->expects($this->once())
->method('getParam')
->with('stackId')
->willReturn($this->stackExample['id']);
$this->cardService->expects($this->once())
->method('create')
->willReturn($card);
$expected = new DataResponse($card, HTTP::STATUS_OK);
$actual = $this->controller->create('title');
$this->assertEquals($expected, $actual);
}
public function testUpdate() {
$card = new Card();
$card->setId($this->cardExample['id']);
$card->setStackId($this->stackExample['id']);
$this->request->expects($this->exactly(2))
->method('getParam')
->withConsecutive(
['cardId'],
['stackId']
)->willReturnonConsecutiveCalls(
$this->cardExample['id'],
$this->stackExample['id']);
$this->cardService->expects($this->once())
->method('update')
->willReturn($card);
$expected = new DataResponse($card, HTTP::STATUS_OK);
$actual = $this->controller->update('title', 'plain', 0, 'description', $this->userId, null);
$this->assertEquals($expected, $actual);
}
public function testDelete() {
$card = new Card();
$card->setId($this->cardExample['id']);
$this->request->expects($this->once())
->method('getParam')
->with('cardId')
->will($this->returnValue($this->cardExample['id']));
$this->cardService->expects($this->once())
->method('delete')
->willReturn($card);
$expected = new DataResponse($card, HTTP::STATUS_OK);
$actual = $this->controller->delete();
$this->assertEquals($expected, $actual);
}
}

View File

@@ -0,0 +1,128 @@
<?php
/**
* @copyright Copyright (c) 2018 Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @author Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Deck\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\IRequest;
use OCA\Deck\Db\Label;
use OCA\Deck\Service\LabelService;
class LabelApiControllerTest extends \Test\TestCase {
private $controller;
private $request;
private $labelService;
private $userId = 'admin';
private $exampleLabel;
public function setUp() {
parent::setUp();
$this->request = $this->createMock(IRequest::class);
$this->labelService = $this->createMock(LabelService::class);
$this->exampleLabel['id'];
$this->controller = new LabelApiController(
'deck',
$this->request,
$this->labelService,
$this->userId
);
}
public function testGet() {
$label = new Label();
$label->setId($this->exampleLabel['id']);
$this->request->expects($this->once())
->method('getParam')
->with('labelId')
->will($this->returnValue($this->exampleLabel['id']));
$this->labelService->expects($this->once())
->method('find')
->willReturn($label);
$expected = new DataResponse($label, HTTP::STATUS_OK);
$actual = $this->controller->get();
$this->assertEquals($expected, $actual);
}
public function testCreate() {
$label = new Label();
$label->setId($this->exampleLabel['id']);
$this->request->expects($this->once())
->method('getParam')
->with('boardId')
->will($this->returnValue(1));
$this->labelService->expects($this->once())
->method('create')
->willReturn($label);
$expected = new DataResponse($label, HTTP::STATUS_OK);
$actual = $this->controller->create('title', '000000');
$this->assertEquals($expected, $actual);
}
public function testUpdate() {
$label = new Label();
$label->setId($this->exampleLabel['id']);
$this->request->expects($this->once())
->method('getParam')
->with('labelId')
->will($this->returnValue($this->exampleLabel['id']));
$this->labelService->expects($this->once())
->method('update')
->will($this->returnValue($label));
$expected = new DataResponse($label, HTTP::STATUS_OK);
$actual = $this->controller->update('title', '000000');
$this->assertEquals($expected, $actual);
}
public function testDelete() {
$label = new Label();
$label->setId($this->exampleLabel['id']);
$this->request->expects($this->once())
->method('getParam')
->with('labelId')
->will($this->returnValue($this->exampleLabel['id']));
$this->labelService->expects($this->once())
->method('delete')
->willReturn($label);
$expected = new DataResponse($label, HTTP::STATUS_OK);
$actual = $this->controller->delete();
$this->assertEquals($expected, $actual);
}
}

View File

@@ -0,0 +1,174 @@
<?php
/**
* @copyright Copyright (c) 2018 Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @author Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Deck\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\IRequest;
use OCA\Deck\Service\BoardService;
use OCA\Deck\Service\StackService;
use OCA\Deck\Db\Board;
use OCA\Deck\Db\Stack;
class StackApiControllerTest extends \Test\TestCase {
private $appName = 'deck';
private $userId = 'admin';
private $controller;
private $boardService;
private $stackService;
private $exampleStack;
private $exampleBoard;
public function setUp() {
parent::setUp();
$this->request = $this->createMock(IRequest::class);
$this->boardService = $this->createMock(BoardService::class);
$this->stackService = $this->createMock(StackService::class);
$this->exampleStack['id'] = 345;
$this->exampleStack['boardId'] = $this->exampleBoard['boardId'];
$this->exampleStack['order'] = 0;
$this->exampleStack['title'] = 'Example Stack From API';
$this->exampleBoard['boardId'] = '89';
$this->controller = new StackApiController(
$this->appName,
$this->request,
$this->stackService,
$this->boardService
);
}
public function testIndex() {
$stack = new Stack();
$stack->setId($this->exampleStack['id']);
$stack->setBoardId($this->exampleStack['boardId']);
$stack->setOrder($this->exampleStack['order']);
$stacks = [$stack];
$this->stackService->expects($this->once())
->method('findAll')
->willReturn($stacks);
$this->request->expects($this->any())
->method('getParam')
->with('boardId')
->will($this->returnValue($this->exampleBoard['boardId']));
$expected = new DataResponse($stacks, HTTP::STATUS_OK);
$actual = $this->controller->index();
$this->assertEquals($expected, $actual);
}
public function testGet() {
$stack = new Stack();
$stack->setId($this->exampleStack['id']);
$stack->setBoardId($this->exampleStack['boardId']);
$stack->setOrder($this->exampleStack['order']);
$this->stackService->expects($this->once())
->method('find')
->willReturn($stack);
$this->request->expects($this->once())
->method('getParam')
->with('stackId')
->willReturn($this->exampleStack['id']);
$expected = new DataResponse($stack, HTTP::STATUS_OK);
$actual = $this->controller->get();
$this->assertEquals($expected, $actual);
}
public function testCreate() {
$this->request->expects($this->any())
->method('getParam')
->with('boardId')
->will($this->returnValue($this->exampleBoard['boardId']));
$stack = new Stack();
$stack->setId($this->exampleStack['id']);
$stack->setBoardId($this->exampleStack['boardId']);
$stack->setOrder($this->exampleStack['order']);
$stack->setTitle($this->exampleStack['title']);
$this->stackService->expects($this->once())
->method('create')
->willReturn($stack);
$expected = new DataResponse($stack, HTTP::STATUS_OK);
$actual = $this->controller->create($this->exampleStack['title'], $this->exampleStack['order']);
$this->assertEquals($expected, $actual);
}
public function testUpdate() {
$this->request->expects($this->exactly(2))
->method('getParam')
->withConsecutive(
['stackId'],
['boardId']
)
->willReturnonConsecutiveCalls($this->exampleStack['id'], $this->exampleBoard['boardId']);
$stack = new Stack();
$stack->setId($this->exampleStack['id']);
$stack->setBoardId($this->exampleStack['boardId']);
$stack->setOrder($this->exampleStack['order']);
$stack->setTitle($this->exampleStack['title']);
$this->stackService->expects($this->once())
->method('update')
->willReturn($stack);
$expected = new DataResponse($stack, HTTP::STATUS_OK);
$actual = $this->controller->update($this->exampleStack['title'], $this->exampleStack['order']);
$this->assertEquals($expected, $actual);
}
public function testDelete() {
$stack = new Stack();
$stack->setId($this->exampleStack['id']);
$stack->setBoardId($this->exampleStack['boardId']);
$stack->setOrder($this->exampleStack['order']);
$stack->setTitle($this->exampleStack['title']);
$this->request->expects($this->once())
->method('getParam')
->with('stackId')
->will($this->returnValue($this->exampleStack['id']));
$this->stackService->expects($this->once())
->method('delete')
->willReturn($stack);
$expected = new DataResponse($stack, HTTP::STATUS_OK);
$actual = $this->controller->delete();
$this->assertEquals($expected, $actual);
}
}