Added application and project roles validation for API procedure calls

This commit is contained in:
Frederic Guillot
2016-06-26 10:25:13 -04:00
parent 922e0fb6de
commit 4a230d331e
79 changed files with 1772 additions and 761 deletions

View File

@@ -0,0 +1,91 @@
<?php
namespace Kanboard\Api\Procedure;
use Kanboard\Api\Authorization\ActionAuthorization;
use Kanboard\Api\Authorization\ProjectAuthorization;
/**
* Action API controller
*
* @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
class ActionProcedure extends BaseProcedure
{
public function getAvailableActions()
{
return $this->actionManager->getAvailableActions();
}
public function getAvailableActionEvents()
{
return $this->eventManager->getAll();
}
public function getCompatibleActionEvents($action_name)
{
return $this->actionManager->getCompatibleEvents($action_name);
}
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,
'action_name' => $action_name,
'params' => $params,
);
list($valid, ) = $this->actionValidator->validateCreation($values);
if (! $valid) {
return false;
}
// Check if the action exists
$actions = $this->actionManager->getAvailableActions();
if (! isset($actions[$action_name])) {
return false;
}
// Check the event
$action = $this->actionManager->getAction($action_name);
if (! in_array($event_name, $action->getEvents())) {
return false;
}
$required_params = $action->getActionRequiredParameters();
// Check missing parameters
foreach ($required_params as $param => $value) {
if (! isset($params[$param])) {
return false;
}
}
// Check extra parameters
foreach ($params as $param => $value) {
if (! isset($required_params[$param])) {
return false;
}
}
return $this->actionModel->create($values);
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace Kanboard\Api\Procedure;
/**
* App API controller
*
* @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
class AppProcedure extends BaseProcedure
{
public function getTimezone()
{
return $this->timezoneModel->getCurrentTimezone();
}
public function getVersion()
{
return APP_VERSION;
}
public function getDefaultTaskColor()
{
return $this->colorModel->getDefaultColor();
}
public function getDefaultTaskColors()
{
return $this->colorModel->getDefaultColors();
}
public function getColorList()
{
return $this->colorModel->getList();
}
public function getApplicationRoles()
{
return $this->role->getApplicationRoles();
}
public function getProjectRoles()
{
return $this->role->getProjectRoles();
}
}

View File

@@ -0,0 +1,86 @@
<?php
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\Procedure
* @author Frederic Guillot
*/
abstract class BaseProcedure extends Base
{
public function beforeProcedure($procedure)
{
ProcedureAuthorization::getInstance($this->container)->check($procedure);
UserAuthorization::getInstance($this->container)->check($this->getClassName(), $procedure);
}
protected function formatTask($task)
{
if (! empty($task)) {
$task['url'] = $this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), '', true);
$task['color'] = $this->colorModel->getColorProperties($task['color_id']);
}
return $task;
}
protected function formatTasks($tasks)
{
if (! empty($tasks)) {
foreach ($tasks as &$task) {
$task = $this->formatTask($task);
}
}
return $tasks;
}
protected function formatProject($project)
{
if (! empty($project)) {
$project['url'] = array(
'board' => $this->helper->url->to('BoardViewController', 'show', array('project_id' => $project['id']), '', true),
'calendar' => $this->helper->url->to('CalendarController', 'show', array('project_id' => $project['id']), '', true),
'list' => $this->helper->url->to('TaskListController', 'show', array('project_id' => $project['id']), '', true),
);
}
return $project;
}
protected function formatProjects($projects)
{
if (! empty($projects)) {
foreach ($projects as &$project) {
$project = $this->formatProject($project);
}
}
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();
}
}

View File

@@ -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();
}
}

View File

