Add column restrictions to custom project roles
This commit is contained in:
parent
4bc83646b0
commit
3043163747
|
|
@ -0,0 +1,103 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ColumnMoveRestrictionController
|
||||||
|
*
|
||||||
|
* @package Kanboard\Controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class ColumnRestrictionController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Show form to create a new column restriction
|
||||||
|
*
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws AccessForbiddenException
|
||||||
|
*/
|
||||||
|
public function create(array $values = array(), array $errors = array())
|
||||||
|
{
|
||||||
|
$project = $this->getProject();
|
||||||
|
$role_id = $this->request->getIntegerParam('role_id');
|
||||||
|
$role = $this->projectRoleModel->getById($project['id'], $role_id);
|
||||||
|
|
||||||
|
$this->response->html($this->template->render('column_restriction/create', array(
|
||||||
|
'project' => $project,
|
||||||
|
'role' => $role,
|
||||||
|
'rules' => $this->columnRestrictionModel->getRules(),
|
||||||
|
'columns' => $this->columnModel->getList($project['id']),
|
||||||
|
'values' => $values + array('project_id' => $project['id'], 'role_id' => $role['role_id']),
|
||||||
|
'errors' => $errors,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save new column restriction
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$project = $this->getProject();
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
|
||||||
|
list($valid, $errors) = $this->columnRestrictionValidator->validateCreation($values);
|
||||||
|
|
||||||
|
if ($valid) {
|
||||||
|
$restriction_id = $this->columnRestrictionModel->create(
|
||||||
|
$project['id'],
|
||||||
|
$values['role_id'],
|
||||||
|
$values['column_id'],
|
||||||
|
$values['rule']
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($restriction_id !== false) {
|
||||||
|
$this->flash->success(t('The column restriction has been created successfully.'));
|
||||||
|
} else {
|
||||||
|
$this->flash->failure(t('Unable to create this column restriction.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->redirect($this->helper->url->to('ProjectRoleController', 'show', array('project_id' => $project['id'])));
|
||||||
|
} else {
|
||||||
|
$this->create($values, $errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirm suppression
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function confirm()
|
||||||
|
{
|
||||||
|
$project = $this->getProject();
|
||||||
|
$restriction_id = $this->request->getIntegerParam('restriction_id');
|
||||||
|
|
||||||
|
$this->response->html($this->helper->layout->project('column_restriction/remove', array(
|
||||||
|
'project' => $project,
|
||||||
|
'restriction' => $this->columnRestrictionModel->getById($project['id'], $restriction_id),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a restriction
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function remove()
|
||||||
|
{
|
||||||
|
$project = $this->getProject();
|
||||||
|
$this->checkCSRFParam();
|
||||||
|
$restriction_id = $this->request->getIntegerParam('restriction_id');
|
||||||
|
|
||||||
|
if ($this->columnRestrictionModel->remove($restriction_id)) {
|
||||||
|
$this->flash->success(t('Column restriction removed successfully.'));
|
||||||
|
} else {
|
||||||
|
$this->flash->failure(t('Unable to remove this restriction.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->redirect($this->helper->url->to('ProjectRoleController', 'show', array('project_id' => $project['id'])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -52,12 +52,16 @@ class TaskCreationController extends BaseController
|
||||||
|
|
||||||
list($valid, $errors) = $this->taskValidator->validateCreation($values);
|
list($valid, $errors) = $this->taskValidator->validateCreation($values);
|
||||||
|
|
||||||
if ($valid && ($task_id = $this->taskCreationModel->create($values))) {
|
if (! $valid) {
|
||||||
$this->flash->success(t('Task created successfully.'));
|
|
||||||
$this->afterSave($project, $values, $task_id);
|
|
||||||
} else {
|
|
||||||
$this->flash->failure(t('Unable to create your task.'));
|
$this->flash->failure(t('Unable to create your task.'));
|
||||||
$this->show($values, $errors);
|
$this->show($values, $errors);
|
||||||
|
} else if (! $this->helper->projectRole->canCreateTaskInColumn($project['id'], $values['column_id'])) {
|
||||||
|
$this->flash->failure(t('You cannot create tasks in this column.'));
|
||||||
|
$this->response->redirect($this->helper->url->to('BoardViewController', 'show', array('project_id' => $project['id'])), true);
|
||||||
|
} else {
|
||||||
|
$task_id = $this->taskCreationModel->create($values);
|
||||||
|
$this->flash->success(t('Task created successfully.'));
|
||||||
|
$this->afterSave($project, $values, $task_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
use Kanboard\Formatter\BoardFormatter;
|
use Kanboard\Formatter\BoardFormatter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,9 @@ use Pimple\Container;
|
||||||
* @property \Kanboard\Core\Paginator $paginator
|
* @property \Kanboard\Core\Paginator $paginator
|
||||||
* @property \Kanboard\Core\Template $template
|
* @property \Kanboard\Core\Template $template
|
||||||
* @property \Kanboard\Decorator\MetadataCacheDecorator $userMetadataCacheDecorator
|
* @property \Kanboard\Decorator\MetadataCacheDecorator $userMetadataCacheDecorator
|
||||||
|
* @property \Kanboard\Decorator\columnRestrictionCacheDecorator $columnRestrictionCacheDecorator
|
||||||
* @property \Kanboard\Decorator\ColumnMoveRestrictionCacheDecorator $columnMoveRestrictionCacheDecorator
|
* @property \Kanboard\Decorator\ColumnMoveRestrictionCacheDecorator $columnMoveRestrictionCacheDecorator
|
||||||
|
* @property \Kanboard\Decorator\ProjectRoleRestrictionCacheDecorator $projectRoleRestrictionCacheDecorator
|
||||||
* @property \Kanboard\Model\ActionModel $actionModel
|
* @property \Kanboard\Model\ActionModel $actionModel
|
||||||
* @property \Kanboard\Model\ActionParameterModel $actionParameterModel
|
* @property \Kanboard\Model\ActionParameterModel $actionParameterModel
|
||||||
* @property \Kanboard\Model\AvatarFileModel $avatarFileModel
|
* @property \Kanboard\Model\AvatarFileModel $avatarFileModel
|
||||||
|
|
@ -65,6 +67,7 @@ use Pimple\Container;
|
||||||
* @property \Kanboard\Model\CategoryModel $categoryModel
|
* @property \Kanboard\Model\CategoryModel $categoryModel
|
||||||
* @property \Kanboard\Model\ColorModel $colorModel
|
* @property \Kanboard\Model\ColorModel $colorModel
|
||||||
* @property \Kanboard\Model\ColumnModel $columnModel
|
* @property \Kanboard\Model\ColumnModel $columnModel
|
||||||
|
* @property \Kanboard\Model\ColumnRestrictionModel $columnRestrictionModel
|
||||||
* @property \Kanboard\Model\ColumnMoveRestrictionModel $columnMoveRestrictionModel
|
* @property \Kanboard\Model\ColumnMoveRestrictionModel $columnMoveRestrictionModel
|
||||||
* @property \Kanboard\Model\CommentModel $commentModel
|
* @property \Kanboard\Model\CommentModel $commentModel
|
||||||
* @property \Kanboard\Model\ConfigModel $configModel
|
* @property \Kanboard\Model\ConfigModel $configModel
|
||||||
|
|
@ -136,6 +139,7 @@ use Pimple\Container;
|
||||||
* @property \Kanboard\Validator\AuthValidator $authValidator
|
* @property \Kanboard\Validator\AuthValidator $authValidator
|
||||||
* @property \Kanboard\Validator\ColumnValidator $columnValidator
|
* @property \Kanboard\Validator\ColumnValidator $columnValidator
|
||||||
* @property \Kanboard\Validator\CategoryValidator $categoryValidator
|
* @property \Kanboard\Validator\CategoryValidator $categoryValidator
|
||||||
|
* @property \Kanboard\Validator\ColumnRestrictionValidator $columnRestrictionValidator
|
||||||
* @property \Kanboard\Validator\ColumnMoveRestrictionValidator $columnMoveRestrictionValidator
|
* @property \Kanboard\Validator\ColumnMoveRestrictionValidator $columnMoveRestrictionValidator
|
||||||
* @property \Kanboard\Validator\CommentValidator $commentValidator
|
* @property \Kanboard\Validator\CommentValidator $commentValidator
|
||||||
* @property \Kanboard\Validator\CurrencyValidator $currencyValidator
|
* @property \Kanboard\Validator\CurrencyValidator $currencyValidator
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,8 @@ class ColumnMoveRestrictionCacheDecorator
|
||||||
/**
|
/**
|
||||||
* Proxy method to get sortable columns
|
* Proxy method to get sortable columns
|
||||||
*
|
*
|
||||||
* @param int $project_id
|
* @param int $project_id
|
||||||
|
* @param string $role
|
||||||
* @return array|mixed
|
* @return array|mixed
|
||||||
*/
|
*/
|
||||||
public function getSortableColumns($project_id, $role)
|
public function getSortableColumns($project_id, $role)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Decorator;
|
||||||
|
|
||||||
|
use Kanboard\Core\Cache\CacheInterface;
|
||||||
|
use Kanboard\Model\ColumnRestrictionModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ColumnRestrictionCacheDecorator
|
||||||
|
*
|
||||||
|
* @package Kanboard\Decorator
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class ColumnRestrictionCacheDecorator
|
||||||
|
{
|
||||||
|
protected $cachePrefix = 'column_restriction:';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var CacheInterface
|
||||||
|
*/
|
||||||
|
protected $cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ColumnRestrictionModel
|
||||||
|
*/
|
||||||
|
protected $columnRestrictionModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ColumnMoveRestrictionDecorator constructor.
|
||||||
|
*
|
||||||
|
* @param CacheInterface $cache
|
||||||
|
* @param ColumnRestrictionModel $columnMoveRestrictionModel
|
||||||
|
*/
|
||||||
|
public function __construct(CacheInterface $cache, ColumnRestrictionModel $columnMoveRestrictionModel)
|
||||||
|
{
|
||||||
|
$this->cache = $cache;
|
||||||
|
$this->columnRestrictionModel = $columnMoveRestrictionModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proxy method to get sortable columns
|
||||||
|
*
|
||||||
|
* @param int $project_id
|
||||||
|
* @param string $role
|
||||||
|
* @return array|mixed
|
||||||
|
*/
|
||||||
|
public function getAllByRole($project_id, $role)
|
||||||
|
{
|
||||||
|
$key = $this->cachePrefix.$project_id.$role;
|
||||||
|
$columnRestrictions = $this->cache->get($key);
|
||||||
|
|
||||||
|
if ($columnRestrictions === null) {
|
||||||
|
$columnRestrictions = $this->columnRestrictionModel->getAllByRole($project_id, $role);
|
||||||
|
$this->cache->set($key, $columnRestrictions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $columnRestrictions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Decorator;
|
||||||
|
|
||||||
|
use Kanboard\Core\Cache\CacheInterface;
|
||||||
|
use Kanboard\Model\ProjectRoleRestrictionModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ProjectRoleRestrictionCacheDecorator
|
||||||
|
*
|
||||||
|
* @package Kanboard\Decorator
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class ProjectRoleRestrictionCacheDecorator
|
||||||
|
{
|
||||||
|
protected $cachePrefix = 'project_restriction:';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var CacheInterface
|
||||||
|
*/
|
||||||
|
protected $cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ProjectRoleRestrictionModel
|
||||||
|
*/
|
||||||
|
protected $projectRoleRestrictionModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ColumnMoveRestrictionDecorator constructor.
|
||||||
|
*
|
||||||
|
* @param CacheInterface $cache
|
||||||
|
* @param ProjectRoleRestrictionModel $projectRoleRestrictionModel
|
||||||
|
*/
|
||||||
|
public function __construct(CacheInterface $cache, ProjectRoleRestrictionModel $projectRoleRestrictionModel)
|
||||||
|
{
|
||||||
|
$this->cache = $cache;
|
||||||
|
$this->projectRoleRestrictionModel = $projectRoleRestrictionModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proxy method to get sortable columns
|
||||||
|
*
|
||||||
|
* @param int $project_id
|
||||||
|
* @param string $role
|
||||||
|
* @return array|mixed
|
||||||
|
*/
|
||||||
|
public function getAllByRole($project_id, $role)
|
||||||
|
{
|
||||||
|
$key = $this->cachePrefix.$project_id.$role;
|
||||||
|
$projectRestrictions = $this->cache->get($key);
|
||||||
|
|
||||||
|
if ($projectRestrictions === null) {
|
||||||
|
$projectRestrictions = $this->projectRoleRestrictionModel->getAllByRole($project_id, $role);
|
||||||
|
$this->cache->set($key, $projectRestrictions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $projectRestrictions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,8 @@ namespace Kanboard\Helper;
|
||||||
|
|
||||||
use Kanboard\Core\Base;
|
use Kanboard\Core\Base;
|
||||||
use Kanboard\Core\Security\Role;
|
use Kanboard\Core\Security\Role;
|
||||||
|
use Kanboard\Model\ColumnRestrictionModel;
|
||||||
|
use Kanboard\Model\ProjectRoleRestrictionModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ProjectRoleHelper
|
* Class ProjectRoleHelper
|
||||||
|
|
@ -98,6 +100,46 @@ class ProjectRoleHelper extends Base
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the user can create a task for the given column
|
||||||
|
*
|
||||||
|
* @param int $project_id
|
||||||
|
* @param int $column_id
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function canCreateTaskInColumn($project_id, $column_id)
|
||||||
|
{
|
||||||
|
$role = $this->getProjectUserRole($project_id);
|
||||||
|
|
||||||
|
if ($this->role->isCustomProjectRole($role)) {
|
||||||
|
if (! $this->isAllowedToCreateTask($project_id, $column_id, $role)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->helper->user->hasProjectAccess('TaskCreationController', 'show', $project_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the user can create a task for the given column
|
||||||
|
*
|
||||||
|
* @param int $project_id
|
||||||
|
* @param int $column_id
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function canChangeTaskStatusInColumn($project_id, $column_id)
|
||||||
|
{
|
||||||
|
$role = $this->getProjectUserRole($project_id);
|
||||||
|
|
||||||
|
if ($this->role->isCustomProjectRole($role)) {
|
||||||
|
if (! $this->isAllowedToChangeTaskStatus($project_id, $column_id, $role)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->helper->user->hasProjectAccess('TaskStatusController', 'close', $project_id);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if the user can remove a task
|
* Return true if the user can remove a task
|
||||||
*
|
*
|
||||||
|
|
@ -145,13 +187,77 @@ class ProjectRoleHelper extends Base
|
||||||
$role = $this->getProjectUserRole($project_id);
|
$role = $this->getProjectUserRole($project_id);
|
||||||
|
|
||||||
if ($this->role->isCustomProjectRole($role)) {
|
if ($this->role->isCustomProjectRole($role)) {
|
||||||
$restrictions = $this->projectRoleRestrictionModel->getAllByRole($project_id, $role);
|
$result = $this->projectAuthorization->isAllowed($controller, $action, Role::PROJECT_MEMBER);
|
||||||
$result = $this->projectRoleRestrictionModel->isAllowed($restrictions, $controller, $action);
|
|
||||||
$result = $result && $this->projectAuthorization->isAllowed($controller, $action, Role::PROJECT_MEMBER);
|
|
||||||
} else {
|
} else {
|
||||||
$result = $this->projectAuthorization->isAllowed($controller, $action, $role);
|
$result = $this->projectAuthorization->isAllowed($controller, $action, $role);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check authorization for a custom project role to change the task status
|
||||||
|
*
|
||||||
|
* @param int $project_id
|
||||||
|
* @param int $column_id
|
||||||
|
* @param string $role
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isAllowedToChangeTaskStatus($project_id, $column_id, $role)
|
||||||
|
{
|
||||||
|
$columnRestrictions = $this->columnRestrictionCacheDecorator->getAllByRole($project_id, $role);
|
||||||
|
|
||||||
|
foreach ($columnRestrictions as $restriction) {
|
||||||
|
if ($restriction['column_id'] == $column_id) {
|
||||||
|
if ($restriction['rule'] == ColumnRestrictionModel::RULE_ALLOW_TASK_OPEN_CLOSE) {
|
||||||
|
return true;
|
||||||
|
} else if ($restriction['rule'] == ColumnRestrictionModel::RULE_BLOCK_TASK_OPEN_CLOSE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$projectRestrictions = $this->projectRoleRestrictionCacheDecorator->getAllByRole($project_id, $role);
|
||||||
|
|
||||||
|
foreach ($projectRestrictions as $restriction) {
|
||||||
|
if ($restriction['rule'] == ProjectRoleRestrictionModel::RULE_TASK_OPEN_CLOSE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check authorization for a custom project role to create a task
|
||||||
|
*
|
||||||
|
* @param int $project_id
|
||||||
|
* @param int $column_id
|
||||||
|
* @param string $role
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isAllowedToCreateTask($project_id, $column_id, $role)
|
||||||
|
{
|
||||||
|
$columnRestrictions = $this->columnRestrictionCacheDecorator->getAllByRole($project_id, $role);
|
||||||
|
|
||||||
|
foreach ($columnRestrictions as $restriction) {
|
||||||
|
if ($restriction['column_id'] == $column_id) {
|
||||||
|
if ($restriction['rule'] == ColumnRestrictionModel::RULE_ALLOW_TASK_CREATION) {
|
||||||
|
return true;
|
||||||
|
} else if ($restriction['rule'] == ColumnRestrictionModel::RULE_BLOCK_TASK_CREATION) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$projectRestrictions = $this->projectRoleRestrictionCacheDecorator->getAllByRole($project_id, $role);
|
||||||
|
|
||||||
|
foreach ($projectRestrictions as $restriction) {
|
||||||
|
if ($restriction['rule'] == ProjectRoleRestrictionModel::RULE_TASK_CREATION) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,152 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Model;
|
||||||
|
|
||||||
|
use Kanboard\Core\Base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ColumnRestrictionModel
|
||||||
|
*
|
||||||
|
* @package Kanboard\Model
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class ColumnRestrictionModel extends Base
|
||||||
|
{
|
||||||
|
const TABLE = 'column_has_restrictions';
|
||||||
|
|
||||||
|
const RULE_ALLOW_TASK_CREATION = 'allow.task_creation';
|
||||||
|
const RULE_ALLOW_TASK_OPEN_CLOSE = 'allow.task_open_close';
|
||||||
|
const RULE_BLOCK_TASK_CREATION = 'block.task_creation';
|
||||||
|
const RULE_BLOCK_TASK_OPEN_CLOSE = 'block.task_open_close';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get rules
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getRules()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
self::RULE_ALLOW_TASK_CREATION => t('Task creation is permitted for this column'),
|
||||||
|
self::RULE_ALLOW_TASK_OPEN_CLOSE => t('Closing or opening a task is permitted for this column'),
|
||||||
|
self::RULE_BLOCK_TASK_CREATION => t('Task creation is blocked for this column'),
|
||||||
|
self::RULE_BLOCK_TASK_OPEN_CLOSE => t('Closing or opening a task is blocked for this column'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch one restriction
|
||||||
|
*
|
||||||
|
* @param int $project_id
|
||||||
|
* @param int $restriction_id
|
||||||
|
* @return array|null
|
||||||
|
*/
|
||||||
|
public function getById($project_id, $restriction_id)
|
||||||
|
{
|
||||||
|
return $this->db
|
||||||
|
->table(self::TABLE)
|
||||||
|
->columns(
|
||||||
|
self::TABLE.'.restriction_id',
|
||||||
|
self::TABLE.'.project_id',
|
||||||
|
self::TABLE.'.role_id',
|
||||||
|
self::TABLE.'.column_id',
|
||||||
|
self::TABLE.'.rule',
|
||||||
|
'pr.role',
|
||||||
|
'c.title as column_title'
|
||||||
|
)
|
||||||
|
->left(ColumnModel::TABLE, 'c', 'id', self::TABLE, 'column_id')
|
||||||
|
->left(ProjectRoleModel::TABLE, 'pr', 'role_id', self::TABLE, 'role_id')
|
||||||
|
->eq(self::TABLE.'.project_id', $project_id)
|
||||||
|
->eq(self::TABLE.'.restriction_id', $restriction_id)
|
||||||
|
->findOne();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all project column restrictions
|
||||||
|
*
|
||||||
|
* @param int $project_id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAll($project_id)
|
||||||
|
{
|
||||||
|
$rules = $this->getRules();
|
||||||
|
$restrictions = $this->db
|
||||||
|
->table(self::TABLE)
|
||||||
|
->columns(
|
||||||
|
self::TABLE.'.restriction_id',
|
||||||
|
self::TABLE.'.project_id',
|
||||||
|
self::TABLE.'.role_id',
|
||||||
|
self::TABLE.'.column_id',
|
||||||
|
self::TABLE.'.rule',
|
||||||
|
'pr.role',
|
||||||
|
'c.title as column_title'
|
||||||
|
)
|
||||||
|
->left(ColumnModel::TABLE, 'c', 'id', self::TABLE, 'column_id')
|
||||||
|
->left(ProjectRoleModel::TABLE, 'pr', 'role_id', self::TABLE, 'role_id')
|
||||||
|
->eq(self::TABLE.'.project_id', $project_id)
|
||||||
|
->findAll();
|
||||||
|
|
||||||
|
foreach ($restrictions as &$restriction) {
|
||||||
|
$restriction['title'] = $rules[$restriction['rule']];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $restrictions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get restrictions
|
||||||
|
*
|
||||||
|
* @param int $project_id
|
||||||
|
* @param string $role
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAllByRole($project_id, $role)
|
||||||
|
{
|
||||||
|
return $this->db
|
||||||
|
->table(self::TABLE)
|
||||||
|
->columns(
|
||||||
|
self::TABLE.'.restriction_id',
|
||||||
|
self::TABLE.'.project_id',
|
||||||
|
self::TABLE.'.role_id',
|
||||||
|
self::TABLE.'.column_id',
|
||||||
|
self::TABLE.'.rule',
|
||||||
|
'pr.role'
|
||||||
|
)
|
||||||
|
->eq(self::TABLE.'.project_id', $project_id)
|
||||||
|
->eq('pr.role', $role)
|
||||||
|
->left(ProjectRoleModel::TABLE, 'pr', 'role_id', self::TABLE, 'role_id')
|
||||||
|
->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new column restriction
|
||||||
|
*
|
||||||
|
* @param int $project_id
|
||||||
|
* @param int $role_id
|
||||||
|
* @param int $column_id
|
||||||
|
* @param int $rule
|
||||||
|
* @return bool|int
|
||||||
|
*/
|
||||||
|
public function create($project_id, $role_id, $column_id, $rule)
|
||||||
|
{
|
||||||
|
return $this->db
|
||||||
|
->table(self::TABLE)
|
||||||
|
->persist(array(
|
||||||
|
'project_id' => $project_id,
|
||||||
|
'role_id' => $role_id,
|
||||||
|
'column_id' => $column_id,
|
||||||
|
'rule' => $rule,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a permission
|
||||||
|
*
|
||||||
|
* @param int $restriction_id
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function remove($restriction_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)->eq('restriction_id', $restriction_id)->remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -122,8 +122,13 @@ class ProjectPermissionModel extends Base
|
||||||
*/
|
*/
|
||||||
public function isAssignable($project_id, $user_id)
|
public function isAssignable($project_id, $user_id)
|
||||||
{
|
{
|
||||||
return $this->userModel->isActive($user_id) &&
|
if ($this->userModel->isActive($user_id)) {
|
||||||
in_array($this->projectUserRoleModel->getUserRole($project_id, $user_id), array(Role::PROJECT_MEMBER, Role::PROJECT_MANAGER));
|
$role = $this->projectUserRoleModel->getUserRole($project_id, $user_id);
|
||||||
|
|
||||||
|
return ! empty($role) && $role !== Role::PROJECT_VIEWER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -71,10 +71,14 @@ class ProjectRoleModel extends Base
|
||||||
{
|
{
|
||||||
$roles = $this->getAll($project_id);
|
$roles = $this->getAll($project_id);
|
||||||
|
|
||||||
$column_restrictions = $this->columnMoveRestrictionModel->getAll($project_id);
|
$column_restrictions = $this->columnRestrictionModel->getAll($project_id);
|
||||||
$column_restrictions = array_column_index($column_restrictions, 'role_id');
|
$column_restrictions = array_column_index($column_restrictions, 'role_id');
|
||||||
array_merge_relation($roles, $column_restrictions, 'column_restrictions', 'role_id');
|
array_merge_relation($roles, $column_restrictions, 'column_restrictions', 'role_id');
|
||||||
|
|
||||||
|
$column_move_restrictions = $this->columnMoveRestrictionModel->getAll($project_id);
|
||||||
|
$column_move_restrictions = array_column_index($column_move_restrictions, 'role_id');
|
||||||
|
array_merge_relation($roles, $column_move_restrictions, 'column_move_restrictions', 'role_id');
|
||||||
|
|
||||||
$project_restrictions = $this->projectRoleRestrictionModel->getAll($project_id);
|
$project_restrictions = $this->projectRoleRestrictionModel->getAll($project_id);
|
||||||
$project_restrictions = array_column_index($project_restrictions, 'role_id');
|
$project_restrictions = array_column_index($project_restrictions, 'role_id');
|
||||||
array_merge_relation($roles, $project_restrictions, 'project_restrictions', 'role_id');
|
array_merge_relation($roles, $project_restrictions, 'project_restrictions', 'role_id');
|
||||||
|
|
@ -109,13 +113,41 @@ class ProjectRoleModel extends Base
|
||||||
*/
|
*/
|
||||||
public function update($role_id, $project_id, $role)
|
public function update($role_id, $project_id, $role)
|
||||||
{
|
{
|
||||||
return $this->db
|
$this->db->startTransaction();
|
||||||
|
|
||||||
|
$previousRole = $this->getById($project_id, $role_id);
|
||||||
|
|
||||||
|
$r1 = $this->db
|
||||||
|
->table(ProjectUserRoleModel::TABLE)
|
||||||
|
->eq('project_id', $project_id)
|
||||||
|
->eq('role', $previousRole['role'])
|
||||||
|
->update(array(
|
||||||
|
'role' => $role
|
||||||
|
));
|
||||||
|
|
||||||
|
$r2 = $this->db
|
||||||
|
->table(ProjectGroupRoleModel::TABLE)
|
||||||
|
->eq('project_id', $project_id)
|
||||||
|
->eq('role', $previousRole['role'])
|
||||||
|
->update(array(
|
||||||
|
'role' => $role
|
||||||
|
));
|
||||||
|
|
||||||
|
$r3 = $this->db
|
||||||
->table(self::TABLE)
|
->table(self::TABLE)
|
||||||
->eq('role_id', $role_id)
|
->eq('role_id', $role_id)
|
||||||
->eq('project_id', $project_id)
|
->eq('project_id', $project_id)
|
||||||
->update(array(
|
->update(array(
|
||||||
'role' => $role,
|
'role' => $role,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
if ($r1 && $r2 && $r3) {
|
||||||
|
$this->db->closeTransaction();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->db->cancelTransaction();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -17,15 +17,6 @@ class ProjectRoleRestrictionModel extends Base
|
||||||
const RULE_TASK_CREATION = 'task_creation';
|
const RULE_TASK_CREATION = 'task_creation';
|
||||||
const RULE_TASK_OPEN_CLOSE = 'task_open_close';
|
const RULE_TASK_OPEN_CLOSE = 'task_open_close';
|
||||||
|
|
||||||
protected $ruleMapping = array(
|
|
||||||
self::RULE_TASK_CREATION => array(
|
|
||||||
array('controller' => 'TaskCreationController', 'method' => '*'),
|
|
||||||
),
|
|
||||||
self::RULE_TASK_OPEN_CLOSE => array(
|
|
||||||
array('controller' => 'TaskStatusController', 'method' => '*'),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get rules
|
* Get rules
|
||||||
*
|
*
|
||||||
|
|
@ -91,7 +82,7 @@ class ProjectRoleRestrictionModel extends Base
|
||||||
*/
|
*/
|
||||||
public function getAllByRole($project_id, $role)
|
public function getAllByRole($project_id, $role)
|
||||||
{
|
{
|
||||||
$rules = $this->db
|
return $this->db
|
||||||
->table(self::TABLE)
|
->table(self::TABLE)
|
||||||
->columns(
|
->columns(
|
||||||
self::TABLE.'.restriction_id',
|
self::TABLE.'.restriction_id',
|
||||||
|
|
@ -104,12 +95,6 @@ class ProjectRoleRestrictionModel extends Base
|
||||||
->eq('role', $role)
|
->eq('role', $role)
|
||||||
->left(ProjectRoleModel::TABLE, 'pr', 'role_id', self::TABLE, 'role_id')
|
->left(ProjectRoleModel::TABLE, 'pr', 'role_id', self::TABLE, 'role_id')
|
||||||
->findAll();
|
->findAll();
|
||||||
|
|
||||||
foreach ($rules as &$rule) {
|
|
||||||
$rule['acl'] = $this->ruleMapping[$rule['rule']];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $rules;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -140,31 +125,4 @@ class ProjectRoleRestrictionModel extends Base
|
||||||
{
|
{
|
||||||
return $this->db->table(self::TABLE)->eq('restriction_id', $restriction_id)->remove();
|
return $this->db->table(self::TABLE)->eq('restriction_id', $restriction_id)->remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the controller/method is allowed
|
|
||||||
*
|
|
||||||
* @param array $restrictions
|
|
||||||
* @param string $controller
|
|
||||||
* @param string $method
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isAllowed(array $restrictions, $controller, $method)
|
|
||||||
{
|
|
||||||
$controller = strtolower($controller);
|
|
||||||
$method = strtolower($method);
|
|
||||||
|
|
||||||
foreach ($restrictions as $restriction) {
|
|
||||||
foreach ($restriction['acl'] as $acl) {
|
|
||||||
$acl['controller'] = strtolower($acl['controller']);
|
|
||||||
$acl['method'] = strtolower($acl['method']);
|
|
||||||
|
|
||||||
if ($acl['controller'] === $controller && ($acl['method'] === '*' || $acl['method'] === $method)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ class ProjectUserRoleModel extends Base
|
||||||
->join(UserModel::TABLE, 'id', 'user_id')
|
->join(UserModel::TABLE, 'id', 'user_id')
|
||||||
->eq(UserModel::TABLE.'.is_active', 1)
|
->eq(UserModel::TABLE.'.is_active', 1)
|
||||||
->eq(self::TABLE.'.project_id', $project_id)
|
->eq(self::TABLE.'.project_id', $project_id)
|
||||||
->in(self::TABLE.'.role', array(Role::PROJECT_MANAGER, Role::PROJECT_MEMBER))
|
->neq(self::TABLE.'.role', Role::PROJECT_VIEWER)
|
||||||
->findAll();
|
->findAll();
|
||||||
|
|
||||||
$groupMembers = $this->projectGroupRoleModel->getAssignableUsers($project_id);
|
$groupMembers = $this->projectGroupRoleModel->getAssignableUsers($project_id);
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ class TaskFinderModel extends Base
|
||||||
TaskModel::TABLE.'.date_due',
|
TaskModel::TABLE.'.date_due',
|
||||||
TaskModel::TABLE.'.date_creation',
|
TaskModel::TABLE.'.date_creation',
|
||||||
TaskModel::TABLE.'.project_id',
|
TaskModel::TABLE.'.project_id',
|
||||||
|
TaskModel::TABLE.'.column_id',
|
||||||
TaskModel::TABLE.'.color_id',
|
TaskModel::TABLE.'.color_id',
|
||||||
TaskModel::TABLE.'.priority',
|
TaskModel::TABLE.'.priority',
|
||||||
TaskModel::TABLE.'.time_spent',
|
TaskModel::TABLE.'.time_spent',
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,25 @@ use PDO;
|
||||||
use Kanboard\Core\Security\Token;
|
use Kanboard\Core\Security\Token;
|
||||||
use Kanboard\Core\Security\Role;
|
use Kanboard\Core\Security\Role;
|
||||||
|
|
||||||
const VERSION = 114;
|
const VERSION = 115;
|
||||||
|
|
||||||
|
function version_115(PDO $pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec("
|
||||||
|
CREATE TABLE column_has_restrictions (
|
||||||
|
restriction_id INT NOT NULL AUTO_INCREMENT,
|
||||||
|
project_id INT NOT NULL,
|
||||||
|
role_id INT NOT NULL,
|
||||||
|
column_id INT NOT NULL,
|
||||||
|
rule VARCHAR(255) NOT NULL,
|
||||||
|
UNIQUE(role_id, column_id, rule),
|
||||||
|
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(role_id) REFERENCES project_has_roles(role_id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(column_id) REFERENCES columns(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY(restriction_id)
|
||||||
|
) ENGINE=InnoDB CHARSET=utf8
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
function version_114(PDO $pdo)
|
function version_114(PDO $pdo)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,24 @@ use PDO;
|
||||||
use Kanboard\Core\Security\Token;
|
use Kanboard\Core\Security\Token;
|
||||||
use Kanboard\Core\Security\Role;
|
use Kanboard\Core\Security\Role;
|
||||||
|
|
||||||
const VERSION = 93;
|
const VERSION = 94;
|
||||||
|
|
||||||
|
function version_94(PDO $pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec("
|
||||||
|
CREATE TABLE column_has_restrictions (
|
||||||
|
restriction_id SERIAL PRIMARY KEY,
|
||||||
|
project_id INTEGER NOT NULL,
|
||||||
|
role_id INTEGER NOT NULL,
|
||||||
|
column_id INTEGER NOT NULL,
|
||||||
|
rule VARCHAR(255) NOT NULL,
|
||||||
|
UNIQUE(role_id, column_id, rule),
|
||||||
|
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(role_id) REFERENCES project_has_roles(role_id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(column_id) REFERENCES columns(id) ON DELETE CASCADE
|
||||||
|
)
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
function version_93(PDO $pdo)
|
function version_93(PDO $pdo)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,24 @@ use Kanboard\Core\Security\Token;
|
||||||
use Kanboard\Core\Security\Role;
|
use Kanboard\Core\Security\Role;
|
||||||
use PDO;
|
use PDO;
|
||||||
|
|
||||||
const VERSION = 105;
|
const VERSION = 106;
|
||||||
|
|
||||||
|
function version_106(PDO $pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec("
|
||||||
|
CREATE TABLE column_has_restrictions (
|
||||||
|
restriction_id INTEGER PRIMARY KEY,
|
||||||
|
project_id INTEGER NOT NULL,
|
||||||
|
role_id INTEGER NOT NULL,
|
||||||
|
column_id INTEGER NOT NULL,
|
||||||
|
rule VARCHAR(255) NOT NULL,
|
||||||
|
UNIQUE(role_id, column_id, rule),
|
||||||
|
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(role_id) REFERENCES project_has_roles(role_id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(column_id) REFERENCES columns(id) ON DELETE CASCADE
|
||||||
|
)
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
function version_105(PDO $pdo)
|
function version_105(PDO $pdo)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,9 @@ namespace Kanboard\ServiceProvider;
|
||||||
use Kanboard\Core\Cache\FileCache;
|
use Kanboard\Core\Cache\FileCache;
|
||||||
use Kanboard\Core\Cache\MemoryCache;
|
use Kanboard\Core\Cache\MemoryCache;
|
||||||
use Kanboard\Decorator\ColumnMoveRestrictionCacheDecorator;
|
use Kanboard\Decorator\ColumnMoveRestrictionCacheDecorator;
|
||||||
|
use Kanboard\Decorator\ColumnRestrictionCacheDecorator;
|
||||||
use Kanboard\Decorator\MetadataCacheDecorator;
|
use Kanboard\Decorator\MetadataCacheDecorator;
|
||||||
|
use Kanboard\Decorator\ProjectRoleRestrictionCacheDecorator;
|
||||||
use Pimple\Container;
|
use Pimple\Container;
|
||||||
use Pimple\ServiceProviderInterface;
|
use Pimple\ServiceProviderInterface;
|
||||||
|
|
||||||
|
|
@ -54,6 +56,20 @@ class CacheProvider implements ServiceProviderInterface
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$container['columnRestrictionCacheDecorator'] = function($c) {
|
||||||
|
return new ColumnRestrictionCacheDecorator(
|
||||||
|
$c['memoryCache'],
|
||||||
|
$c['columnRestrictionModel']
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
$container['projectRoleRestrictionCacheDecorator'] = function($c) {
|
||||||
|
return new ProjectRoleRestrictionCacheDecorator(
|
||||||
|
$c['memoryCache'],
|
||||||
|
$c['projectRoleRestrictionModel']
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return $container;
|
return $container;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ class ClassProvider implements ServiceProviderInterface
|
||||||
'CategoryModel',
|
'CategoryModel',
|
||||||
'ColorModel',
|
'ColorModel',
|
||||||
'ColumnModel',
|
'ColumnModel',
|
||||||
|
'ColumnRestrictionModel',
|
||||||
'ColumnMoveRestrictionModel',
|
'ColumnMoveRestrictionModel',
|
||||||
'CommentModel',
|
'CommentModel',
|
||||||
'ConfigModel',
|
'ConfigModel',
|
||||||
|
|
@ -101,6 +102,7 @@ class ClassProvider implements ServiceProviderInterface
|
||||||
'AuthValidator',
|
'AuthValidator',
|
||||||
'CategoryValidator',
|
'CategoryValidator',
|
||||||
'ColumnMoveRestrictionValidator',
|
'ColumnMoveRestrictionValidator',
|
||||||
|
'ColumnRestrictionValidator',
|
||||||
'ColumnValidator',
|
'ColumnValidator',
|
||||||
'CommentValidator',
|
'CommentValidator',
|
||||||
'CurrencyValidator',
|
'CurrencyValidator',
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
<!-- column in expanded mode -->
|
<!-- column in expanded mode -->
|
||||||
<div class="board-column-expanded">
|
<div class="board-column-expanded">
|
||||||
<?php if (! $not_editable && $this->user->hasProjectAccess('TaskCreationController', 'show', $column['project_id'])): ?>
|
<?php if (! $not_editable && $this->projectRole->canCreateTaskInColumn($column['project_id'], $column['id'])): ?>
|
||||||
<div class="board-add-icon">
|
<div class="board-add-icon">
|
||||||
<?= $this->url->link('+', 'TaskCreationController', 'show', array('project_id' => $column['project_id'], 'column_id' => $column['id'], 'swimlane_id' => $swimlane['id']), false, 'popover', t('Add a new task')) ?>
|
<?= $this->url->link('+', 'TaskCreationController', 'show', array('project_id' => $column['project_id'], 'column_id' => $column['id'], 'swimlane_id' => $swimlane['id']), false, 'popover', t('Add a new task')) ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<section id="main">
|
<section id="main">
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h2><?= t('New column restriction for the role "%s"', $role['role']) ?></h2>
|
<h2><?= t('New drag and drop restriction for the role "%s"', $role['role']) ?></h2>
|
||||||
</div>
|
</div>
|
||||||
<form class="popover-form" method="post" action="<?= $this->url->href('ColumnMoveRestrictionController', 'save', array('project_id' => $project['id'])) ?>" autocomplete="off">
|
<form class="popover-form" method="post" action="<?= $this->url->href('ColumnMoveRestrictionController', 'save', array('project_id' => $project['id'])) ?>" autocomplete="off">
|
||||||
<?= $this->form->csrf() ?>
|
<?= $this->form->csrf() ?>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
<section id="main">
|
||||||
|
<div class="page-header">
|
||||||
|
<h2><?= t('New column restriction for the role "%s"', $role['role']) ?></h2>
|
||||||
|
</div>
|
||||||
|
<form class="popover-form" method="post" action="<?= $this->url->href('ColumnRestrictionController', 'save', array('project_id' => $project['id'])) ?>" autocomplete="off">
|
||||||
|
<?= $this->form->csrf() ?>
|
||||||
|
<?= $this->form->hidden('project_id', $values) ?>
|
||||||
|
<?= $this->form->hidden('role_id', $values) ?>
|
||||||
|
|
||||||
|
<?= $this->form->label(t('Rule'), 'rule') ?>
|
||||||
|
<?= $this->form->select('rule', $rules, $values, $errors) ?>
|
||||||
|
|
||||||
|
<?= $this->form->label(t('Column'), 'column_id') ?>
|
||||||
|
<?= $this->form->select('column_id', $columns, $values, $errors) ?>
|
||||||
|
|
||||||
|
<div class="form-actions">
|
||||||
|
<button type="submit" class="btn btn-blue"><?= t('Save') ?></button>
|
||||||
|
<?= t('or') ?>
|
||||||
|
<?= $this->url->link(t('cancel'), 'ProjectRoleController', 'show', array(), false, 'close-popover') ?>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<div class="page-header">
|
||||||
|
<h2><?= t('Remove a column restriction') ?></h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="confirm">
|
||||||
|
<p class="alert alert-info">
|
||||||
|
<?= t('Do you really want to remove this column restriction?') ?>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="form-actions">
|
||||||
|
<?= $this->url->link(t('Yes'), 'ColumnRestrictionController', 'remove', array('project_id' => $project['id'], 'restriction_id' => $restriction['restriction_id']), true, 'btn btn-red') ?>
|
||||||
|
<?= t('or') ?> <?= $this->url->link(t('cancel'), 'ProjectRoleController', 'show', array('project_id' => $project['id']), false, 'close-popover') ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -24,7 +24,11 @@
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<i class="fa fa-plus fa-fw" aria-hidden="true"></i>
|
<i class="fa fa-plus fa-fw" aria-hidden="true"></i>
|
||||||
<?= $this->url->link(t('Add a new column restriction'), 'ColumnMoveRestrictionController', 'create', array('project_id' => $project['id'], 'role_id' => $role['role_id']), false, 'popover') ?>
|
<?= $this->url->link(t('Add a new drag and drop restriction'), 'ColumnMoveRestrictionController', 'create', array('project_id' => $project['id'], 'role_id' => $role['role_id']), false, 'popover') ?>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<i class="fa fa-plus fa-fw" aria-hidden="true"></i>
|
||||||
|
<?= $this->url->link(t('Add a new column restriction'), 'ColumnRestrictionController', 'create', array('project_id' => $project['id'], 'role_id' => $role['role_id']), false, 'popover') ?>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<i class="fa fa-pencil fa-fw" aria-hidden="true"></i>
|
<i class="fa fa-pencil fa-fw" aria-hidden="true"></i>
|
||||||
|
|
@ -41,7 +45,7 @@
|
||||||
<?= t('Actions') ?>
|
<?= t('Actions') ?>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
<?php if (empty($role['project_restrictions']) && empty($role['column_restrictions'])): ?>
|
<?php if (empty($role['project_restrictions']) && empty($role['column_restrictions']) && empty($role['column_move_restrictions'])): ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><?= t('There is no restriction for this role.') ?></td>
|
<td colspan="2"><?= t('There is no restriction for this role.') ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -49,6 +53,9 @@
|
||||||
<?php foreach ($role['project_restrictions'] as $restriction): ?>
|
<?php foreach ($role['project_restrictions'] as $restriction): ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
<i class="fa fa-ban fa-fw" aria-hidden="true"></i>
|
||||||
|
<strong><?= t('Project') ?></strong>
|
||||||
|
<i class="fa fa-arrow-right fa-fw" aria-hidden="true"></i>
|
||||||
<?= $this->text->e($restriction['title']) ?>
|
<?= $this->text->e($restriction['title']) ?>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
@ -60,7 +67,28 @@
|
||||||
<?php foreach ($role['column_restrictions'] as $restriction): ?>
|
<?php foreach ($role['column_restrictions'] as $restriction): ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<?= t('Only moving task from the column "%s" to "%s" is permitted', $restriction['src_column_title'], $restriction['dst_column_title']) ?>
|
<?php if (strpos($restriction['rule'], 'block') === 0): ?>
|
||||||
|
<i class="fa fa-ban fa-fw" aria-hidden="true"></i>
|
||||||
|
<?php else: ?>
|
||||||
|
<i class="fa fa-check-circle-o fa-fw" aria-hidden="true"></i>
|
||||||
|
<?php endif ?>
|
||||||
|
<strong><?= $this->text->e($restriction['column_title']) ?></strong>
|
||||||
|
<i class="fa fa-arrow-right fa-fw" aria-hidden="true"></i>
|
||||||
|
<?= $this->text->e($restriction['title']) ?>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<i class="fa fa-trash-o fa-fw" aria-hidden="true"></i>
|
||||||
|
<?= $this->url->link(t('Remove'), 'ColumnRestrictionController', 'confirm', array('project_id' => $project['id'], 'restriction_id' => $restriction['restriction_id']), false, 'popover') ?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach ?>
|
||||||
|
<?php foreach ($role['column_move_restrictions'] as $restriction): ?>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<i class="fa fa-check-circle-o fa-fw" aria-hidden="true"></i>
|
||||||
|
<strong><?= $this->text->e($restriction['src_column_title']) ?> / <?= $this->text->e($restriction['dst_column_title']) ?></strong>
|
||||||
|
<i class="fa fa-arrow-right fa-fw" aria-hidden="true"></i>
|
||||||
|
<?= t('Only moving task between those columns is permitted') ?>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<i class="fa fa-trash-o fa-fw" aria-hidden="true"></i>
|
<i class="fa fa-trash-o fa-fw" aria-hidden="true"></i>
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@
|
||||||
<?= $this->url->link(t('Remove'), 'TaskSuppressionController', 'confirm', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'popover') ?>
|
<?= $this->url->link(t('Remove'), 'TaskSuppressionController', 'confirm', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'popover') ?>
|
||||||
</li>
|
</li>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<?php if (isset($task['is_active']) && $this->user->hasProjectAccess('TaskStatusController', 'close', $task['project_id'])): ?>
|
<?php if (isset($task['is_active']) && $this->projectRole->canChangeTaskStatusInColumn($task['project_id'], $task['column_id'])): ?>
|
||||||
<li>
|
<li>
|
||||||
<?php if ($task['is_active'] == 1): ?>
|
<?php if ($task['is_active'] == 1): ?>
|
||||||
<i class="fa fa-times fa-fw"></i>
|
<i class="fa fa-times fa-fw"></i>
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@
|
||||||
<i class="fa fa-clone fa-fw"></i>
|
<i class="fa fa-clone fa-fw"></i>
|
||||||
<?= $this->url->link(t('Move to another project'), 'TaskDuplicationController', 'move', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'popover') ?>
|
<?= $this->url->link(t('Move to another project'), 'TaskDuplicationController', 'move', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'popover') ?>
|
||||||
</li>
|
</li>
|
||||||
<?php if ($this->user->hasProjectAccess('TaskStatusController', 'close', $task['project_id'])): ?>
|
<?php if ($this->projectRole->canChangeTaskStatusInColumn($task['project_id'], $task['column_id'])): ?>
|
||||||
<?php if ($task['is_active'] == 1): ?>
|
<?php if ($task['is_active'] == 1): ?>
|
||||||
<li>
|
<li>
|
||||||
<i class="fa fa-arrows fa-fw"></i>
|
<i class="fa fa-arrows fa-fw"></i>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Validator;
|
||||||
|
|
||||||
|
use SimpleValidator\Validator;
|
||||||
|
use SimpleValidator\Validators;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ColumnRestrictionValidator
|
||||||
|
*
|
||||||
|
* @package Kanboard\Validator
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class ColumnRestrictionValidator extends BaseValidator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Validate creation
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $values Form values
|
||||||
|
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
|
||||||
|
*/
|
||||||
|
public function validateCreation(array $values)
|
||||||
|
{
|
||||||
|
$v = new Validator($values, array(
|
||||||
|
new Validators\Required('project_id', t('This field is required')),
|
||||||
|
new Validators\Integer('project_id', t('This value must be an integer')),
|
||||||
|
new Validators\Required('role_id', t('This field is required')),
|
||||||
|
new Validators\Integer('role_id', t('This value must be an integer')),
|
||||||
|
new Validators\Required('rule', t('This field is required')),
|
||||||
|
new Validators\Required('column_id', t('This field is required')),
|
||||||
|
new Validators\Integer('column_id', t('This value must be an integer')),
|
||||||
|
));
|
||||||
|
|
||||||
|
return array(
|
||||||
|
$v->execute(),
|
||||||
|
$v->getErrors()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,8 +4,10 @@ use Kanboard\Core\Security\Role;
|
||||||
use Kanboard\Core\User\UserSession;
|
use Kanboard\Core\User\UserSession;
|
||||||
use Kanboard\Helper\ProjectRoleHelper;
|
use Kanboard\Helper\ProjectRoleHelper;
|
||||||
use Kanboard\Model\ColumnMoveRestrictionModel;
|
use Kanboard\Model\ColumnMoveRestrictionModel;
|
||||||
|
use Kanboard\Model\ColumnRestrictionModel;
|
||||||
use Kanboard\Model\ProjectModel;
|
use Kanboard\Model\ProjectModel;
|
||||||
use Kanboard\Model\ProjectRoleModel;
|
use Kanboard\Model\ProjectRoleModel;
|
||||||
|
use Kanboard\Model\ProjectRoleRestrictionModel;
|
||||||
use Kanboard\Model\ProjectUserRoleModel;
|
use Kanboard\Model\ProjectUserRoleModel;
|
||||||
use Kanboard\Model\TaskCreationModel;
|
use Kanboard\Model\TaskCreationModel;
|
||||||
use Kanboard\Model\TaskFinderModel;
|
use Kanboard\Model\TaskFinderModel;
|
||||||
|
|
@ -16,6 +18,182 @@ require_once __DIR__.'/../Base.php';
|
||||||
|
|
||||||
class ProjectRoleHelperTest extends Base
|
class ProjectRoleHelperTest extends Base
|
||||||
{
|
{
|
||||||
|
public function testCanCreateTaskInColumnWithProjectViewer()
|
||||||
|
{
|
||||||
|
$projectRoleHelper = new ProjectRoleHelper($this->container);
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectUserRole = new ProjectUserRoleModel($this->container);
|
||||||
|
$userModel = new UserModel($this->container);
|
||||||
|
|
||||||
|
$this->container['sessionStorage']->user = array(
|
||||||
|
'id' => 2,
|
||||||
|
'role' => Role::APP_USER,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(2, $userModel->create(array('username' => 'user')));
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertTrue($projectUserRole->addUser(1, 2, Role::PROJECT_VIEWER));
|
||||||
|
|
||||||
|
$this->assertFalse($projectRoleHelper->canCreateTaskInColumn(1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanCreateTaskInColumnWithProjectMember()
|
||||||
|
{
|
||||||
|
$projectRoleHelper = new ProjectRoleHelper($this->container);
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectUserRole = new ProjectUserRoleModel($this->container);
|
||||||
|
$userModel = new UserModel($this->container);
|
||||||
|
|
||||||
|
$this->container['sessionStorage']->user = array(
|
||||||
|
'id' => 2,
|
||||||
|
'role' => Role::APP_USER,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(2, $userModel->create(array('username' => 'user')));
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertTrue($projectUserRole->addUser(1, 2, Role::PROJECT_MEMBER));
|
||||||
|
|
||||||
|
$this->assertTrue($projectRoleHelper->canCreateTaskInColumn(1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanCreateTaskInColumnWithCustomProjectRole()
|
||||||
|
{
|
||||||
|
$projectRoleHelper = new ProjectRoleHelper($this->container);
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectUserRole = new ProjectUserRoleModel($this->container);
|
||||||
|
$userModel = new UserModel($this->container);
|
||||||
|
$projectRoleModel = new ProjectRoleModel($this->container);
|
||||||
|
|
||||||
|
$this->container['sessionStorage']->user = array(
|
||||||
|
'id' => 2,
|
||||||
|
'role' => Role::APP_USER,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(2, $userModel->create(array('username' => 'user')));
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectRoleModel->create(1, 'Custom Role'));
|
||||||
|
$this->assertTrue($projectUserRole->addUser(1, 2, 'Custom Role'));
|
||||||
|
|
||||||
|
$this->assertTrue($projectRoleHelper->canCreateTaskInColumn(1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanCreateTaskInColumnWithCustomProjectRoleAndRestrictions()
|
||||||
|
{
|
||||||
|
$projectRoleHelper = new ProjectRoleHelper($this->container);
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectUserRole = new ProjectUserRoleModel($this->container);
|
||||||
|
$userModel = new UserModel($this->container);
|
||||||
|
$projectRoleModel = new ProjectRoleModel($this->container);
|
||||||
|
$projectRoleRestrictionModel = new ProjectRoleRestrictionModel($this->container);
|
||||||
|
$columnRestrictionModel = new ColumnRestrictionModel($this->container);
|
||||||
|
|
||||||
|
$this->container['sessionStorage']->user = array(
|
||||||
|
'id' => 2,
|
||||||
|
'role' => Role::APP_USER,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(2, $userModel->create(array('username' => 'user')));
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectRoleModel->create(1, 'Custom Role'));
|
||||||
|
$this->assertTrue($projectUserRole->addUser(1, 2, 'Custom Role'));
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectRoleRestrictionModel->create(1, 1, ProjectRoleRestrictionModel::RULE_TASK_CREATION));
|
||||||
|
$this->assertEquals(1, $columnRestrictionModel->create(1, 1, 1, ColumnRestrictionModel::RULE_ALLOW_TASK_CREATION));
|
||||||
|
|
||||||
|
$this->assertTrue($projectRoleHelper->canCreateTaskInColumn(1, 1));
|
||||||
|
$this->assertFalse($projectRoleHelper->canCreateTaskInColumn(1, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanChangeTaskStatusInColumnWithProjectViewer()
|
||||||
|
{
|
||||||
|
$projectRoleHelper = new ProjectRoleHelper($this->container);
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectUserRole = new ProjectUserRoleModel($this->container);
|
||||||
|
$userModel = new UserModel($this->container);
|
||||||
|
|
||||||
|
$this->container['sessionStorage']->user = array(
|
||||||
|
'id' => 2,
|
||||||
|
'role' => Role::APP_USER,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(2, $userModel->create(array('username' => 'user')));
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertTrue($projectUserRole->addUser(1, 2, Role::PROJECT_VIEWER));
|
||||||
|
|
||||||
|
$this->assertFalse($projectRoleHelper->canChangeTaskStatusInColumn(1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanChangeTaskStatusInColumnWithProjectMember()
|
||||||
|
{
|
||||||
|
$projectRoleHelper = new ProjectRoleHelper($this->container);
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectUserRole = new ProjectUserRoleModel($this->container);
|
||||||
|
$userModel = new UserModel($this->container);
|
||||||
|
|
||||||
|
$this->container['sessionStorage']->user = array(
|
||||||
|
'id' => 2,
|
||||||
|
'role' => Role::APP_USER,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(2, $userModel->create(array('username' => 'user')));
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertTrue($projectUserRole->addUser(1, 2, Role::PROJECT_MEMBER));
|
||||||
|
|
||||||
|
$this->assertTrue($projectRoleHelper->canChangeTaskStatusInColumn(1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanChangeTaskStatusInColumnWithCustomProjectRole()
|
||||||
|
{
|
||||||
|
$projectRoleHelper = new ProjectRoleHelper($this->container);
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectUserRole = new ProjectUserRoleModel($this->container);
|
||||||
|
$userModel = new UserModel($this->container);
|
||||||
|
$projectRoleModel = new ProjectRoleModel($this->container);
|
||||||
|
|
||||||
|
$this->container['sessionStorage']->user = array(
|
||||||
|
'id' => 2,
|
||||||
|
'role' => Role::APP_USER,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(2, $userModel->create(array('username' => 'user')));
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectRoleModel->create(1, 'Custom Role'));
|
||||||
|
$this->assertTrue($projectUserRole->addUser(1, 2, 'Custom Role'));
|
||||||
|
|
||||||
|
$this->assertTrue($projectRoleHelper->canChangeTaskStatusInColumn(1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanChangeTaskStatusInColumnWithCustomProjectRoleAndRestrictions()
|
||||||
|
{
|
||||||
|
$projectRoleHelper = new ProjectRoleHelper($this->container);
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectUserRole = new ProjectUserRoleModel($this->container);
|
||||||
|
$userModel = new UserModel($this->container);
|
||||||
|
$projectRoleModel = new ProjectRoleModel($this->container);
|
||||||
|
$projectRoleRestrictionModel = new ProjectRoleRestrictionModel($this->container);
|
||||||
|
$columnRestrictionModel = new ColumnRestrictionModel($this->container);
|
||||||
|
|
||||||
|
$this->container['sessionStorage']->user = array(
|
||||||
|
'id' => 2,
|
||||||
|
'role' => Role::APP_USER,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(2, $userModel->create(array('username' => 'user')));
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectRoleModel->create(1, 'Custom Role'));
|
||||||
|
$this->assertTrue($projectUserRole->addUser(1, 2, 'Custom Role'));
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectRoleRestrictionModel->create(1, 1, ProjectRoleRestrictionModel::RULE_TASK_OPEN_CLOSE));
|
||||||
|
$this->assertEquals(1, $columnRestrictionModel->create(1, 1, 1, ColumnRestrictionModel::RULE_ALLOW_TASK_OPEN_CLOSE));
|
||||||
|
|
||||||
|
$this->assertTrue($projectRoleHelper->canChangeTaskStatusInColumn(1, 1));
|
||||||
|
$this->assertFalse($projectRoleHelper->canChangeTaskStatusInColumn(1, 2));
|
||||||
|
}
|
||||||
|
|
||||||
public function testIsDraggableWithProjectMember()
|
public function testIsDraggableWithProjectMember()
|
||||||
{
|
{
|
||||||
$projectRoleHelper = new ProjectRoleHelper($this->container);
|
$projectRoleHelper = new ProjectRoleHelper($this->container);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Kanboard\Model\ColumnRestrictionModel;
|
||||||
|
use Kanboard\Model\ProjectModel;
|
||||||
|
use Kanboard\Model\ProjectRoleModel;
|
||||||
|
|
||||||
|
require_once __DIR__.'/../Base.php';
|
||||||
|
|
||||||
|
class ColumnRestrictionModelTest extends Base
|
||||||
|
{
|
||||||
|
public function testCreation()
|
||||||
|
{
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectRoleModel = new ProjectRoleModel($this->container);
|
||||||
|
$columnRestrictionModel = new ColumnRestrictionModel($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $projectRoleModel->create(1, 'my-custom-role'));
|
||||||
|
$this->assertEquals(1, $columnRestrictionModel->create(1, 1, 2, ColumnRestrictionModel::RULE_BLOCK_TASK_CREATION));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRemove()
|
||||||
|
{
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectRoleModel = new ProjectRoleModel($this->container);
|
||||||
|
$projectRoleRestrictionModel = new ColumnRestrictionModel($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $projectRoleModel->create(1, 'my-custom-role'));
|
||||||
|
$this->assertEquals(1, $projectRoleRestrictionModel->create(1, 1, 2, ColumnRestrictionModel::RULE_ALLOW_TASK_OPEN_CLOSE));
|
||||||
|
$this->assertTrue($projectRoleRestrictionModel->remove(1));
|
||||||
|
$this->assertFalse($projectRoleRestrictionModel->remove(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetById()
|
||||||
|
{
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectRoleModel = new ProjectRoleModel($this->container);
|
||||||
|
$projectRoleRestrictionModel = new ColumnRestrictionModel($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $projectRoleModel->create(1, 'my-custom-role'));
|
||||||
|
$this->assertEquals(1, $projectRoleRestrictionModel->create(1, 1, 2, ColumnRestrictionModel::RULE_ALLOW_TASK_CREATION));
|
||||||
|
|
||||||
|
$restriction = $projectRoleRestrictionModel->getById(1, 1);
|
||||||
|
$this->assertEquals(ColumnRestrictionModel::RULE_ALLOW_TASK_CREATION, $restriction['rule']);
|
||||||
|
$this->assertEquals(1, $restriction['project_id']);
|
||||||
|
$this->assertEquals(1, $restriction['restriction_id']);
|
||||||
|
$this->assertEquals('Ready', $restriction['column_title']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetAll()
|
||||||
|
{
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectRoleModel = new ProjectRoleModel($this->container);
|
||||||
|
$projectRoleRestrictionModel = new ColumnRestrictionModel($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $projectRoleModel->create(1, 'my-custom-role'));
|
||||||
|
$this->assertEquals(1, $projectRoleRestrictionModel->create(1, 1, 2, ColumnRestrictionModel::RULE_ALLOW_TASK_CREATION));
|
||||||
|
|
||||||
|
$restrictions = $projectRoleRestrictionModel->getAll(1);
|
||||||
|
$this->assertCount(1, $restrictions);
|
||||||
|
$this->assertEquals(ColumnRestrictionModel::RULE_ALLOW_TASK_CREATION, $restrictions[0]['rule']);
|
||||||
|
$this->assertEquals(1, $restrictions[0]['project_id']);
|
||||||
|
$this->assertEquals(1, $restrictions[0]['restriction_id']);
|
||||||
|
$this->assertEquals(1, $restrictions[0]['role_id']);
|
||||||
|
$this->assertEquals(2, $restrictions[0]['column_id']);
|
||||||
|
$this->assertEquals('Ready', $restrictions[0]['column_title']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetByRole()
|
||||||
|
{
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectRoleModel = new ProjectRoleModel($this->container);
|
||||||
|
$columnRestrictionModel = new ColumnRestrictionModel($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $projectRoleModel->create(1, 'my-custom-role'));
|
||||||
|
$this->assertEquals(1, $columnRestrictionModel->create(1, 1, 2, ColumnRestrictionModel::RULE_BLOCK_TASK_CREATION));
|
||||||
|
|
||||||
|
$restrictions = $columnRestrictionModel->getAllByRole(1, 'my-custom-role');
|
||||||
|
$this->assertCount(1, $restrictions);
|
||||||
|
$this->assertEquals(ColumnRestrictionModel::RULE_BLOCK_TASK_CREATION, $restrictions[0]['rule']);
|
||||||
|
$this->assertEquals(1, $restrictions[0]['project_id']);
|
||||||
|
$this->assertEquals(1, $restrictions[0]['restriction_id']);
|
||||||
|
$this->assertEquals(1, $restrictions[0]['role_id']);
|
||||||
|
$this->assertEquals(2, $restrictions[0]['column_id']);
|
||||||
|
$this->assertEquals('my-custom-role', $restrictions[0]['role']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetRules()
|
||||||
|
{
|
||||||
|
$columnRestrictionModel = new ColumnRestrictionModel($this->container);
|
||||||
|
$rules = $columnRestrictionModel->getRules();
|
||||||
|
|
||||||
|
$this->assertCount(4, $rules);
|
||||||
|
$this->assertArrayHasKey(ColumnRestrictionModel::RULE_ALLOW_TASK_CREATION, $rules);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,7 +11,7 @@ use Kanboard\Model\ProjectGroupRoleModel;
|
||||||
use Kanboard\Model\ProjectUserRoleModel;
|
use Kanboard\Model\ProjectUserRoleModel;
|
||||||
use Kanboard\Core\Security\Role;
|
use Kanboard\Core\Security\Role;
|
||||||
|
|
||||||
class ProjectPermissionTest extends Base
|
class ProjectPermissionModelTest extends Base
|
||||||
{
|
{
|
||||||
public function testFindByUsernames()
|
public function testFindByUsernames()
|
||||||
{
|
{
|
||||||
|
|
@ -41,14 +41,44 @@ class ProjectRoleModelTest extends Base
|
||||||
$this->assertEquals('Role B', $roles[1]['role']);
|
$this->assertEquals('Role B', $roles[1]['role']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testModification()
|
public function testModificationWithUserRole()
|
||||||
{
|
{
|
||||||
$projectModel = new ProjectModel($this->container);
|
$projectModel = new ProjectModel($this->container);
|
||||||
$projectRoleModel = new ProjectRoleModel($this->container);
|
$projectRoleModel = new ProjectRoleModel($this->container);
|
||||||
|
$projectUserRoleModel = new ProjectUserRoleModel($this->container);
|
||||||
|
$groupModel = new GroupModel($this->container);
|
||||||
|
$groupMemberModel = new GroupMemberModel($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $groupModel->create('Group A'));
|
||||||
|
$this->assertTrue($groupMemberModel->addUser(1, 1));
|
||||||
|
|
||||||
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
$this->assertEquals(1, $projectRoleModel->create(1, 'Role A'));
|
$this->assertEquals(1, $projectRoleModel->create(1, 'Role A'));
|
||||||
|
$this->assertTrue($projectUserRoleModel->addUser(1, 1, 'Role A'));
|
||||||
|
$this->assertEquals('Role A', $projectUserRoleModel->getUserRole(1, 1));
|
||||||
|
|
||||||
$this->assertTrue($projectRoleModel->update(1, 1, 'Role B'));
|
$this->assertTrue($projectRoleModel->update(1, 1, 'Role B'));
|
||||||
|
$this->assertEquals('Role B', $projectUserRoleModel->getUserRole(1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testModificationWithGroupRole()
|
||||||
|
{
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectRoleModel = new ProjectRoleModel($this->container);
|
||||||
|
$projectGroupRoleModel = new ProjectGroupRoleModel($this->container);
|
||||||
|
$groupModel = new GroupModel($this->container);
|
||||||
|
$groupMemberModel = new GroupMemberModel($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $groupModel->create('Group A'));
|
||||||
|
$this->assertTrue($groupMemberModel->addUser(1, 1));
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $projectRoleModel->create(1, 'Role A'));
|
||||||
|
$this->assertTrue($projectGroupRoleModel->addGroup(1, 1, 'Role A'));
|
||||||
|
$this->assertEquals('Role A', $projectGroupRoleModel->getUserRole(1, 1));
|
||||||
|
|
||||||
|
$this->assertTrue($projectRoleModel->update(1, 1, 'Role B'));
|
||||||
|
$this->assertEquals('Role B', $projectGroupRoleModel->getUserRole(1, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRemoveWithUserRole()
|
public function testRemoveWithUserRole()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Kanboard\Model\ProjectModel;
|
||||||
|
use Kanboard\Model\ProjectRoleModel;
|
||||||
|
use Kanboard\Model\ProjectRoleRestrictionModel;
|
||||||
|
|
||||||
|
require_once __DIR__.'/../Base.php';
|
||||||
|
|
||||||
|
class ProjectRoleRestrictionModelTest extends Base
|
||||||
|
{
|
||||||
|
public function testCreation()
|
||||||
|
{
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectRoleModel = new ProjectRoleModel($this->container);
|
||||||
|
$projectRoleRestrictionModel = new ProjectRoleRestrictionModel($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $projectRoleModel->create(1, 'my-custom-role'));
|
||||||
|
$this->assertEquals(1, $projectRoleRestrictionModel->create(1, 1, ProjectRoleRestrictionModel::RULE_TASK_CREATION));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRemove()
|
||||||
|
{
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectRoleModel = new ProjectRoleModel($this->container);
|
||||||
|
$projectRoleRestrictionModel = new ProjectRoleRestrictionModel($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $projectRoleModel->create(1, 'my-custom-role'));
|
||||||
|
$this->assertEquals(1, $projectRoleRestrictionModel->create(1, 1, ProjectRoleRestrictionModel::RULE_TASK_CREATION));
|
||||||
|
$this->assertTrue($projectRoleRestrictionModel->remove(1));
|
||||||
|
$this->assertFalse($projectRoleRestrictionModel->remove(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetById()
|
||||||
|
{
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectRoleModel = new ProjectRoleModel($this->container);
|
||||||
|
$projectRoleRestrictionModel = new ProjectRoleRestrictionModel($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $projectRoleModel->create(1, 'my-custom-role'));
|
||||||
|
$this->assertEquals(1, $projectRoleRestrictionModel->create(1, 1, ProjectRoleRestrictionModel::RULE_TASK_CREATION));
|
||||||
|
|
||||||
|
$restriction = $projectRoleRestrictionModel->getById(1, 1);
|
||||||
|
$this->assertEquals(ProjectRoleRestrictionModel::RULE_TASK_CREATION, $restriction['rule']);
|
||||||
|
$this->assertEquals(1, $restriction['project_id']);
|
||||||
|
$this->assertEquals(1, $restriction['restriction_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetAll()
|
||||||
|
{
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectRoleModel = new ProjectRoleModel($this->container);
|
||||||
|
$projectRoleRestrictionModel = new ProjectRoleRestrictionModel($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $projectRoleModel->create(1, 'my-custom-role'));
|
||||||
|
$this->assertEquals(1, $projectRoleRestrictionModel->create(1, 1, ProjectRoleRestrictionModel::RULE_TASK_CREATION));
|
||||||
|
|
||||||
|
$restrictions = $projectRoleRestrictionModel->getAll(1);
|
||||||
|
$this->assertCount(1, $restrictions);
|
||||||
|
$this->assertEquals(ProjectRoleRestrictionModel::RULE_TASK_CREATION, $restrictions[0]['rule']);
|
||||||
|
$this->assertEquals(1, $restrictions[0]['project_id']);
|
||||||
|
$this->assertEquals(1, $restrictions[0]['restriction_id']);
|
||||||
|
$this->assertEquals(1, $restrictions[0]['role_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetByRole()
|
||||||
|
{
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$projectRoleModel = new ProjectRoleModel($this->container);
|
||||||
|
$projectRoleRestrictionModel = new ProjectRoleRestrictionModel($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $projectRoleModel->create(1, 'my-custom-role'));
|
||||||
|
$this->assertEquals(1, $projectRoleRestrictionModel->create(1, 1, ProjectRoleRestrictionModel::RULE_TASK_CREATION));
|
||||||
|
|
||||||
|
$restrictions = $projectRoleRestrictionModel->getAllByRole(1, 'my-custom-role');
|
||||||
|
$this->assertCount(1, $restrictions);
|
||||||
|
$this->assertEquals(ProjectRoleRestrictionModel::RULE_TASK_CREATION, $restrictions[0]['rule']);
|
||||||
|
$this->assertEquals(1, $restrictions[0]['project_id']);
|
||||||
|
$this->assertEquals(1, $restrictions[0]['restriction_id']);
|
||||||
|
$this->assertEquals(1, $restrictions[0]['role_id']);
|
||||||
|
$this->assertEquals('my-custom-role', $restrictions[0]['role']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetRules()
|
||||||
|
{
|
||||||
|
$projectRoleRestrictionModel = new ProjectRoleRestrictionModel($this->container);
|
||||||
|
$rules = $projectRoleRestrictionModel->getRules();
|
||||||
|
|
||||||
|
$this->assertCount(2, $rules);
|
||||||
|
$this->assertArrayHasKey(ProjectRoleRestrictionModel::RULE_TASK_OPEN_CLOSE, $rules);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -89,6 +89,7 @@ class TaskFinderModelTest extends Base
|
||||||
$tasks = $taskFinderModel->getUserQuery(1)->findAll();
|
$tasks = $taskFinderModel->getUserQuery(1)->findAll();
|
||||||
$this->assertCount(1, $tasks);
|
$this->assertCount(1, $tasks);
|
||||||
$this->assertEquals('Task #1', $tasks[0]['title']);
|
$this->assertEquals('Task #1', $tasks[0]['title']);
|
||||||
|
$this->assertEquals(1, $tasks[0]['column_id']);
|
||||||
|
|
||||||
$this->assertTrue($columnModel->update(2, 'Test', 0, '', 0));
|
$this->assertTrue($columnModel->update(2, 'Test', 0, '', 0));
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue