diff --git a/appinfo/app.php b/appinfo/app.php index d570e49ae..3dc7fc82d 100644 --- a/appinfo/app.php +++ b/appinfo/app.php @@ -1,43 +1,25 @@ * * @author Julius Härtl - * @copyright Julius Härtl 2016 + * + * @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 . + * */ -namespace OCA\Deck\AppInfo; - -use OCP\AppFramework\App; - -require_once __DIR__ . '/autoload.php'; - -$app = new App('deck'); -$container = $app->getContainer(); - -$container->query('OCP\INavigationManager')->add(function () use ($container) { - $urlGenerator = $container->query('OCP\IURLGenerator'); - $l10n = $container->query('OCP\IL10N'); - return [ - // the string under which your app will be referenced in owncloud - 'id' => 'deck', - - // sorting weight for the navigation. The higher the number, the higher - // will it be listed in the navigation - 'order' => 10, - - // the route that will be shown on startup - 'href' => $urlGenerator->linkToRoute('deck.page.index'), - - // the icon that will be shown in the navigation - // this file needs to exist in img/ - 'icon' => $urlGenerator->imagePath('deck', 'app.svg'), - - // the title of your application. This will be used in the - // navigation or on the settings page of your app - 'name' => $l10n->t('Deck'), - ]; -}); \ No newline at end of file +$app = new \OCA\Deck\AppInfo\Application(); +$app->registerNavigationEntry(); diff --git a/appinfo/routes.php b/appinfo/routes.php index 0ff8ae773..91773e232 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -56,9 +56,6 @@ return [ ['name' => 'card#unarchive', 'url' => '/cards/{cardId}/unarchive', 'verb' => 'PUT'], ['name' => 'card#assignLabel', 'url' => '/cards/{cardId}/label/{labelId}', 'verb' => 'POST'], ['name' => 'card#removeLabel', 'url' => '/cards/{cardId}/label/{labelId}', 'verb' => 'DELETE'], - // TODO: card - assign user - ['name' => 'card#assignUser', 'url' => '/cards/{cardId}/user/{labelId}', 'verb' => 'POST'], - ['name' => 'card#removeUser', 'url' => '/cards/{cardId}/user/{labelId}', 'verb' => 'DELETE'], // labels ['name' => 'label#create', 'url' => '/labels', 'verb' => 'POST'], @@ -66,9 +63,6 @@ return [ ['name' => 'label#delete', 'url' => '/labels/{labelId}', 'verb' => 'DELETE'], // TODO: Implement public board sharing - ['name' => 'public#index', 'url' => '/public/board/:hash', 'verb' => 'GET'], - ['name' => 'public#board', 'url' => '/public/board/ajax/:hash', 'verb' => 'GET'], - // TODO: API for external access ] diff --git a/css/style.css b/css/style.css index bce0b9e86..ab6dd3149 100644 --- a/css/style.css +++ b/css/style.css @@ -862,3 +862,9 @@ button:hover { .icon-archive { background-image: url('../img/archive.svg'); } +.icon-archive-white { + background-image: url('../img/archive-white.svg'); +} +.icon-details { + background-image: url('../img/details-white.svg'); +} diff --git a/appinfo/application.php b/lib/AppInfo/Application.php similarity index 63% rename from appinfo/application.php rename to lib/AppInfo/Application.php index 65cb05b4a..f74aa0422 100644 --- a/appinfo/application.php +++ b/lib/AppInfo/Application.php @@ -28,22 +28,38 @@ use OCA\Deck\Middleware\SharingMiddleware; class Application extends App { + public function __construct(array $urlParams = array()) { parent::__construct('deck', $urlParams); $container = $this->getContainer(); $server = $container->getServer(); - $container->registerService('SharingMiddleware', function ($c) use ($server) { + // This is currently unused + $container->registerService('SharingMiddleware', function ($container) use ($server) { return new SharingMiddleware( - $server->getUserManager(), - $server->getGroupManager(), - $server->getDatabaseConnection(), - $server->getUserSession()->getUser()->getUID() // FIXME: ERROR when logged out!!! + $container, + $server->getRequest(), + $server->getUserSession(), + $container->query('ControllerMethodReflector') ); }); $container->registerMiddleware('SharingMiddleware'); + } + public function registerNavigationEntry() { + $container = $this->getContainer(); + $container->query('OCP\INavigationManager')->add(function () use ($container) { + $urlGenerator = $container->query('OCP\IURLGenerator'); + $l10n = $container->query('OCP\IL10N'); + return [ + 'id' => 'deck', + 'order' => 10, + 'href' => $urlGenerator->linkToRoute('deck.page.index'), + 'icon' => $urlGenerator->imagePath('deck', 'app.svg'), + 'name' => $l10n->t('Deck'), + ]; + }); } } diff --git a/lib/Controller/BoardController.php b/lib/Controller/BoardController.php index 31977cb46..58350f39c 100644 --- a/lib/Controller/BoardController.php +++ b/lib/Controller/BoardController.php @@ -63,16 +63,14 @@ class BoardController extends Controller { * @NoAdminRequired */ public function index() { - return $this->boardService->findAll($this->userInfo); } /** * @NoAdminRequired + * @RequireReadPermission */ public function read($boardId) { - // FIXME: Remove as this is just for testing if loading animation works out nicely - //usleep(2000); return $this->boardService->find($this->userId, $boardId); } @@ -85,6 +83,7 @@ class BoardController extends Controller { /** * @NoAdminRequired + * @RequireManagePermission */ public function update($id, $title, $color) { return $this->boardService->update($id, $title, $this->userId, $color); @@ -92,21 +91,40 @@ class BoardController extends Controller { /** * @NoAdminRequired + * @RequireManagePermission */ public function delete($boardId) { return $this->boardService->delete($this->userId, $boardId); } + /** + * @NoAdminRequired + * @RequireReadPermission + */ public function labels($boardId) { return $this->boardService->labels($this->boardId); } + /** + * @NoAdminRequired + * @RequireManagePermission + */ public function addAcl($boardId, $type, $participant, $write, $invite, $manage) { return $this->boardService->addAcl($boardId, $type, $participant, $write, $invite, $manage); } + + /** + * @NoAdminRequired + * @RequireManagePermission + */ public function updateAcl($id, $permissionWrite, $permissionInvite, $permissionManage) { return $this->boardService->updateAcl($id, $permissionWrite, $permissionInvite, $permissionManage); } + + /** + * @NoAdminRequired + * @RequireManagePermission + */ public function deleteAcl($id) { return $this->boardService->deleteAcl($id); } diff --git a/lib/Controller/CardController.php b/lib/Controller/CardController.php index 4d95b686b..73d63d6ae 100644 --- a/lib/Controller/CardController.php +++ b/lib/Controller/CardController.php @@ -41,42 +41,42 @@ class CardController extends Controller { } /** * @NoAdminRequired - */ - public function index($cardId) { - return $this->cardService->findAll($boardId); - } - /** - * @NoAdminRequired + * @RequireReadPermission */ public function read($cardId) { return $this->cardService->find($this->userId, $cardId); } /** * @NoAdminRequired + * @RequireEditPermission */ public function reorder($cardId, $stackId, $order) { return $this->cardService->reorder($cardId, $stackId, $order); } /** * @NoAdminRequired + * @RequireEditPermission */ public function rename($cardId, $title) { return $this->cardService->rename($cardId, $title); } - /** + /** * @NoAdminRequired + * @RequireEditPermission */ public function create($title, $stackId, $type, $order=999) { return $this->cardService->create($title, $stackId, $type, $order, $this->userId); } /** * @NoAdminRequired + * @RequireEditPermission */ public function update($id, $title, $stackId, $type, $order, $description) { return $this->cardService->update($id, $title, $stackId, $type, $order, $description, $this->userId); } /** * @NoAdminRequired + * @RequireEditPermission */ public function delete($cardId) { return $this->cardService->delete($this->userId, $cardId); @@ -84,24 +84,28 @@ class CardController extends Controller { /** * @NoAdminRequired + * @RequireEditPermission */ public function archive($cardId) { return $this->cardService->archive($cardId); } /** * @NoAdminRequired + * @RequireEditPermission */ public function unarchive($cardId) { return $this->cardService->unarchive($cardId); } /** * @NoAdminRequired + * @RequireEditPermission */ public function assignLabel($cardId, $labelId) { return $this->cardService->assignLabel($this->userId, $cardId, $labelId); } /** * @NoAdminRequired + * @RequireEditPermission */ public function removeLabel($cardId, $labelId) { return $this->cardService->removeLabel($this->userId, $cardId, $labelId); diff --git a/lib/Controller/LabelController.php b/lib/Controller/LabelController.php index 9dc32d6f2..2a8914f4d 100644 --- a/lib/Controller/LabelController.php +++ b/lib/Controller/LabelController.php @@ -44,18 +44,21 @@ class LabelController extends Controller { /** * @NoAdminRequired + * @RequireManagePermission */ public function create($title, $color, $boardId) { return $this->labelService->create($title, $this->userId, $color, $boardId); } /** * @NoAdminRequired + * @RequireManagePermission */ public function update($id, $title, $color) { return $this->labelService->update($id, $title, $this->userId, $color); } /** * @NoAdminRequired + * @RequireManagePermission */ public function delete($labelId) { return $this->labelService->delete($this->userId, $labelId); diff --git a/lib/Controller/ShareController.php b/lib/Controller/ShareController.php index ae04f0c4d..c07c05097 100644 --- a/lib/Controller/ShareController.php +++ b/lib/Controller/ShareController.php @@ -47,8 +47,6 @@ class ShareController extends Controller { } /** - * FIXME: REMOVE, just for testing - * @NoCSRFRequired * @NoAdminRequired */ public function searchUser($search) { diff --git a/lib/Controller/StackController.php b/lib/Controller/StackController.php index faf52f64d..49d061b99 100644 --- a/lib/Controller/StackController.php +++ b/lib/Controller/StackController.php @@ -43,36 +43,42 @@ class StackController extends Controller { } /** * @NoAdminRequired + * @RequireReadPermission */ public function index($boardId) { return $this->stackService->findAll($boardId); } /** * @NoAdminRequired + * @RequireReadPermission */ public function archived($boardId) { return $this->stackService->findAllArchived($boardId); } /** * @NoAdminRequired + * @RequireReadPermission */ public function read($boardId) { return $this->stackService->find($this->userId, $boardId); } /** * @NoAdminRequired + * @RequireManagePermission */ public function create($title, $boardId, $order=999) { return $this->stackService->create($title, $boardId, $order); } /** * @NoAdminRequired + * @RequireManagePermission */ public function update($id, $title, $boardId, $order) { return $this->stackService->update($id, $title, $boardId, $order); } /** * @NoAdminRequired + * @RequireManagePermission */ public function delete($stackId) { return $this->stackService->delete($this->userId, $stackId); diff --git a/lib/Db/AclMapper.php b/lib/Db/AclMapper.php index bfb656c58..942b6a69b 100644 --- a/lib/Db/AclMapper.php +++ b/lib/Db/AclMapper.php @@ -23,30 +23,48 @@ namespace OCA\Deck\Db; +use OCA\Deck\NoPermissionException; use OCP\AppFramework\Db\Entity; use OCP\IDb; use OCP\AppFramework\Db\Mapper; -class AclMapper extends DeckMapper { +class AclMapper extends DeckMapper implements IPermissionMapper { public function __construct(IDb $db) { parent::__construct($db, 'deck_board_acl', '\OCA\Deck\Db\Acl'); } public function findAll($boardId, $limit=null, $offset=null) { - $sql = 'SELECT id, board_id, type, participant, permission_write, permission_invite, permission_manage, 0 as owner FROM `*PREFIX*deck_board_acl` WHERE `board_id` = ? UNION SELECT 0, id, \'user\', owner, 1, 1, 1, 1 FROM `*PREFIX*deck_boards` WHERE `id` = ? '; + $sql = 'SELECT id, board_id, type, participant, permission_write, permission_invite, permission_manage, 0 as owner FROM `*PREFIX*deck_board_acl` WHERE `board_id` = ? ' . + 'UNION SELECT 0, id, \'user\', owner, 1, 1, 1, 1 FROM `*PREFIX*deck_boards` WHERE `id` = ? '; return $this->findEntities($sql, [$boardId, $boardId], $limit, $offset); } + public function findAllShared($boardId) { + $sql = 'SELECT id, board_id, type, participant, permission_write, permission_invite, permission_manage FROM `*PREFIX*deck_board_acl` WHERE `board_id` = ? '; + return $this->findEntities($sql, [$boardId]); + } public function findAllForCard($cardId, $userId) { $findBoardId = "(SELECT board_id from oc_deck_stacks WHERE id IN (SELECT stack_id from oc_deck_cards WHERE id = 15))"; - $sql = "SELECT 0, id, 'user', owner, 1, 1, 1, 1 as owner FROM `oc_deck_boards` WHERE `id` IN (SELECT board_id from oc_deck_stacks WHERE id IN (SELECT stack_id from oc_deck_cards WHERE id = 15)) + $sql = "SELECT 0, id, 'user', owner, 1, 1, 1, 1 as owner FROM `oc_deck_boards` " . + "WHERE `id` IN (SELECT board_id from oc_deck_stacks WHERE id IN (SELECT stack_id from oc_deck_cards WHERE id = 15)) UNION SELECT id, board_id, type, participant, permission_write, permission_invite, permission_manage, 0 FROM oc_deck_board_acl WHERE participant = 'admin' AND board_id IN (SELECT board_id from oc_deck_stacks WHERE id IN (SELECT stack_id from oc_deck_cards WHERE id = 15));"; } + public function isOwner($userId, $aclId) { + $sql = 'SELECT * FROM `*PREFIX*deck_boards` WHERE `id` IN (SELECT board_id FROM `*PREFIX*deck_board_acl` WHERE id = ?)'; + $stmt = $this->execute($sql, [$aclId]); + $row = $stmt->fetch(); + return ($row['owner'] === $userId); + } + + public function findBoardId($aclId) { + $entity = $this->find($aclId); + return $entity->getBoardId(); + } } diff --git a/lib/Db/BoardMapper.php b/lib/Db/BoardMapper.php index f2d03f02a..63b8f3913 100644 --- a/lib/Db/BoardMapper.php +++ b/lib/Db/BoardMapper.php @@ -28,7 +28,7 @@ use OCP\AppFramework\Db\Mapper; use Symfony\Component\Config\Definition\Exception\Exception; -class BoardMapper extends Mapper { +class BoardMapper extends Mapper implements IPermissionMapper { private $labelMapper; private $_relationMappers = array(); @@ -136,4 +136,14 @@ class BoardMapper extends Mapper { } + public function isOwner($userId, $boardId) { + $board = $this->find($boardId); + return ($board->getOwner() === $userId); + } + + public function findBoardId($id) { + return $id; + } + + } \ No newline at end of file diff --git a/lib/Db/CardMapper.php b/lib/Db/CardMapper.php index 184e55c13..9408d1b4a 100644 --- a/lib/Db/CardMapper.php +++ b/lib/Db/CardMapper.php @@ -29,7 +29,7 @@ use OCP\AppFramework\Db\Mapper; -class CardMapper extends Mapper { +class CardMapper extends Mapper implements IPermissionMapper { private $labelMapper; @@ -79,7 +79,6 @@ class CardMapper extends Mapper { return $entities; } - // TODO: test public function findAllArchived($stackId, $limit=null, $offset=null) { $sql = 'SELECT * FROM `*PREFIX*deck_cards` WHERE `stack_id`=? AND archived ORDER BY `last_modified`'; $entities = $this->findEntities($sql, [$stackId], $limit, $offset); @@ -107,5 +106,19 @@ class CardMapper extends Mapper { $stmt->execute(); } + public function isOwner($userId, $cardId) { + $sql = 'SELECT * FROM `*PREFIX*deck_boards` WHERE `id` IN (SELECT board_id FROM `*PREFIX*deck_stacks` WHERE id IN (SELECT stack_id FROM `*PREFIX*deck_cards` WHERE id = ?))'; + $stmt = $this->execute($sql, [$cardId]); + $row = $stmt->fetch(); + return ($row['owner'] === $userId); + } + + public function findBoardId($cardId) { + $sql = 'SELECT * FROM `*PREFIX*deck_boards` WHERE `id` IN (SELECT board_id FROM `*PREFIX*deck_stacks` WHERE id IN (SELECT stack_id FROM `*PREFIX*deck_cards` WHERE id = ?))'; + $stmt = $this->execute($sql, [$cardId]); + $row = $stmt->fetch(); + return $row['id']; + } + } \ No newline at end of file diff --git a/lib/Db/DeckMapper.php b/lib/Db/DeckMapper.php index 3f67bfc84..b38e37820 100644 --- a/lib/Db/DeckMapper.php +++ b/lib/Db/DeckMapper.php @@ -23,7 +23,6 @@ namespace OCA\Deck\Db; -use OCP\AppFramework\Db\Entity; use OCP\AppFramework\Db\Mapper; abstract class DeckMapper extends Mapper { diff --git a/lib/Controller/StyleController.php b/lib/Db/IPermissionMapper.php similarity index 55% rename from lib/Controller/StyleController.php rename to lib/Db/IPermissionMapper.php index 23678b50a..8ba6854a2 100644 --- a/lib/Controller/StyleController.php +++ b/lib/Db/IPermissionMapper.php @@ -5,42 +5,37 @@ * @author Julius Härtl * * @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 . - * + * */ -namespace OCA\Deck\Controller; +/** + * Created by PhpStorm. + * User: jus + * Date: 19.08.16 + * Time: 22:25 + */ -use OCP\IRequest; -use OCP\AppFramework\ApiController as BaseApiController; +namespace OCA\Deck\Db; -class StyleController extends Controller { - private $defaults; - public function __construct($appName, - IRequest $request, OC_Defaults $defaults){ - parent::__construct($appName, $request); - $this->defaults = $defaults; - } - /** - * @PublicPage - * @NoCSRFRequired - */ - public function generateCss() { - $color = $this->config->getAppValue($this->appName, 'color'); - $responseCss .= ''; - $response = new Http\DataDownloadResponse($responseCss, 'style', 'text/css'); - } -} +interface IPermissionMapper { + + public function isOwner($userId, $id); + + public function findBoardId($id); + + +} \ No newline at end of file diff --git a/lib/Db/LabelMapper.php b/lib/Db/LabelMapper.php index cfbdd07c5..9a4ca6a86 100644 --- a/lib/Db/LabelMapper.php +++ b/lib/Db/LabelMapper.php @@ -28,7 +28,7 @@ use OCP\IDb; use OCP\AppFramework\Db\Mapper; -class LabelMapper extends DeckMapper { +class LabelMapper extends DeckMapper implements IPermissionMapper { public function __construct(IDb $db) { parent::__construct($db, 'deck_labels', '\OCA\Deck\Db\Label'); @@ -66,4 +66,16 @@ class LabelMapper extends DeckMapper { } return $result; } + + public function isOwner($userId, $labelId) { + $sql = 'SELECT * FROM `*PREFIX*deck_boards` WHERE `id` IN (SELECT board_id FROM `*PREFIX*deck_labels` WHERE id = ?)'; + $stmt = $this->execute($sql, [$labelId]); + $row = $stmt->fetch(); + return ($row['owner'] === $userId); + } + + public function findBoardId($labelId) { + $entity = $this->find($labelId); + return $entity->getBoardId(); + } } diff --git a/lib/Db/StackMapper.php b/lib/Db/StackMapper.php index ef3dd6f4a..8a7bcd4e0 100644 --- a/lib/Db/StackMapper.php +++ b/lib/Db/StackMapper.php @@ -28,7 +28,7 @@ use OCP\IDb; use OCP\AppFramework\Db\Mapper; -class StackMapper extends Mapper { +class StackMapper extends Mapper implements IPermissionMapper { private $cardMapper; @@ -59,4 +59,16 @@ class StackMapper extends Mapper { // FIXME: delete linked elements, because owncloud doesn't support foreign keys for apps return parent::delete($entity); } + + public function isOwner($userId, $stackId) { + $sql = 'SELECT * FROM `*PREFIX*deck_boards` WHERE `id` IN (SELECT board_id FROM `*PREFIX*deck_stacks` WHERE id = ?)'; + $stmt = $this->execute($sql, [$stackId]); + $row = $stmt->fetch(); + return ($row['owner'] === $userId); + } + + public function findBoardId($stackId) { + $entity = $this->find($stackId); + return $entity->getBoardId(); + } } \ No newline at end of file diff --git a/lib/Middleware/SharingMiddleware.php b/lib/Middleware/SharingMiddleware.php index 50992c47a..17b99fd58 100644 --- a/lib/Middleware/SharingMiddleware.php +++ b/lib/Middleware/SharingMiddleware.php @@ -23,31 +23,260 @@ namespace OCA\Deck\Middleware; +use OC\OCS\Exception; +use OCA\Deck\Controller\BoardController; +use OCA\Deck\Controller\CardController; +use OCA\Deck\Controller\LabelController; +use OCA\Deck\Controller\PageController; +use OCA\Deck\Controller\ShareController; +use OCA\Deck\Db\CardMapper; +use OCA\Deck\NoPermissionException; +use OCA\Deck\Service\ServicePermissionException; +use OCA\Files_Versions\Expiration; use \OCP\AppFramework\Middleware; +use OCP\IContainer; use OCP\IDBConnection; use OCP\IGroupManager; +use OCP\IRequest; use OCP\IUserManager; +use OCA\Deck\Controller\StackController; +use OCP\IUserSession; +use OCP\AppFramework\Http\JSONResponse; +use OC\AppFramework\Utility\ControllerMethodReflector; class SharingMiddleware extends Middleware { + private $container; + private $request; + private $userSession; + private $reflector; + private $groupManager; + public function __construct( - IUserManager $userManager, - IGroupManager $groupManager, - IDBConnection $db, - $userId + IContainer $container, + IRequest $request, + IUserSession $userSession, + ControllerMethodReflector $reflector ) { - $this->userId = $userId; - $this->db = $db; - $this->userManager = $userManager; - $this->groupManager = $groupManager; + $this->container = $container; + $this->request = $request; + $this->userSession = $userSession; + $this->reflector = $reflector; + $this->aclMapper = $this->container->query('OCA\Deck\Db\AclMapper'); + $this->groupManager = $this->container->query('\OCP\IGroupManager'); + } + /** + * All permission checks for controller access + * + * The following method annotaitons are possible + * - RequireReadPermission + * - RequireEditPermission + * - RequireSharePermission + * - RequireManagePermission + * + * Depending on the Controller class we call a corresponding mapper to find the board_id + * With the board_id we can check for ownership/permissions in the acl table + * + * @param \OCP\AppFramework\Controller $controller + * @param string $methodName + * @throws NoPermissionException + */ public function beforeController($controller, $methodName) { - \OCP\Util::writeLog('deck', "", \OCP\Util::ERROR); - //$userBoards = $this->boardMapper->findAllByUser($userInfo['user']); - //$groupBoards = $this->boardMapper->findAllByGroups($userInfo['user'], $userInfo['groups']); + $this->start = microtime(true); + $userId = null; + if($this->userSession->getUser()) { + $userId = $this->userSession->getUser()->getUID(); + } + $method = $this->request->getMethod(); + $params = $this->request->getParams(); + $this->checkPermissions($userId, $controller, $method, $params); + + // TODO: remove, just for testing + \OCP\Util::writeLog('deck', (microtime(true)-$this->start), \OCP\Util::ERROR); } + private function checkPermissions($userId, $controller, $method, $params) { + + // no permission checks needed for plain html page + if($controller instanceof PageController) { + return; + } + + // FIXME: ShareController#search should be limited to board users/groups + if($controller instanceof BoardController or $controller instanceof ShareController) { + $mapper = $this->container->query('OCA\Deck\Db\BoardMapper'); + $id = $params['boardId']; + } + + if($controller instanceof StackController) { + if($method==="GET" || $method === "POST") { + $mapper = $this->container->query('OCA\Deck\Db\BoardMapper'); + $id = $params['boardId']; + } else { + $mapper = $this->container->query('OCA\Deck\Db\StackMapper'); + $id = $params['stackId']; + } + + } + if($controller instanceof CardController) { + if($method==="GET" || $method === "POST") { + $mapper = $this->container->query('OCA\Deck\Db\StackMapper'); + $id = $params['stackId']; + } else { + $mapper = $this->container->query('OCA\Deck\Db\CardMapper'); + $id = $params['cardId']; + } + + } + if($controller instanceof LabelController) { + if($method==="GET" || $method === "POST") { + $mapper = $this->container->query('OCA\Deck\Db\BoardMapper'); + $id = $params['boardId']; + } else { + $mapper = $this->container->query('OCA\Deck\Db\LabelMapper'); + $id = $params['labelId']; + } + + } + + + if($this->reflector->hasAnnotation('RequireReadPermission')) { + if(!$this->checkReadPermission($userId, $mapper, $id)) { + throw new NoPermissionException("User ". $userId . " has no permission to read."); + } + } + if($this->reflector->hasAnnotation('RequireEditPermission')) { + if(!$this->checkEditPermission($userId, $mapper, $id)) { + throw new NoPermissionException("User ". $userId . " has no permission to edit."); + } + + } + if($this->reflector->hasAnnotation('RequireSharePermission')) { + if(!$this->checkSharePermission($userId, $mapper, $id)) { + throw new NoPermissionException("User ". $userId . " has no permission to share."); + } + } + if($this->reflector->hasAnnotation('RequireManagePermission')) { + if(!$this->checkManagePermission($userId, $mapper, $id)) { + throw new NoPermissionException("User ". $userId . " has no permission to manage."); + } + } + + // FIXME: Default should be nopermisison mybe add norequirepermission for index + + } + + /* TODO: Priorize groups with higher permissions */ + public function checkReadPermission($userId, $mapper, $id) { + // is owner + if($mapper->isOwner($userId, $id)) { + return true; + } + $boardId = $mapper->findBoardId($id); + $acls = $this->aclMapper->findAllShared($boardId); + // check for users + foreach ($acls as $acl) { + if($acl->getType() === "user" && $acl->getParticipant() === $userId) { + return true; + } + } + // check for groups + foreach ($acls as $acl) { + if($acl->getType() === "user" && $this->groupManager->isInGroup($userId, $acl->getParticipant())) { + return true; + } + } + + throw new NoPermissionException("User ". $userId . " has no permission to read."); + + } + public function checkEditPermission($userId, $mapper, $id) { + // is owner + if($mapper->isOwner($userId, $id)) { + return true; + } + // check if is in acl + $boardId = $mapper->findBoardId($id); + $acls = $this->aclMapper->findAllShared($boardId); + // check for users + foreach ($acls as $acl) { + if($acl->getType() === "user" && $acl->getParticipant() === $userId) { + return $acl->getPermissionWrite(); + } + } + // check for groups + foreach ($acls as $acl) { + if($acl->getType() === "user" && $this->groupManager->isInGroup($userId, $acl->getParticipant())) { + return $acl->getPermissionWrite(); + } + } + + throw new NoPermissionException("User ". $userId . " has no permission to edit."); + + } + public function checkManagePermission($userId, $mapper, $id) { + // is owner + if($mapper->isOwner($userId, $id)) { + return true; + } + // check if is in acl + $boardId = $mapper->findBoardId($id); + $acls = $this->aclMapper->findAllShared($boardId); + // check for users + foreach ($acls as $acl) { + if($acl->getType() === "user" && $acl->getParticipant() === $userId) { + return $acl->getPermissionManage(); + } + } + // check for groups + foreach ($acls as $acl) { + if($acl->getType() === "user" && $this->groupManager->isInGroup($userId, $acl->getParticipant())) { + return $acl->getPermissionManage(); + } + } + + throw new NoPermissionException(); + + } + public function checkSharePermission($userId, $mapper, $id) { + // is owner + if($mapper->isOwner($userId, $id)) { + return true; + } + // check if is in acl + $boardId = $mapper->findBoardId($id); + $acls = $this->aclMapper->findAllShared($boardId); + // check for users + foreach ($acls as $acl) { + if($acl->getType() === "user" && $acl->getParticipant() === $userId) { + return $acl->getPermissionInvite(); + } + } + // check for groups + foreach ($acls as $acl) { + if($acl->getType() === "user" && $this->groupManager->isInGroup($userId, $acl->getParticipant())) { + return $acl->getPermissionInvite(); + } + } + + throw new NoPermissionException(); + + } + + public function afterException($controller, $methodName, \Exception $exception) { + \OCP\Util::writeLog('deck', (microtime(true)-$this->start), \OCP\Util::ERROR); + if(is_a($exception, '\OCA\Deck\NoPermissionException')) { + return new JSONResponse([ + "status" => 401, + "message" => $exception->getMessage() + ], 401); + } + throw $exception; + } + + } \ No newline at end of file diff --git a/lib/NoPermissionException.php b/lib/NoPermissionException.php new file mode 100644 index 000000000..6ad682031 --- /dev/null +++ b/lib/NoPermissionException.php @@ -0,0 +1,29 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ + +namespace OCA\Deck; + + +class NoPermissionException extends \Exception { + +} \ No newline at end of file diff --git a/lib/Service/BoardService.php b/lib/Service/BoardService.php index ed12af2a8..f75abce96 100644 --- a/lib/Service/BoardService.php +++ b/lib/Service/BoardService.php @@ -66,13 +66,7 @@ class BoardService { public function find($userId, $boardId) { $board = $this->boardMapper->find($boardId); - if ($board->getOwner() === $userId) - return $board; - else - return null; - - // FIXME: [share] Check for user permissions - + return $board; } public function create($title, $userId, $color) { diff --git a/lib/Service/LabelService.php b/lib/Service/LabelService.php index 59ffe2c56..7f0bfc531 100644 --- a/lib/Service/LabelService.php +++ b/lib/Service/LabelService.php @@ -51,7 +51,6 @@ class LabelService { public function find($userId, $labelId) { $label = $this->labelMapper->find($labelId); - // FIXME: [share] Check for user permissions return $label; } diff --git a/templates/part.board.mainView.php b/templates/part.board.mainView.php index 841f83986..5577cc143 100644 --- a/templates/part.board.mainView.php +++ b/templates/part.board.mainView.php @@ -9,9 +9,9 @@

{{ boardservice.data[id].title }}
-
-
-
+
+
+