@@ -0,0 +1,59 @@
<?php
namespace Kanboard\Api\Procedure;
use Kanboard\Api\Authorization\CategoryAuthorization;
use Kanboard\Api\Authorization\ProjectAuthorization;
/**
* Category API controller
*
* @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
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,
);
list($valid, ) = $this->categoryValidator->validateCreation($values);
return $valid ? $this->categoryModel->create($values) : false;
}
public function updateCategory($id, $name)
{
CategoryAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateCategory', $id);
$values = array(
'id' => $id,
'name' => $name,
);
list($valid, ) = $this->categoryValidator->validateModification($values);
return $valid && $this->categoryModel->update($values);
}
}

View File

@@ -0,0 +1,51 @@
<?php
namespace Kanboard\Api\Procedure;
use Kanboard\Api\Authorization\ColumnAuthorization;
use Kanboard\Api\Authorization\ProjectAuthorization;
/**
* Column API controller
*
* @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
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);
}
}

View File

@@ -0,0 +1,62 @@
<?php
namespace Kanboard\Api\Procedure;
use Kanboard\Api\Authorization\CommentAuthorization;
use Kanboard\Api\Authorization\TaskAuthorization;
/**
* Comment API controller
*
* @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
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,
'comment' => $content,
'reference' => $reference,
);
list($valid, ) = $this->commentValidator->validateCreation($values);
return $valid ? $this->commentModel->create($values) : false;
}
public function updateComment($id, $content)
{
CommentAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateComment', $id);
$values = array(
'id' => $id,
'comment' => $content,
);
list($valid, ) = $this->commentValidator->validateModification($values);
return $valid && $this->commentModel->update($values);
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace Kanboard\Api\Procedure;
/**
* Group Member API controller
*
* @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
class GroupMemberProcedure extends BaseProcedure
{
public function getMemberGroups($user_id)
{
return $this->groupMemberModel->getGroups($user_id);
}
public function getGroupMembers($group_id)
{
return $this->groupMemberModel->getMembers($group_id);
}
public function addGroupMember($group_id, $user_id)
{
return $this->groupMemberModel->addUser($group_id, $user_id);
}
public function removeGroupMember($group_id, $user_id)
{
return $this->groupMemberModel->removeUser($group_id, $user_id);
}
public function isGroupMember($group_id, $user_id)
{
return $this->groupMemberModel->isMember($group_id, $user_id);
}
}

View File

@@ -0,0 +1,49 @@
<?php
namespace Kanboard\Api\Procedure;
/**
* Group API controller
*
* @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
class GroupProcedure extends BaseProcedure
{
public function createGroup($name, $external_id = '')
{
return $this->groupModel->create($name, $external_id);
}
public function updateGroup($group_id, $name = null, $external_id = null)
{
$values = array(
'id' => $group_id,
'name' => $name,
'external_id' => $external_id,
);
foreach ($values as $key => $value) {
if (is_null($value)) {
unset($values[$key]);
}
}
return $this->groupModel->update($values);
}
public function removeGroup($group_id)
{
return $this->groupModel->remove($group_id);
}
public function getGroup($group_id)
{
return $this->groupModel->getById($group_id);
}
public function getAllGroups()
{
return $this->groupModel->getAll();
}
}

View File

@@ -0,0 +1,111 @@
<?php
namespace Kanboard\Api\Procedure;
/**
* Link API controller
*
* @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
class LinkProcedure extends BaseProcedure
{
/**
* Get a link by id
*
* @access public
* @param integer $link_id Link id
* @return array
*/
public function getLinkById($link_id)
{
return $this->linkModel->getById($link_id);
}
/**
* Get a link by name
*
* @access public
* @param string $label
* @return array
*/
public function getLinkByLabel($label)
{
return $this->linkModel->getByLabel($label);
}
/**
* Get the opposite link id
*
* @access public
* @param integer $link_id Link id
* @return integer
*/
public function getOppositeLinkId($link_id)
{
return $this->linkModel->getOppositeLinkId($link_id);
}
/**
* Get all links
*
* @access public
* @return array
*/
public function getAllLinks()
{
return $this->linkModel->getAll();
}
/**
* Create a new link label
*
* @access public
* @param string $label
* @param string $opposite_label
* @return boolean|integer
*/
public function createLink($label, $opposite_label = '')
{
$values = array(
'label' => $label,
'opposite_label' => $opposite_label,
);
list($valid, ) = $this->linkValidator->validateCreation($values);
return $valid ? $this->linkModel->create($label, $opposite_label) : false;
}
/**
* Update a link
*
* @access public
* @param integer $link_id
* @param integer $opposite_link_id
* @param string $label
* @return boolean
*/
public function updateLink($link_id, $opposite_link_id, $label)
{
$values = array(
'id' => $link_id,
'opposite_id' => $opposite_link_id,
'label' => $label,
);
list($valid, ) = $this->linkValidator->validateModification($values);
return $valid && $this->linkModel->update($values);
}
/**
* Remove a link a the relation to its opposite
*
* @access public
* @param integer $link_id
* @return boolean
*/
public function removeLink($link_id)
{
return $this->linkModel->remove($link_id);
}
}

