diff options
Diffstat (limited to 'app/Api')
38 files changed, 814 insertions, 355 deletions
diff --git a/app/Api/Authorization/ActionAuthorization.php b/app/Api/Authorization/ActionAuthorization.php new file mode 100644 index 00000000..4b41ad82 --- /dev/null +++ b/app/Api/Authorization/ActionAuthorization.php @@ -0,0 +1,19 @@ +<?php + +namespace Kanboard\Api\Authorization; + +/** + * Class ActionAuthorization + * + * @package Kanboard\Api\Authorization + * @author Frederic Guillot + */ +class ActionAuthorization extends ProjectAuthorization +{ + public function check($class, $method, $action_id) + { + if ($this->userSession->isLogged()) { + $this->checkProjectPermission($class, $method, $this->actionModel->getProjectId($action_id)); + } + } +} diff --git a/app/Api/Authorization/CategoryAuthorization.php b/app/Api/Authorization/CategoryAuthorization.php new file mode 100644 index 00000000..f17265a2 --- /dev/null +++ b/app/Api/Authorization/CategoryAuthorization.php @@ -0,0 +1,19 @@ +<?php + +namespace Kanboard\Api\Authorization; + +/** + * Class CategoryAuthorization + * + * @package Kanboard\Api\Authorization + * @author Frederic Guillot + */ +class CategoryAuthorization extends ProjectAuthorization +{ + public function check($class, $method, $category_id) + { + if ($this->userSession->isLogged()) { + $this->checkProjectPermission($class, $method, $this->categoryModel->getProjectId($category_id)); + } + } +} diff --git a/app/Api/Authorization/ColumnAuthorization.php b/app/Api/Authorization/ColumnAuthorization.php new file mode 100644 index 00000000..37aecda2 --- /dev/null +++ b/app/Api/Authorization/ColumnAuthorization.php @@ -0,0 +1,19 @@ +<?php + +namespace Kanboard\Api\Authorization; + +/** + * Class ColumnAuthorization + * + * @package Kanboard\Api\Authorization + * @author Frederic Guillot + */ +class ColumnAuthorization extends ProjectAuthorization +{ + public function check($class, $method, $column_id) + { + if ($this->userSession->isLogged()) { + $this->checkProjectPermission($class, $method, $this->columnModel->getProjectId($column_id)); + } + } +} diff --git a/app/Api/Authorization/CommentAuthorization.php b/app/Api/Authorization/CommentAuthorization.php new file mode 100644 index 00000000..ed15512e --- /dev/null +++ b/app/Api/Authorization/CommentAuthorization.php @@ -0,0 +1,19 @@ +<?php + +namespace Kanboard\Api\Authorization; + +/** + * Class CommentAuthorization + * + * @package Kanboard\Api\Authorization + * @author Frederic Guillot + */ +class CommentAuthorization extends ProjectAuthorization +{ + public function check($class, $method, $comment_id) + { + if ($this->userSession->isLogged()) { + $this->checkProjectPermission($class, $method, $this->commentModel->getProjectId($comment_id)); + } + } +} diff --git a/app/Api/Authorization/ProcedureAuthorization.php b/app/Api/Authorization/ProcedureAuthorization.php new file mode 100644 index 00000000..070a6371 --- /dev/null +++ b/app/Api/Authorization/ProcedureAuthorization.php @@ -0,0 +1,32 @@ +<?php + +namespace Kanboard\Api\Authorization; + +use JsonRPC\Exception\AccessDeniedException; +use Kanboard\Core\Base; + +/** + * Class ProcedureAuthorization + * + * @package Kanboard\Api\Authorization + * @author Frederic Guillot + */ +class ProcedureAuthorization extends Base +{ + private $userSpecificProcedures = array( + 'getMe', + 'getMyDashboard', + 'getMyActivityStream', + 'createMyPrivateProject', + 'getMyProjectsList', + 'getMyProjects', + 'getMyOverdueTasks', + ); + + public function check($procedure) + { + if (! $this->userSession->isLogged() && in_array($procedure, $this->userSpecificProcedures)) { + throw new AccessDeniedException('This procedure is not available with the API credentials'); + } + } +} diff --git a/app/Api/Authorization/ProjectAuthorization.php b/app/Api/Authorization/ProjectAuthorization.php new file mode 100644 index 00000000..21ecf311 --- /dev/null +++ b/app/Api/Authorization/ProjectAuthorization.php @@ -0,0 +1,35 @@ +<?php + +namespace Kanboard\Api\Authorization; + +use JsonRPC\Exception\AccessDeniedException; +use Kanboard\Core\Base; + +/** + * Class ProjectAuthorization + * + * @package Kanboard\Api\Authorization + * @author Frederic Guillot + */ +class ProjectAuthorization extends Base +{ + public function check($class, $method, $project_id) + { + if ($this->userSession->isLogged()) { + $this->checkProjectPermission($class, $method, $project_id); + } + } + + protected function checkProjectPermission($class, $method, $project_id) + { + if (empty($project_id)) { + throw new AccessDeniedException('Project not found'); + } + + $role = $this->projectUserRoleModel->getUserRole($project_id, $this->userSession->getId()); + + if (! $this->apiProjectAuthorization->isAllowed($class, $method, $role)) { + throw new AccessDeniedException('Project access denied'); + } + } +} diff --git a/app/Api/Authorization/SubtaskAuthorization.php b/app/Api/Authorization/SubtaskAuthorization.php new file mode 100644 index 00000000..fcb57929 --- /dev/null +++ b/app/Api/Authorization/SubtaskAuthorization.php @@ -0,0 +1,19 @@ +<?php + +namespace Kanboard\Api\Authorization; + +/** + * Class SubtaskAuthorization + * + * @package Kanboard\Api\Authorization + * @author Frederic Guillot + */ +class SubtaskAuthorization extends ProjectAuthorization +{ + public function check($class, $method, $subtask_id) + { + if ($this->userSession->isLogged()) { + $this->checkProjectPermission($class, $method, $this->subtaskModel->getProjectId($subtask_id)); + } + } +} diff --git a/app/Api/Authorization/TaskAuthorization.php b/app/Api/Authorization/TaskAuthorization.php new file mode 100644 index 00000000..db93b76b --- /dev/null +++ b/app/Api/Authorization/TaskAuthorization.php @@ -0,0 +1,19 @@ +<?php + +namespace Kanboard\Api\Authorization; + +/** + * Class TaskAuthorization + * + * @package Kanboard\Api\Authorization + * @author Frederic Guillot + */ +class TaskAuthorization extends ProjectAuthorization +{ + public function check($class, $method, $category_id) + { + if ($this->userSession->isLogged()) { + $this->checkProjectPermission($class, $method, $this->taskFinderModel->getProjectId($category_id)); + } + } +} diff --git a/app/Api/Authorization/TaskFileAuthorization.php b/app/Api/Authorization/TaskFileAuthorization.php new file mode 100644 index 00000000..e40783eb --- /dev/null +++ b/app/Api/Authorization/TaskFileAuthorization.php @@ -0,0 +1,19 @@ +<?php + +namespace Kanboard\Api\Authorization; + +/** + * Class TaskFileAuthorization + * + * @package Kanboard\Api\Authorization + * @author Frederic Guillot + */ +class TaskFileAuthorization extends ProjectAuthorization +{ + public function check($class, $method, $file_id) + { + if ($this->userSession->isLogged()) { + $this->checkProjectPermission($class, $method, $this->taskFileModel->getProjectId($file_id)); + } + } +} diff --git a/app/Api/Authorization/TaskLinkAuthorization.php b/app/Api/Authorization/TaskLinkAuthorization.php new file mode 100644 index 00000000..2f5fc8d5 --- /dev/null +++ b/app/Api/Authorization/TaskLinkAuthorization.php @@ -0,0 +1,19 @@ +<?php + +namespace Kanboard\Api\Authorization; + +/** + * Class TaskLinkAuthorization + * + * @package Kanboard\Api\Authorization + * @author Frederic Guillot + */ +class TaskLinkAuthorization extends ProjectAuthorization +{ + public function check($class, $method, $task_link_id) + { + if ($this->userSession->isLogged()) { + $this->checkProjectPermission($class, $method, $this->taskLinkModel->getProjectId($task_link_id)); + } + } +} diff --git a/app/Api/Authorization/UserAuthorization.php b/app/Api/Authorization/UserAuthorization.php new file mode 100644 index 00000000..3fd6865c --- /dev/null +++ b/app/Api/Authorization/UserAuthorization.php @@ -0,0 +1,22 @@ +<?php + +namespace Kanboard\Api\Authorization; + +use JsonRPC\Exception\AccessDeniedException; +use Kanboard\Core\Base; + +/** + * Class UserAuthorization + * + * @package Kanboard\Api\Authorization + * @author Frederic Guillot + */ +class UserAuthorization extends Base +{ + public function check($class, $method) + { + if ($this->userSession->isLogged() && ! $this->apiAuthorization->isAllowed($class, $method, $this->userSession->getRole())) { + throw new AccessDeniedException('You are not allowed to access to this resource'); + } + } +} diff --git a/app/Api/BoardApi.php b/app/Api/BoardApi.php deleted file mode 100644 index aa5942af..00000000 --- a/app/Api/BoardApi.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -namespace Kanboard\Api; - -/** - * Board API controller - * - * @package Kanboard\Api - * @author Frederic Guillot - */ -class BoardApi extends BaseApi -{ - public function getBoard($project_id) - { - $this->checkProjectPermission($project_id); - return $this->boardModel->getBoard($project_id); - } -} diff --git a/app/Api/Middleware/AuthenticationApiMiddleware.php b/app/Api/Middleware/AuthenticationMiddleware.php index b16e10b8..8e309593 100644 --- a/app/Api/Middleware/AuthenticationApiMiddleware.php +++ b/app/Api/Middleware/AuthenticationMiddleware.php @@ -13,46 +13,8 @@ use Kanboard\Core\Base; * @package Kanboard\Api\Middleware * @author Frederic Guillot */ -class AuthenticationApiMiddleware extends Base implements MiddlewareInterface +class AuthenticationMiddleware extends Base implements MiddlewareInterface { - private $user_allowed_procedures = array( - 'getMe', - 'getMyDashboard', - 'getMyActivityStream', - 'createMyPrivateProject', - 'getMyProjectsList', - 'getMyProjects', - 'getMyOverdueTasks', - ); - - private $both_allowed_procedures = array( - 'getTimezone', - 'getVersion', - 'getDefaultTaskColor', - 'getDefaultTaskColors', - 'getColorList', - 'getProjectById', - 'getSubTask', - 'getTask', - 'getTaskByReference', - 'getTimeSpent', - 'getAllTasks', - 'getAllSubTasks', - 'hasTimer', - 'logStartTime', - 'logEndTime', - 'openTask', - 'closeTask', - 'moveTaskPosition', - 'createTask', - 'createSubtask', - 'updateTask', - 'getBoard', - 'getProjectActivity', - 'getOverdueTasksByProject', - 'searchTasks', - ); - /** * Execute Middleware * @@ -68,11 +30,8 @@ class AuthenticationApiMiddleware extends Base implements MiddlewareInterface $this->dispatcher->dispatch('app.bootstrap'); if ($this->isUserAuthenticated($username, $password)) { - $this->checkProcedurePermission(true, $procedureName); $this->userSession->initialize($this->userModel->getByUsername($username)); - } elseif ($this->isAppAuthenticated($username, $password)) { - $this->checkProcedurePermission(false, $procedureName); - } else { + } elseif (! $this->isAppAuthenticated($username, $password)) { $this->logger->error('API authentication failure for '.$username); throw new AuthenticationFailureException('Wrong credentials'); } @@ -120,18 +79,4 @@ class AuthenticationApiMiddleware extends Base implements MiddlewareInterface return $this->configModel->get('api_token'); } - - public function checkProcedurePermission($is_user, $procedure) - { - $is_both_procedure = in_array($procedure, $this->both_allowed_procedures); - $is_user_procedure = in_array($procedure, $this->user_allowed_procedures); - - if ($is_user && ! $is_both_procedure && ! $is_user_procedure) { - throw new AccessDeniedException('Permission denied'); - } elseif (! $is_user && ! $is_both_procedure && $is_user_procedure) { - throw new AccessDeniedException('Permission denied'); - } - - $this->logger->debug('API call: '.$procedure); - } } diff --git a/app/Api/ActionApi.php b/app/Api/Procedure/ActionProcedure.php index 116742d8..4043dbb9 100644 --- a/app/Api/ActionApi.php +++ b/app/Api/Procedure/ActionProcedure.php @@ -1,16 +1,17 @@ <?php -namespace Kanboard\Api; +namespace Kanboard\Api\Procedure; -use Kanboard\Core\Base; +use Kanboard\Api\Authorization\ActionAuthorization; +use Kanboard\Api\Authorization\ProjectAuthorization; /** * Action API controller * - * @package Kanboard\Api + * @package Kanboard\Api\Procedure * @author Frederic Guillot */ -class ActionApi extends Base +class ActionProcedure extends BaseProcedure { public function getAvailableActions() { @@ -29,16 +30,19 @@ class ActionApi extends Base public function removeAction($action_id) { + ActionAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeAction', $action_id); return $this->actionModel->remove($action_id); } public function getActions($project_id) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getActions', $project_id); return $this->actionModel->getAllByProject($project_id); } public function createAction($project_id, $event_name, $action_name, array $params) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createAction', $project_id); $values = array( 'project_id' => $project_id, 'event_name' => $event_name, diff --git a/app/Api/AppApi.php b/app/Api/Procedure/AppProcedure.php index 637de5c5..60af4a60 100644 --- a/app/Api/AppApi.php +++ b/app/Api/Procedure/AppProcedure.php @@ -1,16 +1,14 @@ <?php -namespace Kanboard\Api; - -use Kanboard\Core\Base; +namespace Kanboard\Api\Procedure; /** * App API controller * - * @package Kanboard\Api + * @package Kanboard\Api\Procedure * @author Frederic Guillot */ -class AppApi extends Base +class AppProcedure extends BaseProcedure { public function getTimezone() { diff --git a/app/Api/BaseApi.php b/app/Api/Procedure/BaseProcedure.php index 9f69aa65..e31b3027 100644 --- a/app/Api/BaseApi.php +++ b/app/Api/Procedure/BaseProcedure.php @@ -1,30 +1,24 @@ <?php -namespace Kanboard\Api; +namespace Kanboard\Api\Procedure; -use JsonRPC\Exception\AccessDeniedException; +use Kanboard\Api\Authorization\ProcedureAuthorization; +use Kanboard\Api\Authorization\UserAuthorization; use Kanboard\Core\Base; +use ReflectionClass; /** * Base class * - * @package Kanboard\Api + * @package Kanboard\Api\Procedure * @author Frederic Guillot */ -abstract class BaseApi extends Base +abstract class BaseProcedure extends Base { - public function checkProjectPermission($project_id) + public function beforeProcedure($procedure) { - if ($this->userSession->isLogged() && ! $this->projectPermissionModel->isUserAllowed($project_id, $this->userSession->getId())) { - throw new AccessDeniedException('Permission denied'); - } - } - - public function checkTaskPermission($task_id) - { - if ($this->userSession->isLogged()) { - $this->checkProjectPermission($this->taskFinderModel->getProjectId($task_id)); - } + ProcedureAuthorization::getInstance($this->container)->check($procedure); + UserAuthorization::getInstance($this->container)->check($this->getClassName(), $procedure); } protected function formatTask($task) @@ -71,4 +65,21 @@ abstract class BaseApi extends Base return $projects; } + + protected function filterValues(array $values) + { + foreach ($values as $key => $value) { + if (is_null($value)) { + unset($values[$key]); + } + } + + return $values; + } + + protected function getClassName() + { + $reflection = new ReflectionClass(get_called_class()); + return $reflection->getShortName(); + } } diff --git a/app/Api/Procedure/BoardProcedure.php b/app/Api/Procedure/BoardProcedure.php new file mode 100644 index 00000000..674b5466 --- /dev/null +++ b/app/Api/Procedure/BoardProcedure.php @@ -0,0 +1,25 @@ +<?php + +namespace Kanboard\Api\Procedure; + +use Kanboard\Api\Authorization\ProjectAuthorization; +use Kanboard\Formatter\BoardFormatter; + +/** + * Board API controller + * + * @package Kanboard\Api\Procedure + * @author Frederic Guillot + */ +class BoardProcedure extends BaseProcedure +{ + public function getBoard($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getBoard', $project_id); + + return BoardFormatter::getInstance($this->container) + ->withProjectId($project_id) + ->withQuery($this->taskFinderModel->getExtendedQuery()) + ->format(); + } +} diff --git a/app/Api/CategoryApi.php b/app/Api/Procedure/CategoryProcedure.php index c56cfb35..3ebbd908 100644 --- a/app/Api/CategoryApi.php +++ b/app/Api/Procedure/CategoryProcedure.php @@ -1,34 +1,40 @@ <?php -namespace Kanboard\Api; +namespace Kanboard\Api\Procedure; -use Kanboard\Core\Base; +use Kanboard\Api\Authorization\CategoryAuthorization; +use Kanboard\Api\Authorization\ProjectAuthorization; /** * Category API controller * - * @package Kanboard\Api + * @package Kanboard\Api\Procedure * @author Frederic Guillot */ -class CategoryApi extends Base +class CategoryProcedure extends BaseProcedure { public function getCategory($category_id) { + CategoryAuthorization::getInstance($this->container)->check($this->getClassName(), 'getCategory', $category_id); return $this->categoryModel->getById($category_id); } public function getAllCategories($project_id) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllCategories', $project_id); return $this->categoryModel->getAll($project_id); } public function removeCategory($category_id) { + CategoryAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeCategory', $category_id); return $this->categoryModel->remove($category_id); } public function createCategory($project_id, $name) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createCategory', $project_id); + $values = array( 'project_id' => $project_id, 'name' => $name, @@ -40,6 +46,8 @@ class CategoryApi extends Base public function updateCategory($id, $name) { + CategoryAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateCategory', $id); + $values = array( 'id' => $id, 'name' => $name, diff --git a/app/Api/ColumnApi.php b/app/Api/Procedure/ColumnProcedure.php index aa4026f6..ab9d173b 100644 --- a/app/Api/ColumnApi.php +++ b/app/Api/Procedure/ColumnProcedure.php @@ -1,42 +1,51 @@ <?php -namespace Kanboard\Api; +namespace Kanboard\Api\Procedure; + +use Kanboard\Api\Authorization\ColumnAuthorization; +use Kanboard\Api\Authorization\ProjectAuthorization; /** * Column API controller * - * @package Kanboard\Api + * @package Kanboard\Api\Procedure * @author Frederic Guillot */ -class ColumnApi extends BaseApi +class ColumnProcedure extends BaseProcedure { public function getColumns($project_id) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getColumns', $project_id); return $this->columnModel->getAll($project_id); } public function getColumn($column_id) { + ColumnAuthorization::getInstance($this->container)->check($this->getClassName(), 'getColumn', $column_id); return $this->columnModel->getById($column_id); } public function updateColumn($column_id, $title, $task_limit = 0, $description = '') { + ColumnAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateColumn', $column_id); return $this->columnModel->update($column_id, $title, $task_limit, $description); } public function addColumn($project_id, $title, $task_limit = 0, $description = '') { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'addColumn', $project_id); return $this->columnModel->create($project_id, $title, $task_limit, $description); } public function removeColumn($column_id) { + ColumnAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeColumn', $column_id); return $this->columnModel->remove($column_id); } public function changeColumnPosition($project_id, $column_id, $position) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'changeColumnPosition', $project_id); return $this->columnModel->changePosition($project_id, $column_id, $position); } } diff --git a/app/Api/CommentApi.php b/app/Api/Procedure/CommentProcedure.php index 8358efee..019a49bb 100644 --- a/app/Api/CommentApi.php +++ b/app/Api/Procedure/CommentProcedure.php @@ -1,34 +1,40 @@ <?php -namespace Kanboard\Api; +namespace Kanboard\Api\Procedure; -use Kanboard\Core\Base; +use Kanboard\Api\Authorization\CommentAuthorization; +use Kanboard\Api\Authorization\TaskAuthorization; /** * Comment API controller * - * @package Kanboard\Api + * @package Kanboard\Api\Procedure * @author Frederic Guillot */ -class CommentApi extends Base +class CommentProcedure extends BaseProcedure { public function getComment($comment_id) { + CommentAuthorization::getInstance($this->container)->check($this->getClassName(), 'getComment', $comment_id); return $this->commentModel->getById($comment_id); } public function getAllComments($task_id) { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllComments', $task_id); return $this->commentModel->getAll($task_id); } public function removeComment($comment_id) { + CommentAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeComment', $comment_id); return $this->commentModel->remove($comment_id); } public function createComment($task_id, $user_id, $content, $reference = '') { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'createComment', $task_id); + $values = array( 'task_id' => $task_id, 'user_id' => $user_id, @@ -43,6 +49,8 @@ class CommentApi extends Base public function updateComment($id, $content) { + CommentAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateComment', $id); + $values = array( 'id' => $id, 'comment' => $content, diff --git a/app/Api/GroupMemberApi.php b/app/Api/Procedure/GroupMemberProcedure.php index e09f6975..081d6ac8 100644 --- a/app/Api/GroupMemberApi.php +++ b/app/Api/Procedure/GroupMemberProcedure.php @@ -1,16 +1,14 @@ <?php -namespace Kanboard\Api; - -use Kanboard\Core\Base; +namespace Kanboard\Api\Procedure; /** * Group Member API controller * - * @package Kanboard\Api + * @package Kanboard\Api\Procedure * @author Frederic Guillot */ -class GroupMemberApi extends Base +class GroupMemberProcedure extends BaseProcedure { public function getMemberGroups($user_id) { diff --git a/app/Api/GroupApi.php b/app/Api/Procedure/GroupProcedure.php index 1701edc3..804940a2 100644 --- a/app/Api/GroupApi.php +++ b/app/Api/Procedure/GroupProcedure.php @@ -1,16 +1,14 @@ <?php -namespace Kanboard\Api; - -use Kanboard\Core\Base; +namespace Kanboard\Api\Procedure; /** * Group API controller * - * @package Kanboard\Api + * @package Kanboard\Api\Procedure * @author Frederic Guillot */ -class GroupApi extends Base +class GroupProcedure extends BaseProcedure { public function createGroup($name, $external_id = '') { diff --git a/app/Api/LinkApi.php b/app/Api/Procedure/LinkProcedure.php index d8e525e4..b4cecf3a 100644 --- a/app/Api/LinkApi.php +++ b/app/Api/Procedure/LinkProcedure.php @@ -1,16 +1,14 @@ <?php -namespace Kanboard\Api; - -use Kanboard\Core\Base; +namespace Kanboard\Api\Procedure; /** * Link API controller * - * @package Kanboard\Api + * @package Kanboard\Api\Procedure * @author Frederic Guillot */ -class LinkApi extends Base +class LinkProcedure extends BaseProcedure { /** * Get a link by id diff --git a/app/Api/MeApi.php b/app/Api/Procedure/MeProcedure.php index 497749b6..e59e6522 100644 --- a/app/Api/MeApi.php +++ b/app/Api/Procedure/MeProcedure.php @@ -1,16 +1,16 @@ <?php -namespace Kanboard\Api; +namespace Kanboard\Api\Procedure; use Kanboard\Model\SubtaskModel; /** * Me API controller * - * @package Kanboard\Api + * @package Kanboard\Api\Procedure * @author Frederic Guillot */ -class MeApi extends BaseApi +class MeProcedure extends BaseProcedure { public function getMe() { diff --git a/app/Api/Procedure/ProjectFileProcedure.php b/app/Api/Procedure/ProjectFileProcedure.php new file mode 100644 index 00000000..48466ce3 --- /dev/null +++ b/app/Api/Procedure/ProjectFileProcedure.php @@ -0,0 +1,68 @@ +<?php + +namespace Kanboard\Api\Procedure; + +use Kanboard\Api\Authorization\ProjectAuthorization; +use Kanboard\Core\ObjectStorage\ObjectStorageException; + +/** + * Project File API controller + * + * @package Kanboard\Api\Procedure + * @author Frederic Guillot + */ +class ProjectFileProcedure extends BaseProcedure +{ + public function getProjectFile($project_id, $file_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectFile', $project_id); + return $this->projectFileModel->getById($file_id); + } + + public function getAllProjectFiles($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllProjectFiles', $project_id); + return $this->projectFileModel->getAll($project_id); + } + + public function downloadProjectFile($project_id, $file_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'downloadProjectFile', $project_id); + + try { + $file = $this->projectFileModel->getById($file_id); + + if (! empty($file)) { + return base64_encode($this->objectStorage->get($file['path'])); + } + } catch (ObjectStorageException $e) { + $this->logger->error($e->getMessage()); + } + + return ''; + } + + public function createProjectFile($project_id, $filename, $blob) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createProjectFile', $project_id); + + try { + return $this->projectFileModel->uploadContent($project_id, $filename, $blob); + } catch (ObjectStorageException $e) { + $this->logger->error(__METHOD__.': '.$e->getMessage()); + return false; + } + } + + public function removeProjectFile($project_id, $file_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeProjectFile', $project_id); + return $this->projectFileModel->remove($file_id); + } + + public function removeAllProjectFiles($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeAllProjectFiles', $project_id); + return $this->projectFileModel->removeAll($project_id); + } +} diff --git a/app/Api/ProjectPermissionApi.php b/app/Api/Procedure/ProjectPermissionProcedure.php index 703cd0f3..e22e1d62 100644 --- a/app/Api/ProjectPermissionApi.php +++ b/app/Api/Procedure/ProjectPermissionProcedure.php @@ -1,73 +1,69 @@ <?php -namespace Kanboard\Api; +namespace Kanboard\Api\Procedure; -use Kanboard\Core\Base; +use Kanboard\Api\Authorization\ProjectAuthorization; use Kanboard\Core\Security\Role; /** * Project Permission API controller * - * @package Kanboard\Api + * @package Kanboard\Api\Procedure * @author Frederic Guillot */ -class ProjectPermissionApi extends Base +class ProjectPermissionProcedure extends BaseProcedure { public function getProjectUsers($project_id) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectUsers', $project_id); return $this->projectUserRoleModel->getAllUsers($project_id); } public function getAssignableUsers($project_id, $prepend_unassigned = false) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAssignableUsers', $project_id); return $this->projectUserRoleModel->getAssignableUsersList($project_id, $prepend_unassigned); } public function addProjectUser($project_id, $user_id, $role = Role::PROJECT_MEMBER) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'addProjectUser', $project_id); return $this->projectUserRoleModel->addUser($project_id, $user_id, $role); } public function addProjectGroup($project_id, $group_id, $role = Role::PROJECT_MEMBER) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'addProjectGroup', $project_id); return $this->projectGroupRoleModel->addGroup($project_id, $group_id, $role); } public function removeProjectUser($project_id, $user_id) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeProjectUser', $project_id); return $this->projectUserRoleModel->removeUser($project_id, $user_id); } public function removeProjectGroup($project_id, $group_id) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeProjectGroup', $project_id); return $this->projectGroupRoleModel->removeGroup($project_id, $group_id); } public function changeProjectUserRole($project_id, $user_id, $role) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'changeProjectUserRole', $project_id); return $this->projectUserRoleModel->changeUserRole($project_id, $user_id, $role); } public function changeProjectGroupRole($project_id, $group_id, $role) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'changeProjectGroupRole', $project_id); return $this->projectGroupRoleModel->changeGroupRole($project_id, $group_id, $role); } - // Deprecated - public function getMembers($project_id) + public function getProjectUserRole($project_id, $user_id) { - return $this->getProjectUsers($project_id); - } - - // Deprecated - public function revokeUser($project_id, $user_id) - { - return $this->removeProjectUser($project_id, $user_id); - } - - // Deprecated - public function allowUser($project_id, $user_id) - { - return $this->addProjectUser($project_id, $user_id); + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectUserRole', $project_id); + return $this->projectUserRoleModel->getUserRole($project_id, $user_id); } } diff --git a/app/Api/Procedure/ProjectProcedure.php b/app/Api/Procedure/ProjectProcedure.php new file mode 100644 index 00000000..a580c8d9 --- /dev/null +++ b/app/Api/Procedure/ProjectProcedure.php @@ -0,0 +1,113 @@ +<?php + +namespace Kanboard\Api\Procedure; + +use Kanboard\Api\Authorization\ProjectAuthorization; + +/** + * Project API controller + * + * @package Kanboard\Api\Procedure + * @author Frederic Guillot + */ +class ProjectProcedure extends BaseProcedure +{ + public function getProjectById($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectById', $project_id); + return $this->formatProject($this->projectModel->getById($project_id)); + } + + public function getProjectByName($name) + { + $project = $this->projectModel->getByName($name); + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectByName', $project['id']); + return $this->formatProject($project); + } + + public function getProjectByIdentifier($identifier) + { + $project = $this->formatProject($this->projectModel->getByIdentifier($identifier)); + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectByIdentifier', $project['id']); + return $this->formatProject($project); + } + + public function getAllProjects() + { + return $this->formatProjects($this->projectModel->getAll()); + } + + public function removeProject($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeProject', $project_id); + return $this->projectModel->remove($project_id); + } + + public function enableProject($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'enableProject', $project_id); + return $this->projectModel->enable($project_id); + } + + public function disableProject($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'disableProject', $project_id); + return $this->projectModel->disable($project_id); + } + + public function enableProjectPublicAccess($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'enableProjectPublicAccess', $project_id); + return $this->projectModel->enablePublicAccess($project_id); + } + + public function disableProjectPublicAccess($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'disableProjectPublicAccess', $project_id); + return $this->projectModel->disablePublicAccess($project_id); + } + + public function getProjectActivities(array $project_ids) + { + foreach ($project_ids as $project_id) { + ProjectAuthorization::getInstance($this->container) + ->check($this->getClassName(), 'getProjectActivities', $project_id); + } + + return $this->helper->projectActivity->getProjectsEvents($project_ids); + } + + public function getProjectActivity($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectActivity', $project_id); + return $this->helper->projectActivity->getProjectEvents($project_id); + } + + public function createProject($name, $description = null, $owner_id = 0, $identifier = null) + { + $values = $this->filterValues(array( + 'name' => $name, + 'description' => $description, + 'identifier' => $identifier, + )); + + list($valid, ) = $this->projectValidator->validateCreation($values); + return $valid ? $this->projectModel->create($values, $owner_id, $this->userSession->isLogged()) : false; + } + + public function updateProject($project_id, $name = null, $description = null, $owner_id = null, $identifier = null) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateProject', $project_id); + + $values = $this->filterValues(array( + 'id' => $project_id, + 'name' => $name, + 'description' => $description, + 'owner_id' => $owner_id, + 'identifier' => $identifier, + )); + + list($valid, ) = $this->projectValidator->validateModification($values); + return $valid && $this->projectModel->update($values); + } +} diff --git a/app/Api/SubtaskApi.php b/app/Api/Procedure/SubtaskProcedure.php index 5764ff7d..e2400912 100644 --- a/app/Api/SubtaskApi.php +++ b/app/Api/Procedure/SubtaskProcedure.php @@ -1,34 +1,40 @@ <?php -namespace Kanboard\Api; +namespace Kanboard\Api\Procedure; -use Kanboard\Core\Base; +use Kanboard\Api\Authorization\SubtaskAuthorization; +use Kanboard\Api\Authorization\TaskAuthorization; /** * Subtask API controller * - * @package Kanboard\Api + * @package Kanboard\Api\Procedure * @author Frederic Guillot */ -class SubtaskApi extends Base +class SubtaskProcedure extends BaseProcedure { public function getSubtask($subtask_id) { + SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getSubtask', $subtask_id); return $this->subtaskModel->getById($subtask_id); } public function getAllSubtasks($task_id) { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllSubtasks', $task_id); return $this->subtaskModel->getAll($task_id); } public function removeSubtask($subtask_id) { + SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeSubtask', $subtask_id); return $this->subtaskModel->remove($subtask_id); } public function createSubtask($task_id, $title, $user_id = 0, $time_estimated = 0, $time_spent = 0, $status = 0) { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'createSubtask', $task_id); + $values = array( 'title' => $title, 'task_id' => $task_id, @@ -44,6 +50,8 @@ class SubtaskApi extends Base public function updateSubtask($id, $task_id, $title = null, $user_id = null, $time_estimated = null, $time_spent = null, $status = null) { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateSubtask', $task_id); + $values = array( 'id' => $id, 'task_id' => $task_id, diff --git a/app/Api/Procedure/SubtaskTimeTrackingProcedure.php b/app/Api/Procedure/SubtaskTimeTrackingProcedure.php new file mode 100644 index 00000000..5ceaa08d --- /dev/null +++ b/app/Api/Procedure/SubtaskTimeTrackingProcedure.php @@ -0,0 +1,39 @@ +<?php + +namespace Kanboard\Api\Procedure; + +use Kanboard\Api\Authorization\SubtaskAuthorization; + +/** + * Subtask Time Tracking API controller + * + * @package Kanboard\Api\Procedure + * @author Frederic Guillot + * @author Nikolaos Georgakis + */ +class SubtaskTimeTrackingProcedure extends BaseProcedure +{ + public function hasSubtaskTimer($subtask_id, $user_id) + { + SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'hasSubtaskTimer', $subtask_id); + return $this->subtaskTimeTrackingModel->hasTimer($subtask_id, $user_id); + } + + public function setSubtaskStartTime($subtask_id, $user_id) + { + SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'setSubtaskStartTime', $subtask_id); + return $this->subtaskTimeTrackingModel->logStartTime($subtask_id, $user_id); + } + + public function setSubtaskEndTime($subtask_id, $user_id) + { + SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'setSubtaskEndTime', $subtask_id); + return $this->subtaskTimeTrackingModel->logEndTime($subtask_id, $user_id); + } + + public function getSubtaskTimeSpent($subtask_id, $user_id) + { + SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getSubtaskTimeSpent', $subtask_id); + return $this->subtaskTimeTrackingModel->getTimeSpent($subtask_id, $user_id); + } +} diff --git a/app/Api/SwimlaneApi.php b/app/Api/Procedure/SwimlaneProcedure.php index c3c56a71..9b7d181d 100644 --- a/app/Api/SwimlaneApi.php +++ b/app/Api/Procedure/SwimlaneProcedure.php @@ -1,34 +1,39 @@ <?php -namespace Kanboard\Api; +namespace Kanboard\Api\Procedure; -use Kanboard\Core\Base; +use Kanboard\Api\Authorization\ProjectAuthorization; /** * Swimlane API controller * - * @package Kanboard\Api + * @package Kanboard\Api\Procedure * @author Frederic Guillot */ -class SwimlaneApi extends Base +class SwimlaneProcedure extends BaseProcedure { public function getActiveSwimlanes($project_id) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getActiveSwimlanes', $project_id); return $this->swimlaneModel->getSwimlanes($project_id); } public function getAllSwimlanes($project_id) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllSwimlanes', $project_id); return $this->swimlaneModel->getAll($project_id); } public function getSwimlaneById($swimlane_id) { - return $this->swimlaneModel->getById($swimlane_id); + $swimlane = $this->swimlaneModel->getById($swimlane_id); + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getSwimlaneById', $swimlane['project_id']); + return $swimlane; } public function getSwimlaneByName($project_id, $name) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getSwimlaneByName', $project_id); return $this->swimlaneModel->getByName($project_id, $name); } @@ -39,11 +44,13 @@ class SwimlaneApi extends Base public function getDefaultSwimlane($project_id) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getDefaultSwimlane', $project_id); return $this->swimlaneModel->getDefault($project_id); } public function addSwimlane($project_id, $name, $description = '') { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'addSwimlane', $project_id); return $this->swimlaneModel->create(array('project_id' => $project_id, 'name' => $name, 'description' => $description)); } @@ -60,21 +67,25 @@ class SwimlaneApi extends Base public function removeSwimlane($project_id, $swimlane_id) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeSwimlane', $project_id); return $this->swimlaneModel->remove($project_id, $swimlane_id); } public function disableSwimlane($project_id, $swimlane_id) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'disableSwimlane', $project_id); return $this->swimlaneModel->disable($project_id, $swimlane_id); } public function enableSwimlane($project_id, $swimlane_id) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'enableSwimlane', $project_id); return $this->swimlaneModel->enable($project_id, $swimlane_id); } public function changeSwimlanePosition($project_id, $swimlane_id, $position) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'changeSwimlanePosition', $project_id); return $this->swimlaneModel->changePosition($project_id, $swimlane_id, $position); } } diff --git a/app/Api/Procedure/TaskExternalLinkProcedure.php b/app/Api/Procedure/TaskExternalLinkProcedure.php new file mode 100644 index 00000000..05ec6906 --- /dev/null +++ b/app/Api/Procedure/TaskExternalLinkProcedure.php @@ -0,0 +1,106 @@ +<?php + +namespace Kanboard\Api\Procedure; + +use Kanboard\Api\Authorization\TaskAuthorization; +use Kanboard\Core\ExternalLink\ExternalLinkManager; +use Kanboard\Core\ExternalLink\ExternalLinkProviderNotFound; + +/** + * Task External Link API controller + * + * @package Kanboard\Api\Procedure + * @author Frederic Guillot + */ +class TaskExternalLinkProcedure extends BaseProcedure +{ + public function getExternalTaskLinkTypes() + { + return $this->externalLinkManager->getTypes(); + } + + public function getExternalTaskLinkProviderDependencies($providerName) + { + try { + return $this->externalLinkManager->getProvider($providerName)->getDependencies(); + } catch (ExternalLinkProviderNotFound $e) { + $this->logger->error(__METHOD__.': '.$e->getMessage()); + return false; + } + } + + public function getExternalTaskLinkById($task_id, $link_id) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getExternalTaskLink', $task_id); + return $this->taskExternalLinkModel->getById($link_id); + } + + public function getAllExternalTaskLinks($task_id) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getExternalTaskLinks', $task_id); + return $this->taskExternalLinkModel->getAll($task_id); + } + + public function createExternalTaskLink($task_id, $url, $dependency, $type = ExternalLinkManager::TYPE_AUTO, $title = '') + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'createExternalTaskLink', $task_id); + + try { + $provider = $this->externalLinkManager + ->setUserInputText($url) + ->setUserInputType($type) + ->find(); + + $link = $provider->getLink(); + + $values = array( + 'task_id' => $task_id, + 'title' => $title ?: $link->getTitle(), + 'url' => $link->getUrl(), + 'link_type' => $provider->getType(), + 'dependency' => $dependency, + ); + + list($valid, $errors) = $this->externalLinkValidator->validateCreation($values); + + if (! $valid) { + $this->logger->error(__METHOD__.': '.var_export($errors)); + return false; + } + + return $this->taskExternalLinkModel->create($values); + } catch (ExternalLinkProviderNotFound $e) { + $this->logger->error(__METHOD__.': '.$e->getMessage()); + } + + return false; + } + + public function updateExternalTaskLink($task_id, $link_id, $title = null, $url = null, $dependency = null) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateExternalTaskLink', $task_id); + + $link = $this->taskExternalLinkModel->getById($link_id); + $values = $this->filterValues(array( + 'title' => $title, + 'url' => $url, + 'dependency' => $dependency, + )); + + $values = array_merge($link, $values); + list($valid, $errors) = $this->externalLinkValidator->validateModification($values); + + if (! $valid) { + $this->logger->error(__METHOD__.': '.var_export($errors)); + return false; + } + + return $this->taskExternalLinkModel->update($values); + } + + public function removeExternalTaskLink($task_id, $link_id) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeExternalTaskLink', $task_id); + return $this->taskExternalLinkModel->remove($link_id); + } +} diff --git a/app/Api/FileApi.php b/app/Api/Procedure/TaskFileProcedure.php index 1ed3aeb9..bd006578 100644 --- a/app/Api/FileApi.php +++ b/app/Api/Procedure/TaskFileProcedure.php @@ -1,29 +1,36 @@ <?php -namespace Kanboard\Api; +namespace Kanboard\Api\Procedure; +use Kanboard\Api\Authorization\ProjectAuthorization; +use Kanboard\Api\Authorization\TaskAuthorization; +use Kanboard\Api\Authorization\TaskFileAuthorization; use Kanboard\Core\ObjectStorage\ObjectStorageException; /** - * File API controller + * Task File API controller * - * @package Kanboard\Api + * @package Kanboard\Api\Procedure * @author Frederic Guillot */ -class FileApi extends BaseApi +class TaskFileProcedure extends BaseProcedure { public function getTaskFile($file_id) { + TaskFileAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTaskFile', $file_id); return $this->taskFileModel->getById($file_id); } public function getAllTaskFiles($task_id) { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllTaskFiles', $task_id); return $this->taskFileModel->getAll($task_id); } public function downloadTaskFile($file_id) { + TaskFileAuthorization::getInstance($this->container)->check($this->getClassName(), 'downloadTaskFile', $file_id); + try { $file = $this->taskFileModel->getById($file_id); @@ -33,59 +40,31 @@ class FileApi extends BaseApi } catch (ObjectStorageException $e) { $this->logger->error($e->getMessage()); } - + return ''; } public function createTaskFile($project_id, $task_id, $filename, $blob) { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createTaskFile', $project_id); + try { return $this->taskFileModel->uploadContent($task_id, $filename, $blob); } catch (ObjectStorageException $e) { - $this->logger->error($e->getMessage()); + $this->logger->error(__METHOD__.': '.$e->getMessage()); return false; } } public function removeTaskFile($file_id) { + TaskFileAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeTaskFile', $file_id); return $this->taskFileModel->remove($file_id); } public function removeAllTaskFiles($task_id) { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeAllTaskFiles', $task_id); return $this->taskFileModel->removeAll($task_id); } - - // Deprecated procedures - - public function getFile($file_id) - { - return $this->getTaskFile($file_id); - } - - public function getAllFiles($task_id) - { - return $this->getAllTaskFiles($task_id); - } - - public function downloadFile($file_id) - { - return $this->downloadTaskFile($file_id); - } - - public function createFile($project_id, $task_id, $filename, $blob) - { - return $this->createTaskFile($project_id, $task_id, $filename, $blob); - } - - public function removeFile($file_id) - { - return $this->removeTaskFile($file_id); - } - - public function removeAllFiles($task_id) - { - return $this->removeAllTaskFiles($task_id); - } } diff --git a/app/Api/TaskLinkApi.php b/app/Api/Procedure/TaskLinkProcedure.php index bb809133..375266fb 100644 --- a/app/Api/TaskLinkApi.php +++ b/app/Api/Procedure/TaskLinkProcedure.php @@ -1,16 +1,17 @@ <?php -namespace Kanboard\Api; +namespace Kanboard\Api\Procedure; -use Kanboard\Core\Base; +use Kanboard\Api\Authorization\TaskAuthorization; +use Kanboard\Api\Authorization\TaskLinkAuthorization; /** * TaskLink API controller * - * @package Kanboard\Api + * @package Kanboard\Api\Procedure * @author Frederic Guillot */ -class TaskLinkApi extends Base +class TaskLinkProcedure extends BaseProcedure { /** * Get a task link @@ -21,6 +22,7 @@ class TaskLinkApi extends Base */ public function getTaskLinkById($task_link_id) { + TaskLinkAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTaskLinkById', $task_link_id); return $this->taskLinkModel->getById($task_link_id); } @@ -33,6 +35,7 @@ class TaskLinkApi extends Base */ public function getAllTaskLinks($task_id) { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllTaskLinks', $task_id); return $this->taskLinkModel->getAll($task_id); } @@ -47,6 +50,7 @@ class TaskLinkApi extends Base */ public function createTaskLink($task_id, $opposite_task_id, $link_id) { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'createTaskLink', $task_id); return $this->taskLinkModel->create($task_id, $opposite_task_id, $link_id); } @@ -62,6 +66,7 @@ class TaskLinkApi extends Base */ public function updateTaskLink($task_link_id, $task_id, $opposite_task_id, $link_id) { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateTaskLink', $task_id); return $this->taskLinkModel->update($task_link_id, $task_id, $opposite_task_id, $link_id); } @@ -74,6 +79,7 @@ class TaskLinkApi extends Base */ public function removeTaskLink($task_link_id) { + TaskLinkAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeTaskLink', $task_link_id); return $this->taskLinkModel->remove($task_link_id); } } diff --git a/app/Api/Procedure/TaskMetadataProcedure.php b/app/Api/Procedure/TaskMetadataProcedure.php new file mode 100644 index 00000000..169482f5 --- /dev/null +++ b/app/Api/Procedure/TaskMetadataProcedure.php @@ -0,0 +1,38 @@ +<?php + +namespace Kanboard\Api\Procedure; + +use Kanboard\Api\Authorization\TaskAuthorization; + +/** + * Class TaskMetadataProcedure + * + * @package Kanboard\Api\Procedure + * @author Frederic Guillot + */ +class TaskMetadataProcedure extends BaseProcedure +{ + public function getTaskMetadata($task_id) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTask', $task_id); + return $this->taskMetadataModel->getAll($task_id); + } + + public function getTaskMetadataByName($task_id, $name) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTask', $task_id); + return $this->taskMetadataModel->get($task_id, $name); + } + + public function saveTaskMetadata($task_id, array $values) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateTask', $task_id); + return $this->taskMetadataModel->save($task_id, $values); + } + + public function removeTaskMetadata($task_id, $name) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateTask', $task_id); + return $this->taskMetadataModel->remove($task_id, $name); + } +} diff --git a/app/Api/TaskApi.php b/app/Api/Procedure/TaskProcedure.php index ddb3ac54..ee9242d1 100644 --- a/app/Api/TaskApi.php +++ b/app/Api/Procedure/TaskProcedure.php @@ -1,39 +1,41 @@ <?php -namespace Kanboard\Api; +namespace Kanboard\Api\Procedure; +use Kanboard\Api\Authorization\ProjectAuthorization; +use Kanboard\Api\Authorization\TaskAuthorization; use Kanboard\Filter\TaskProjectFilter; use Kanboard\Model\TaskModel; /** * Task API controller * - * @package Kanboard\Api + * @package Kanboard\Api\Procedure * @author Frederic Guillot */ -class TaskApi extends BaseApi +class TaskProcedure extends BaseProcedure { public function searchTasks($project_id, $query) { - $this->checkProjectPermission($project_id); + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'searchTasks', $project_id); return $this->taskLexer->build($query)->withFilter(new TaskProjectFilter($project_id))->toArray(); } public function getTask($task_id) { - $this->checkTaskPermission($task_id); + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTask', $task_id); return $this->formatTask($this->taskFinderModel->getById($task_id)); } public function getTaskByReference($project_id, $reference) { - $this->checkProjectPermission($project_id); + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTaskByReference', $project_id); return $this->formatTask($this->taskFinderModel->getByReference($project_id, $reference)); } public function getAllTasks($project_id, $status_id = TaskModel::STATUS_OPEN) { - $this->checkProjectPermission($project_id); + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllTasks', $project_id); return $this->formatTasks($this->taskFinderModel->getAll($project_id, $status_id)); } @@ -44,41 +46,44 @@ class TaskApi extends BaseApi public function getOverdueTasksByProject($project_id) { - $this->checkProjectPermission($project_id); + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getOverdueTasksByProject', $project_id); return $this->taskFinderModel->getOverdueTasksByProject($project_id); } public function openTask($task_id) { - $this->checkTaskPermission($task_id); + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'openTask', $task_id); return $this->taskStatusModel->open($task_id); } public function closeTask($task_id) { - $this->checkTaskPermission($task_id); + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'closeTask', $task_id); return $this->taskStatusModel->close($task_id); } public function removeTask($task_id) { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeTask', $task_id); return $this->taskModel->remove($task_id); } public function moveTaskPosition($project_id, $task_id, $column_id, $position, $swimlane_id = 0) { - $this->checkProjectPermission($project_id); + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'moveTaskPosition', $project_id); return $this->taskPositionModel->movePosition($project_id, $task_id, $column_id, $position, $swimlane_id); } public function moveTaskToProject($task_id, $project_id, $swimlane_id = null, $column_id = null, $category_id = null, $owner_id = null) { - return $this->taskDuplicationModel->moveToProject($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id); + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'moveTaskToProject', $project_id); + return $this->taskProjectMoveModel->moveToProject($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id); } public function duplicateTaskToProject($task_id, $project_id, $swimlane_id = null, $column_id = null, $category_id = null, $owner_id = null) { - return $this->taskDuplicationModel->duplicateToProject($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id); + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'duplicateTaskToProject', $project_id); + return $this->taskProjectDuplicationModel->duplicateToProject($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id); } public function createTask($title, $project_id, $color_id = '', $column_id = 0, $owner_id = 0, $creator_id = 0, @@ -86,7 +91,7 @@ class TaskApi extends BaseApi $recurrence_status = 0, $recurrence_trigger = 0, $recurrence_factor = 0, $recurrence_timeframe = 0, $recurrence_basedate = 0, $reference = '') { - $this->checkProjectPermission($project_id); + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createTask', $project_id); if ($owner_id !== 0 && ! $this->projectPermissionModel->isAssignable($project_id, $owner_id)) { return false; @@ -127,8 +132,7 @@ class TaskApi extends BaseApi $recurrence_status = null, $recurrence_trigger = null, $recurrence_factor = null, $recurrence_timeframe = null, $recurrence_basedate = null, $reference = null) { - $this->checkTaskPermission($id); - + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateTask', $id); $project_id = $this->taskFinderModel->getProjectId($id); if ($project_id === 0) { @@ -139,7 +143,7 @@ class TaskApi extends BaseApi return false; } - $values = array( + $values = $this->filterValues(array( 'id' => $id, 'title' => $title, 'color_id' => $color_id, @@ -155,13 +159,7 @@ class TaskApi extends BaseApi 'recurrence_basedate' => $recurrence_basedate, 'reference' => $reference, 'priority' => $priority, - ); - - foreach ($values as $key => $value) { - if (is_null($value)) { - unset($values[$key]); - } - } + )); list($valid) = $this->taskValidator->validateApiModification($values); return $valid && $this->taskModificationModel->update($values); diff --git a/app/Api/UserApi.php b/app/Api/Procedure/UserProcedure.php index 88d75527..145f85bf 100644 --- a/app/Api/UserApi.php +++ b/app/Api/Procedure/UserProcedure.php @@ -1,8 +1,7 @@ <?php -namespace Kanboard\Api; +namespace Kanboard\Api\Procedure; -use Kanboard\Core\Base; use LogicException; use Kanboard\Core\Security\Role; use Kanboard\Core\Ldap\Client as LdapClient; @@ -12,10 +11,10 @@ use Kanboard\Core\Ldap\User as LdapUser; /** * User API controller * - * @package Kanboard\Api + * @package Kanboard\Api\Procedure * @author Frederic Guillot */ -class UserApi extends Base +class UserProcedure extends BaseProcedure { public function getUser($user_id) { @@ -118,19 +117,13 @@ class UserApi extends Base public function updateUser($id, $username = null, $name = null, $email = null, $role = null) { - $values = array( + $values = $this->filterValues(array( 'id' => $id, 'username' => $username, 'name' => $name, 'email' => $email, 'role' => $role, - ); - - foreach ($values as $key => $value) { - if (is_null($value)) { - unset($values[$key]); - } - } + )); list($valid, ) = $this->userValidator->validateApiModification($values); return $valid && $this->userModel->update($values); diff --git a/app/Api/ProjectApi.php b/app/Api/ProjectApi.php deleted file mode 100644 index 29a9cd79..00000000 --- a/app/Api/ProjectApi.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -namespace Kanboard\Api; - -/** - * Project API controller - * - * @package Kanboard\Api - * @author Frederic Guillot - */ -class ProjectApi extends BaseApi -{ - public function getProjectById($project_id) - { - $this->checkProjectPermission($project_id); - return $this->formatProject($this->projectModel->getById($project_id)); - } - - public function getProjectByName($name) - { - return $this->formatProject($this->projectModel->getByName($name)); - } - - public function getAllProjects() - { - return $this->formatProjects($this->projectModel->getAll()); - } - - public function removeProject($project_id) - { - return $this->projectModel->remove($project_id); - } - - public function enableProject($project_id) - { - return $this->projectModel->enable($project_id); - } - - public function disableProject($project_id) - { - return $this->projectModel->disable($project_id); - } - - public function enableProjectPublicAccess($project_id) - { - return $this->projectModel->enablePublicAccess($project_id); - } - - public function disableProjectPublicAccess($project_id) - { - return $this->projectModel->disablePublicAccess($project_id); - } - - public function getProjectActivities(array $project_ids) - { - return $this->helper->projectActivity->getProjectsEvents($project_ids); - } - - public function getProjectActivity($project_id) - { - $this->checkProjectPermission($project_id); - return $this->helper->projectActivity->getProjectEvents($project_id); - } - - public function createProject($name, $description = null) - { - $values = array( - 'name' => $name, - 'description' => $description - ); - - list($valid, ) = $this->projectValidator->validateCreation($values); - return $valid ? $this->projectModel->create($values) : false; - } - - public function updateProject($id, $name, $description = null) - { - $values = array( - 'id' => $id, - 'name' => $name, - 'description' => $description - ); - - list($valid, ) = $this->projectValidator->validateModification($values); - return $valid && $this->projectModel->update($values); - } -} diff --git a/app/Api/SubtaskTimeTrackingApi.php b/app/Api/SubtaskTimeTrackingApi.php deleted file mode 100644 index 0e700b31..00000000 --- a/app/Api/SubtaskTimeTrackingApi.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -namespace Kanboard\Api; - -use Kanboard\Core\Base; - -/** - * Subtask Time Tracking API controller - * - * @package api - * @author Nikolaos Georgakis - */ -class SubtaskTimeTrackingApi extends Base -{ - public function hasTimer($subtask_id,$user_id) - { - return $this->subtaskTimeTrackingModel->hasTimer($subtask_id,$user_id); - } - - public function logStartTime($subtask_id,$user_id) - { - return $this->subtaskTimeTrackingModel->logStartTime($subtask_id,$user_id); - } - - public function logEndTime($subtask_id,$user_id) - { - return $this->subtaskTimeTrackingModel->logEndTime($subtask_id,$user_id); - } - - public function getTimeSpent($subtask_id,$user_id) - { - return $this->subtaskTimeTrackingModel->getTimeSpent($subtask_id,$user_id); - } -} |