diff --git a/appinfo/routes.php b/appinfo/routes.php index 4eda78b04..a86020203 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -34,6 +34,7 @@ return [ ['name' => 'board#read', 'url' => '/boards/{boardId}', 'verb' => 'GET'], ['name' => 'board#update', 'url' => '/boards/{boardId}', 'verb' => 'PUT'], ['name' => 'board#delete', 'url' => '/boards/{boardId}', 'verb' => 'DELETE'], + ['name' => 'board#getUserPermissions', 'url' => '/boards/{boardId}/permissions', 'verb' => 'GET'], ['name' => 'board#addAcl', 'url' => '/boards/{boardId}/acl', 'verb' => 'POST'], ['name' => 'board#updateAcl', 'url' => '/boards/{boardId}/acl', 'verb' => 'PUT'], ['name' => 'board#deleteAcl', 'url' => '/boards/{boardId}/acl/{aclId}', 'verb' => 'DELETE'], diff --git a/js/controller/AppController.js b/js/controller/AppController.js index 555ed2014..bc3242e0d 100644 --- a/js/controller/AppController.js +++ b/js/controller/AppController.js @@ -25,4 +25,5 @@ app.controller('AppController', function ($scope, $location, $http, $route, $log show: false }; $scope.sidebar = $rootScope.sidebar; + $scope.user = oc_current_user; }); \ No newline at end of file diff --git a/js/controller/BoardController.js b/js/controller/BoardController.js index f0d50fcf3..399b116fe 100644 --- a/js/controller/BoardController.js +++ b/js/controller/BoardController.js @@ -113,6 +113,7 @@ app.controller('BoardController', function ($rootScope, $scope, $stateParams, St // Handle initial Loading BoardService.fetchOne($scope.id).then(function (data) { + BoardService.getPermissions(); $scope.statusservice.releaseWaiting(); }, function (error) { $scope.statusservice.setError('Error occured', error); diff --git a/js/controller/CardController.js b/js/controller/CardController.js index d165de4eb..afb08f6fe 100644 --- a/js/controller/CardController.js +++ b/js/controller/CardController.js @@ -41,14 +41,14 @@ app.controller('CardController', function ($scope, $rootScope, $routeParams, $lo }); $scope.cardRenameShow = function() { - if($scope.archived) + if($scope.archived || !BoardService.canEdit()) return false; else { $scope.status.cardRename=true; } }; $scope.cardEditDescriptionShow = function() { - if($scope.archived) + if($scope.archived || !BoardService.canEdit()) return false; else { $scope.status.cardEditDescription=true; diff --git a/js/public/app.js b/js/public/app.js index 853ef77f7..83ca51aec 100644 --- a/js/public/app.js +++ b/js/public/app.js @@ -113,6 +113,7 @@ app.controller('AppController', ["$scope", "$location", "$http", "$route", "$log show: false }; $scope.sidebar = $rootScope.sidebar; + $scope.user = oc_current_user; }]); app.controller('BoardController', ["$rootScope", "$scope", "$stateParams", "StatusService", "BoardService", "StackService", "CardService", "LabelService", "$state", "$transitions", "$filter", function ($rootScope, $scope, $stateParams, StatusService, BoardService, StackService, CardService, LabelService, $state, $transitions, $filter) { @@ -207,6 +208,7 @@ app.controller('BoardController', ["$rootScope", "$scope", "$stateParams", "Stat // Handle initial Loading BoardService.fetchOne($scope.id).then(function (data) { + BoardService.getPermissions(); $scope.statusservice.releaseWaiting(); }, function (error) { $scope.statusservice.setError('Error occured', error); @@ -361,14 +363,14 @@ app.controller('CardController', ["$scope", "$rootScope", "$routeParams", "$loca }); $scope.cardRenameShow = function() { - if($scope.archived) + if($scope.archived || !BoardService.canEdit()) return false; else { $scope.status.cardRename=true; } }; $scope.cardEditDescriptionShow = function() { - if($scope.archived) + if($scope.archived || !BoardService.canEdit()) return false; else { $scope.status.cardEditDescription=true; @@ -978,6 +980,46 @@ app.factory('BoardService', ["ApiService", "$http", "$q", function(ApiService, $ return deferred.promise; }; + BoardService.prototype.getPermissions = function() { + var board = this.getCurrent(); + var deferred = $q.defer(); + $http.get(this.baseUrl + '/' + board.id + '/permissions').then(function (response) { + board.permissions = response.data; + console.log(board.permissions); + deferred.resolve(response.data); + }, function (error) { + deferred.reject('Error fetching board permissions ' + board); + }); + }; + + BoardService.prototype.canRead = function() { + if(!this.getCurrent() || !this.getCurrent().permissions) { + return false; + } + return this.getCurrent().permissions['PERMISSION_READ']; + } + + BoardService.prototype.canEdit = function() { + if(!this.getCurrent() || !this.getCurrent().permissions) { + return false; + } + return this.getCurrent().permissions['PERMISSION_EDIT']; + } + + BoardService.prototype.canManage = function() { + if(!this.getCurrent() || !this.getCurrent().permissions) { + return false; + } + return this.getCurrent().permissions['PERMISSION_MANAGE']; + } + + BoardService.prototype.canShare = function() { + if(!this.getCurrent() || !this.getCurrent().permissions) { + return false; + } + return this.getCurrent().permissions['PERMISSION_SHARE']; + } + service = new BoardService($http, 'boards', $q); return service; diff --git a/js/service/BoardService.js b/js/service/BoardService.js index 9bafa26e9..223725793 100644 --- a/js/service/BoardService.js +++ b/js/service/BoardService.js @@ -100,6 +100,46 @@ app.factory('BoardService', function(ApiService, $http, $q){ return deferred.promise; }; + BoardService.prototype.getPermissions = function() { + var board = this.getCurrent(); + var deferred = $q.defer(); + $http.get(this.baseUrl + '/' + board.id + '/permissions').then(function (response) { + board.permissions = response.data; + console.log(board.permissions); + deferred.resolve(response.data); + }, function (error) { + deferred.reject('Error fetching board permissions ' + board); + }); + }; + + BoardService.prototype.canRead = function() { + if(!this.getCurrent() || !this.getCurrent().permissions) { + return false; + } + return this.getCurrent().permissions['PERMISSION_READ']; + } + + BoardService.prototype.canEdit = function() { + if(!this.getCurrent() || !this.getCurrent().permissions) { + return false; + } + return this.getCurrent().permissions['PERMISSION_EDIT']; + } + + BoardService.prototype.canManage = function() { + if(!this.getCurrent() || !this.getCurrent().permissions) { + return false; + } + return this.getCurrent().permissions['PERMISSION_MANAGE']; + } + + BoardService.prototype.canShare = function() { + if(!this.getCurrent() || !this.getCurrent().permissions) { + return false; + } + return this.getCurrent().permissions['PERMISSION_SHARE']; + } + service = new BoardService($http, 'boards', $q); return service; diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 5ba2a2c0a..e6bf9775b 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -49,6 +49,7 @@ class Application extends App { $container->query('ControllerMethodReflector') ); }); + /** @noinspection PhpMethodOrClassCallIsNotCaseSensitiveInspection */ $container->registerMiddleware('SharingMiddleware'); } diff --git a/lib/Controller/BoardController.php b/lib/Controller/BoardController.php index f3399d81e..d28f6fd65 100644 --- a/lib/Controller/BoardController.php +++ b/lib/Controller/BoardController.php @@ -23,6 +23,7 @@ namespace OCA\Deck\Controller; +use OCA\Deck\Db\Acl; use OCA\Deck\Service\BoardService; use OCP\IRequest; @@ -121,6 +122,33 @@ class BoardController extends Controller { return $this->boardService->labels($boardId); } + /** + * @NoAdminRequired + * @RequireReadPermission + * @param $boardId + * @return array|bool + * @internal param $userId + */ + public function getUserPermissions($boardId) { + $board = $this->boardService->find($boardId); + if($this->userId === $board->getOwner()) { + return [ + 'PERMISSION_READ' => true, + 'PERMISSION_EDIT' => true, + 'PERMISSION_MANAGE' => true, + 'PERMISSION_SHARE' => true, + ]; + } + + return [ + 'PERMISSION_READ' => $this->boardService->getPermission($boardId, $this->userId, Acl::PERMISSION_READ), + 'PERMISSION_EDIT' => $this->boardService->getPermission($boardId, $this->userId, Acl::PERMISSION_EDIT), + 'PERMISSION_MANAGE' => $this->boardService->getPermission($boardId, $this->userId, Acl::PERMISSION_MANAGE), + 'PERMISSION_SHARE' => $this->boardService->getPermission($boardId, $this->userId, Acl::PERMISSION_SHARE), + ]; + + } + /** * @NoAdminRequired * @RequireManagePermission diff --git a/lib/Controller/ShareController.php b/lib/Controller/ShareController.php index ee6981fd1..6d641f7bc 100644 --- a/lib/Controller/ShareController.php +++ b/lib/Controller/ShareController.php @@ -24,6 +24,8 @@ namespace OCA\Deck\Controller; use OCA\Deck\Db\Acl; + +use OCA\Deck\Service\BoardService; use OCP\IGroupManager; use OCP\IRequest; use OCP\AppFramework\Controller; @@ -31,20 +33,23 @@ use OCP\IUserManager; class ShareController extends Controller { - protected $userManager; - protected $groupManager; + private $userManager; + private $groupManager; + private $boardService; private $userId; public function __construct($appName, IRequest $request, IUserManager $userManager, IGroupManager $groupManager, + BoardService $boardService, $userId ){ parent::__construct($appName, $request); $this->userManager = $userManager; $this->groupManager = $groupManager; $this->userId = $userId; + $this->boardService = $boardService; } @@ -81,4 +86,8 @@ class ShareController extends Controller { } return $result; } + + + + } diff --git a/lib/Db/BoardMapper.php b/lib/Db/BoardMapper.php index 27af614b4..a0f66d21d 100644 --- a/lib/Db/BoardMapper.php +++ b/lib/Db/BoardMapper.php @@ -42,9 +42,11 @@ class BoardMapper extends DeckMapper implements IPermissionMapper { /** * @param $id + * @param bool $withLabels + * @param bool $withAcl * @return \OCP\AppFramework\Db\Entity if not found */ - public function find($id) { + public function find($id, $withLabels=false, $withAcl=false) { $sql = 'SELECT id, title, owner, color, archived FROM `*PREFIX*deck_boards` ' . 'WHERE `id` = ?'; $board = $this->findEntity($sql, [$id]); @@ -95,13 +97,12 @@ class BoardMapper extends DeckMapper implements IPermissionMapper { } $sql = 'SELECT boards.id, title, owner, color, archived, 2 as shared FROM oc_deck_boards as boards ' . 'INNER JOIN oc_deck_board_acl as acl ON boards.id=acl.board_id WHERE owner != ? AND type=\'group\' AND ('; - $countGroups = 0; - // FIXME: group unused? - foreach ($groups as $group) { - $sql .= 'acl.participant = ? '; - if(count($groups)>1 && $countGroups++1 && $ifindEntities($sql, array_merge([$userId], $groups), $limit, $offset); /* @var Board $entry */ @@ -112,7 +113,8 @@ class BoardMapper extends DeckMapper implements IPermissionMapper { return $entries; } - public function delete(\OCP\AppFramework\Db\Entity $entity) { + public function delete(/** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */ + \OCP\AppFramework\Db\Entity $entity) { // delete acl $acl = $this->aclMapper->findAll($entity->getId()); foreach ($acl as $item) { diff --git a/lib/Db/CardMapper.php b/lib/Db/CardMapper.php index 9a6ef4b18..e00948a41 100644 --- a/lib/Db/CardMapper.php +++ b/lib/Db/CardMapper.php @@ -25,8 +25,6 @@ namespace OCA\Deck\Db; use OCP\AppFramework\Db\Entity; use OCP\IDb; -use OCP\AppFramework\Db\Mapper; - class CardMapper extends DeckMapper implements IPermissionMapper { diff --git a/lib/Db/DeckMapper.php b/lib/Db/DeckMapper.php index 4c99f45d2..663a9e17a 100644 --- a/lib/Db/DeckMapper.php +++ b/lib/Db/DeckMapper.php @@ -51,6 +51,8 @@ abstract class DeckMapper extends Mapper { protected function execute($sql, array $params = [], $limit = null, $offset = null) { // FIXME: remove on release + /** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */ + /** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */ \OCP\Util::writeLog('deck', "DeckMapper SQL: " . $sql . " with " . implode("|", $params), \OCP\Util::DEBUG); return parent::execute($sql, $params, $limit, $offset); } diff --git a/lib/Db/StackMapper.php b/lib/Db/StackMapper.php index 86bd14a7b..db4ee18b9 100644 --- a/lib/Db/StackMapper.php +++ b/lib/Db/StackMapper.php @@ -25,7 +25,6 @@ namespace OCA\Deck\Db; use OCP\AppFramework\Db\Entity; use OCP\IDb; -use OCP\AppFramework\Db\Mapper; class StackMapper extends DeckMapper implements IPermissionMapper { diff --git a/lib/Middleware/SharingMiddleware.php b/lib/Middleware/SharingMiddleware.php index 8ef5e931a..70498b924 100644 --- a/lib/Middleware/SharingMiddleware.php +++ b/lib/Middleware/SharingMiddleware.php @@ -27,9 +27,11 @@ 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\NoPermissionException; use OCA\Deck\NotFoundException; + use \OCP\AppFramework\Middleware; use OCP\IContainer; use OCP\IRequest; @@ -47,6 +49,7 @@ class SharingMiddleware extends Middleware { private $reflector; private $groupManager; private $aclMapper; + private $boardService; public function __construct( @@ -61,6 +64,7 @@ class SharingMiddleware extends Middleware { $this->reflector = $reflector; $this->aclMapper = $this->container->query('OCA\Deck\Db\AclMapper'); $this->groupManager = $this->container->query('\OCP\IGroupManager'); + $this->boardService = $this->container->query('OCA\Deck\Service\BoardService'); } /** @@ -117,8 +121,7 @@ class SharingMiddleware extends Middleware { $mapper = null; $id = null; - // FIXME: ShareController#search should be limited to board users/groups - if ($controller instanceof BoardController or $controller instanceof ShareController) { + if ($controller instanceof BoardController) { $mapper = $this->container->query('OCA\Deck\Db\BoardMapper'); $id = $params['boardId']; } @@ -198,29 +201,12 @@ class SharingMiddleware extends Middleware { if ($mapper->isOwner($userId, $id)) { return true; } - // find related board $boardId = $mapper->findBoardId($id); if(!$boardId) { throw new NotFoundException("Entity not found"); } - // check if is in acl - - $acls = $this->aclMapper->findAll($boardId); - // check for users - foreach ($acls as $acl) { - if ($acl->getType() === "user" && $acl->getParticipant() === $userId) { - return $acl->getPermission($permission); - } - } - // check for groups - $hasGroupPermission = false; - foreach ($acls as $acl) { - if (!$hasGroupPermission && $acl->getType() === "group" && $this->groupManager->isInGroup($userId, $acl->getParticipant())) { - $hasGroupPermission = $acl->getPermission($permission); - } - } - return $hasGroupPermission; + return $this->boardService->getPermission($boardId, $userId, $permission); } /** diff --git a/lib/Service/BoardService.php b/lib/Service/BoardService.php index ce1fb8643..e8496bc91 100644 --- a/lib/Service/BoardService.php +++ b/lib/Service/BoardService.php @@ -26,6 +26,7 @@ namespace OCA\Deck\Service; use OCA\Deck\Db\Acl; use OCA\Deck\Db\AclMapper; use OCA\Deck\Db\Label; +use OCP\IGroupManager; use OCP\ILogger; use OCP\IL10N; @@ -33,6 +34,7 @@ use OCP\IL10N; use \OCA\Deck\Db\Board; use \OCA\Deck\Db\BoardMapper; use \OCA\Deck\Db\LabelMapper; +use OCP\IUserManager; class BoardService { @@ -47,12 +49,16 @@ class BoardService { ILogger $logger, IL10N $l10n, LabelMapper $labelMapper, - AclMapper $aclMapper) { + AclMapper $aclMapper, + IUserManager $userManager, + IGroupManager $groupManager) { $this->boardMapper = $boardMapper; $this->labelMapper = $labelMapper; $this->aclMapper = $aclMapper; $this->logger = $logger; $this->l10n = $l10n; + $this->userManager = $userManager; + $this->groupManager = $groupManager; } public function findAll($userInfo) { @@ -127,4 +133,22 @@ class BoardService { $acl = $this->aclMapper->find($id); return $this->aclMapper->delete($acl); } + + public function getPermission($boardId, $user, $permission) { + $acls = $this->aclMapper->findAll($boardId); + // check for users + foreach ($acls as $acl) { + if ($acl->getType() === "user" && $acl->getParticipant() === $user) { + return $acl->getPermission($permission); + } + } + // check for groups + $hasGroupPermission = false; + foreach ($acls as $acl) { + if (!$hasGroupPermission && $acl->getType() === "group" && $this->groupManager->isInGroup($user, $acl->getParticipant())) { + $hasGroupPermission = $acl->getPermission($permission); + } + } + return $hasGroupPermission; + } } \ No newline at end of file diff --git a/templates/part.board.mainView.php b/templates/part.board.mainView.php index b791793f4..eacf28c4e 100644 --- a/templates/part.board.mainView.php +++ b/templates/part.board.mainView.php @@ -7,11 +7,11 @@

- {{ boardservice.data[id].title }} + {{ boardservice.getCurrent().title }}
-
-
-
+
+
+

@@ -40,7 +40,7 @@ ng-click="stackservice.delete(s.id)">
- @@ -66,7 +66,7 @@ diff --git a/templates/part.card.php b/templates/part.card.php index b3dc0efd8..4939cd906 100644 --- a/templates/part.card.php +++ b/templates/part.card.php @@ -34,7 +34,7 @@ style="width:100%;" title="Choose a label" placeholder="Add a label" on-select="labelAssign($item, $model)" - on-remove="labelRemove($item, $model)" ng-disabled="archived"> + on-remove="labelRemove($item, $model)" ng-disabled="!boardservice.canEdit() || archived"> {{$item.title}}  diff --git a/templates/part.navigation.php b/templates/part.navigation.php index 40b21db61..ea50e4ff7 100644 --- a/templates/part.navigation.php +++ b/templates/part.navigation.php @@ -7,18 +7,15 @@ {{ b.title }}
    -
  • +
    - -
  • -
  • +
  • +
  • +
@@ -36,7 +33,6 @@
-
  • t('Create a new board')); ?>