View File

@@ -0,0 +1,72 @@
<?php
namespace Kanboard\Api\Procedure;
use Kanboard\Model\SubtaskModel;
/**
* Me API controller
*
* @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
class MeProcedure extends BaseProcedure
{
public function getMe()
{
return $this->sessionStorage->user;
}
public function getMyDashboard()
{
$user_id = $this->userSession->getId();
$projects = $this->projectModel->getQueryColumnStats($this->projectPermissionModel->getActiveProjectIds($user_id))->findAll();
$tasks = $this->taskFinderModel->getUserQuery($user_id)->findAll();
return array(
'projects' => $this->formatProjects($projects),
'tasks' => $this->formatTasks($tasks),
'subtasks' => $this->subtaskModel->getUserQuery($user_id, array(SubtaskModel::STATUS_TODO, SubtaskModel::STATUS_INPROGRESS))->findAll(),
);
}
public function getMyActivityStream()
{
$project_ids = $this->projectPermissionModel->getActiveProjectIds($this->userSession->getId());
return $this->helper->projectActivity->getProjectsEvents($project_ids, 100);
}
public function createMyPrivateProject($name, $description = null)
{
if ($this->configModel->get('disable_private_project', 0) == 1) {
return false;
}
$values = array(
'name' => $name,
'description' => $description,
'is_private' => 1,
);
list($valid, ) = $this->projectValidator->validateCreation($values);
return $valid ? $this->projectModel->create($values, $this->userSession->getId(), true) : false;
}
public function getMyProjectsList()
{
return $this->projectUserRoleModel->getProjectsByUser($this->userSession->getId());
}
public function getMyOverdueTasks()
{
return $this->taskFinderModel->getOverdueTasksByUser($this->userSession->getId());
}
public function getMyProjects()
{
$project_ids = $this->projectPermissionModel->getActiveProjectIds($this->userSession->getId());
$projects = $this->projectModel->getAllByIds($project_ids);
return $this->formatProjects($projects);
}
}

View File

@@ -0,0 +1,69 @@
<?php
namespace Kanboard\Api\Procedure;
use Kanboard\Api\Authorization\ProjectAuthorization;
use Kanboard\Core\Security\Role;
/**
* Project Permission API controller
*
* @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
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);
}
public function getProjectUserRole($project_id, $user_id)
{
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectUserRole', $project_id);
return $this->projectUserRoleModel->getUserRole($project_id, $user_id);
}
}

View File

@@ -0,0 +1,106 @@
<?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 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 = 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, $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);
}
}

View File

@@ -0,0 +1,74 @@
<?php
namespace Kanboard\Api\Procedure;
use Kanboard\Api\Authorization\SubtaskAuthorization;
use Kanboard\Api\Authorization\TaskAuthorization;
/**
* Subtask API controller
*
* @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
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,
'user_id' => $user_id,
'time_estimated' => $time_estimated,
'time_spent' => $time_spent,
'status' => $status,
);
list($valid, ) = $this->subtaskValidator->validateCreation($values);
return $valid ? $this->subtaskModel->create($values) : false;
}
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,
'title' => $title,
'user_id' => $user_id,
'time_estimated' => $time_estimated,
'time_spent' => $time_spent,
'status' => $status,
);
foreach ($values as $key => $value) {
if (is_null($value)) {
unset($values[$key]);
}
}
list($valid, ) = $this->subtaskValidator->validateApiModification($values);
return $valid && $this->subtaskModel->update($values);
}
}

View File

@@ -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 logSubtaskStartTime($subtask_id, $user_id)
{
SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'logSubtaskStartTime', $subtask_id);
return $this->subtaskTimeTrackingModel->logStartTime($subtask_id, $user_id);
}
public function logSubtaskEndTime($subtask_id,$user_id)
{
SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'logSubtaskEndTime', $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);
}
}

View File

@@ -0,0 +1,91 @@
<?php
namespace Kanboard\Api\Procedure;
use Kanboard\Api\Authorization\ProjectAuthorization;
/**
* Swimlane API controller
*
* @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
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)
{
$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);
}
public function getSwimlane($swimlane_id)
{
return $this->swimlaneModel->getById($swimlane_id);
}
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));
}
public function updateSwimlane($swimlane_id, $name, $description = null)
{
$values = array('id' => $swimlane_id, 'name' => $name);
if (!is_null($description)) {
$values['description'] = $description;
}
return $this->swimlaneModel->update($values);
}
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);
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace Kanboard\Api\Procedure;
use Kanboard\Api\Authorization\ProjectAuthorization;
use Kanboard\Api\Authorization\TaskAuthorization;
use Kanboard\Api\Authorization\TaskFileAuthorization;
use Kanboard\Core\ObjectStorage\ObjectStorageException;
/**
* Task File API controller
*
* @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
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);
if (! empty($file)) {
return base64_encode($this->objectStorage->get($file['path']));
}
} 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());
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);
}
}

View File

@@ -0,0 +1,85 @@
<?php
namespace Kanboard\Api\Procedure;
use Kanboard\Api\Authorization\TaskAuthorization;
use Kanboard\Api\Authorization\TaskLinkAuthorization;
/**
* TaskLink API controller
*
* @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
class TaskLinkProcedure extends BaseProcedure
{
/**
* Get a task link
*
* @access public
* @param integer $task_link_id Task link id
* @return array
*/
public function getTaskLinkById($task_link_id)
{
TaskLinkAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTaskLinkById', $task_link_id);
return $this->taskLinkModel->getById($task_link_id);
}
/**
* Get all links attached to a task
*
* @access public
* @param integer $task_id Task id
* @return array
*/
public function getAllTaskLinks($task_id)
{
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllTaskLinks', $task_id);
return $this->taskLinkModel->getAll($task_id);
}
/**
* Create a new link
*
* @access public
* @param integer $task_id Task id
* @param integer $opposite_task_id Opposite task id
* @param integer $link_id Link id
* @return integer Task link id
*/
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);
}
/**
* Update a task link
*
* @access public
* @param integer $task_link_id Task link id
* @param integer $task_id Task id
* @param integer $opposite_task_id Opposite task id
* @param integer $link_id Link id
* @return boolean
*/
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);
}
/**
* Remove a link between two tasks
*
* @access public
* @param integer $task_link_id
* @return boolean
*/
public function removeTaskLink($task_link_id)
{
TaskLinkAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeTaskLink', $task_link_id);
return $this->taskLinkModel->remove($task_link_id);
}
}

View File

@@ -0,0 +1,167 @@
<?php
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\Procedure
* @author Frederic Guillot
*/
class TaskProcedure extends BaseProcedure
{
public function searchTasks($project_id, $query)
{
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)
{
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTask', $task_id);
return $this->formatTask($this->taskFinderModel->getById($task_id));
}
public function getTaskByReference($project_id, $reference)
{
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)
{
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllTasks', $project_id);
return $this->formatTasks($this->taskFinderModel->getAll($project_id, $status_id));
}
public function getOverdueTasks()
{
return $this->taskFinderModel->getOverdueTasks();
}
public function getOverdueTasksByProject($project_id)
{
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getOverdueTasksByProject', $project_id);
return $this->taskFinderModel->getOverdueTasksByProject($project_id);
}
public function openTask($task_id)
{
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'openTask', $task_id);
return $this->taskStatusModel->open($task_id);
}
public function closeTask($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)
{
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)
{
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'moveTaskToProject', $project_id);
return $this->taskDuplicationModel->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)
{
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'duplicateTaskToProject', $project_id);
return $this->taskDuplicationModel->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,
$date_due = '', $description = '', $category_id = 0, $score = 0, $swimlane_id = 0, $priority = 0,
$recurrence_status = 0, $recurrence_trigger = 0, $recurrence_factor = 0, $recurrence_timeframe = 0,
$recurrence_basedate = 0, $reference = '')
{
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createTask', $project_id);
if ($owner_id !== 0 && ! $this->projectPermissionModel->isAssignable($project_id, $owner_id)) {
return false;
}
if ($this->userSession->isLogged()) {
$creator_id = $this->userSession->getId();
}
$values = array(
'title' => $title,
'project_id' => $project_id,
'color_id' => $color_id,
'column_id' => $column_id,
'owner_id' => $owner_id,
'creator_id' => $creator_id,
'date_due' => $date_due,
'description' => $description,
'category_id' => $category_id,
'score' => $score,
'swimlane_id' => $swimlane_id,
'recurrence_status' => $recurrence_status,
'recurrence_trigger' => $recurrence_trigger,
'recurrence_factor' => $recurrence_factor,
'recurrence_timeframe' => $recurrence_timeframe,
'recurrence_basedate' => $recurrence_basedate,
'reference' => $reference,
'priority' => $priority,
);
list($valid, ) = $this->taskValidator->validateCreation($values);
return $valid ? $this->taskCreationModel->create($values) : false;
}
public function updateTask($id, $title = null, $color_id = null, $owner_id = null,
$date_due = null, $description = null, $category_id = null, $score = null, $priority = null,
$recurrence_status = null, $recurrence_trigger = null, $recurrence_factor = null,
$recurrence_timeframe = null, $recurrence_basedate = null, $reference = null)
{
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateTask', $id);
$project_id = $this->taskFinderModel->getProjectId($id);
if ($project_id === 0) {
return false;
}
if ($owner_id !== null && $owner_id != 0 && ! $this->projectPermissionModel->isAssignable($project_id, $owner_id)) {
return false;
}
$values = $this->filterValues(array(
'id' => $id,
'title' => $title,
'color_id' => $color_id,
'owner_id' => $owner_id,
'date_due' => $date_due,
'description' => $description,
'category_id' => $category_id,
'score' => $score,
'recurrence_status' => $recurrence_status,
'recurrence_trigger' => $recurrence_trigger,
'recurrence_factor' => $recurrence_factor,
'recurrence_timeframe' => $recurrence_timeframe,
'recurrence_basedate' => $recurrence_basedate,
'reference' => $reference,
'priority' => $priority,
));
list($valid) = $this->taskValidator->validateApiModification($values);
return $valid && $this->taskModificationModel->update($values);
}
}

View File

@@ -0,0 +1,131 @@
<?php
namespace Kanboard\Api\Procedure;
use LogicException;
use Kanboard\Core\Security\Role;
use Kanboard\Core\Ldap\Client as LdapClient;
use Kanboard\Core\Ldap\ClientException as LdapException;
use Kanboard\Core\Ldap\User as LdapUser;
/**
* User API controller
*
* @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
class UserProcedure extends BaseProcedure
{
public function getUser($user_id)
{
return $this->userModel->getById($user_id);
}
public function getUserByName($username)
{
return $this->userModel->getByUsername($username);
}
public function getAllUsers()
{
return $this->userModel->getAll();
}
public function removeUser($user_id)
{
return $this->userModel->remove($user_id);
}
public function disableUser($user_id)
{
return $this->userModel->disable($user_id);
}
public function enableUser($user_id)
{
return $this->userModel->enable($user_id);
}
public function isActiveUser($user_id)
{
return $this->userModel->isActive($user_id);
}
public function createUser($username, $password, $name = '', $email = '', $role = Role::APP_USER)
{
$values = array(
'username' => $username,
'password' => $password,
'confirmation' => $password,
'name' => $name,
'email' => $email,
'role' => $role,
);
list($valid, ) = $this->userValidator->validateCreation($values);
return $valid ? $this->userModel->create($values) : false;
}
/**
* Create LDAP user in the database
*
* Only "anonymous" and "proxy" LDAP authentication are supported by this method
*
* User information will be fetched from the LDAP server
*
* @access public
* @param string $username
* @return bool|int
*/
public function createLdapUser($username)
{
if (LDAP_BIND_TYPE === 'user') {
$this->logger->error('LDAP authentication "user" is not supported by this API call');
return false;
}
try {
$ldap = LdapClient::connect();
$ldap->setLogger($this->logger);
$user = LdapUser::getUser($ldap, $username);
if ($user === null) {
$this->logger->info('User not found in LDAP server');
return false;
}
if ($user->getUsername() === '') {
throw new LogicException('Username not found in LDAP profile, check the parameter LDAP_USER_ATTRIBUTE_USERNAME');
}
$values = array(
'username' => $user->getUsername(),
'name' => $user->getName(),
'email' => $user->getEmail(),
'role' => $user->getRole(),
'is_ldap_user' => 1,
);
return $this->userModel->create($values);
} catch (LdapException $e) {
$this->logger->error($e->getMessage());
return false;
}
}
public function updateUser($id, $username = null, $name = null, $email = null, $role = null)
{
$values = $this->filterValues(array(
'id' => $id,
'username' => $username,
'name' => $name,
'email' => $email,
'role' => $role,
));
list($valid, ) = $this->userValidator->validateApiModification($values);
return $valid && $this->userModel->update($values);
}
}