From 3043163747b13ce1942b2e55977cf7c5417021de Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 18 Sep 2016 21:19:48 -0400 Subject: Add column restrictions to custom project roles --- app/Controller/ColumnRestrictionController.php | 103 +++++++ app/Controller/TaskCreationController.php | 12 +- app/Controller/TaskMovePositionController.php | 1 + app/Core/Base.php | 4 + .../ColumnMoveRestrictionCacheDecorator.php | 3 +- app/Decorator/ColumnRestrictionCacheDecorator.php | 59 ++++ .../ProjectRoleRestrictionCacheDecorator.php | 59 ++++ app/Helper/ProjectRoleHelper.php | 112 ++++++- app/Model/ColumnRestrictionModel.php | 152 ++++++++++ app/Model/ProjectPermissionModel.php | 9 +- app/Model/ProjectRoleModel.php | 36 ++- app/Model/ProjectRoleRestrictionModel.php | 44 +-- app/Model/ProjectUserRoleModel.php | 2 +- app/Model/TaskFinderModel.php | 1 + app/Schema/Mysql.php | 20 +- app/Schema/Postgres.php | 19 +- app/Schema/Sqlite.php | 19 +- app/ServiceProvider/CacheProvider.php | 16 + app/ServiceProvider/ClassProvider.php | 2 + app/Template/board/table_column.php | 2 +- app/Template/column_move_restriction/create.php | 2 +- app/Template/column_restriction/create.php | 22 ++ app/Template/column_restriction/remove.php | 14 + app/Template/project_role/show.php | 34 ++- app/Template/task/dropdown.php | 2 +- app/Template/task/sidebar.php | 2 +- app/Validator/ColumnRestrictionValidator.php | 40 +++ tests/units/Helper/ProjectRoleHelperTest.php | 178 +++++++++++ tests/units/Model/ColumnRestrictionModelTest.php | 100 +++++++ tests/units/Model/ProjectPermissionModelTest.php | 332 +++++++++++++++++++++ tests/units/Model/ProjectPermissionTest.php | 332 --------------------- tests/units/Model/ProjectRoleModelTest.php | 32 +- .../Model/ProjectRoleRestrictionModelTest.php | 96 ++++++ tests/units/Model/TaskFinderModelTest.php | 1 + 34 files changed, 1463 insertions(+), 399 deletions(-) create mode 100644 app/Controller/ColumnRestrictionController.php create mode 100644 app/Decorator/ColumnRestrictionCacheDecorator.php create mode 100644 app/Decorator/ProjectRoleRestrictionCacheDecorator.php create mode 100644 app/Model/ColumnRestrictionModel.php create mode 100644 app/Template/column_restriction/create.php create mode 100644 app/Template/column_restriction/remove.php create mode 100644 app/Validator/ColumnRestrictionValidator.php create mode 100644 tests/units/Model/ColumnRestrictionModelTest.php create mode 100644 tests/units/Model/ProjectPermissionModelTest.php delete mode 100644 tests/units/Model/ProjectPermissionTest.php create mode 100644 tests/units/Model/ProjectRoleRestrictionModelTest.php diff --git a/app/Controller/ColumnRestrictionController.php b/app/Controller/ColumnRestrictionController.php new file mode 100644 index 00000000..ce2a1ca8 --- /dev/null +++ b/app/Controller/ColumnRestrictionController.php @@ -0,0 +1,103 @@ +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']))); + } +} diff --git a/app/Controller/TaskCreationController.php b/app/Controller/TaskCreationController.php index c68964f6..c754b029 100644 --- a/app/Controller/TaskCreationController.php +++ b/app/Controller/TaskCreationController.php @@ -52,12 +52,16 @@ class TaskCreationController extends BaseController list($valid, $errors) = $this->taskValidator->validateCreation($values); - if ($valid && ($task_id = $this->taskCreationModel->create($values))) { - $this->flash->success(t('Task created successfully.')); - $this->afterSave($project, $values, $task_id); - } else { + if (! $valid) { $this->flash->failure(t('Unable to create your task.')); $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); } } diff --git a/app/Controller/TaskMovePositionController.php b/app/Controller/TaskMovePositionController.php index c6e8be0c..1a8eee45 100644 --- a/app/Controller/TaskMovePositionController.php +++ b/app/Controller/TaskMovePositionController.php @@ -2,6 +2,7 @@ namespace Kanboard\Controller; +use Kanboard\Core\Controller\AccessForbiddenException; use Kanboard\Formatter\BoardFormatter; /** diff --git a/app/Core/Base.php b/app/Core/Base.php index d6da13f2..44dfaa39 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -57,7 +57,9 @@ use Pimple\Container; * @property \Kanboard\Core\Paginator $paginator * @property \Kanboard\Core\Template $template * @property \Kanboard\Decorator\MetadataCacheDecorator $userMetadataCacheDecorator + * @property \Kanboard\Decorator\columnRestrictionCacheDecorator $columnRestrictionCacheDecorator * @property \Kanboard\Decorator\ColumnMoveRestrictionCacheDecorator $columnMoveRestrictionCacheDecorator + * @property \Kanboard\Decorator\ProjectRoleRestrictionCacheDecorator $projectRoleRestrictionCacheDecorator * @property \Kanboard\Model\ActionModel $actionModel * @property \Kanboard\Model\ActionParameterModel $actionParameterModel * @property \Kanboard\Model\AvatarFileModel $avatarFileModel @@ -65,6 +67,7 @@ use Pimple\Container; * @property \Kanboard\Model\CategoryModel $categoryModel * @property \Kanboard\Model\ColorModel $colorModel * @property \Kanboard\Model\ColumnModel $columnModel + * @property \Kanboard\Model\ColumnRestrictionModel $columnRestrictionModel * @property \Kanboard\Model\ColumnMoveRestrictionModel $columnMoveRestrictionModel * @property \Kanboard\Model\CommentModel $commentModel * @property \Kanboard\Model\ConfigModel $configModel @@ -136,6 +139,7 @@ use Pimple\Container; * @property \Kanboard\Validator\AuthValidator $authValidator * @property \Kanboard\Validator\ColumnValidator $columnValidator * @property \Kanboard\Validator\CategoryValidator $categoryValidator + * @property \Kanboard\Validator\ColumnRestrictionValidator $columnRestrictionValidator * @property \Kanboard\Validator\ColumnMoveRestrictionValidator $columnMoveRestrictionValidator * @property \Kanboard\Validator\CommentValidator $commentValidator * @property \Kanboard\Validator\CurrencyValidator $currencyValidator diff --git a/app/Decorator/ColumnMoveRestrictionCacheDecorator.php b/app/Decorator/ColumnMoveRestrictionCacheDecorator.php index 2a3e9c2a..82140d16 100644 --- a/app/Decorator/ColumnMoveRestrictionCacheDecorator.php +++ b/app/Decorator/ColumnMoveRestrictionCacheDecorator.php @@ -40,7 +40,8 @@ class ColumnMoveRestrictionCacheDecorator /** * Proxy method to get sortable columns * - * @param int $project_id + * @param int $project_id + * @param string $role * @return array|mixed */ public function getSortableColumns($project_id, $role) diff --git a/app/Decorator/ColumnRestrictionCacheDecorator.php b/app/Decorator/ColumnRestrictionCacheDecorator.php new file mode 100644 index 00000000..a615030d --- /dev/null +++ b/app/Decorator/ColumnRestrictionCacheDecorator.php @@ -0,0 +1,59 @@ +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; + } +} diff --git a/app/Decorator/ProjectRoleRestrictionCacheDecorator.php b/app/Decorator/ProjectRoleRestrictionCacheDecorator.php new file mode 100644 index 00000000..a6e24048 --- /dev/null +++ b/app/Decorator/ProjectRoleRestrictionCacheDecorator.php @@ -0,0 +1,59 @@ +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; + } +} diff --git a/app/Helper/ProjectRoleHelper.php b/app/Helper/ProjectRoleHelper.php index 99fa82bc..e1808be5 100644 --- a/app/Helper/ProjectRoleHelper.php +++ b/app/Helper/ProjectRoleHelper.php @@ -4,6 +4,8 @@ namespace Kanboard\Helper; use Kanboard\Core\Base; use Kanboard\Core\Security\Role; +use Kanboard\Model\ColumnRestrictionModel; +use Kanboard\Model\ProjectRoleRestrictionModel; /** * Class ProjectRoleHelper @@ -98,6 +100,46 @@ class ProjectRoleHelper extends Base 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 * @@ -145,13 +187,77 @@ class ProjectRoleHelper extends Base $role = $this->getProjectUserRole($project_id); if ($this->role->isCustomProjectRole($role)) { - $restrictions = $this->projectRoleRestrictionModel->getAllByRole($project_id, $role); - $result = $this->projectRoleRestrictionModel->isAllowed($restrictions, $controller, $action); - $result = $result && $this->projectAuthorization->isAllowed($controller, $action, Role::PROJECT_MEMBER); + $result = $this->projectAuthorization->isAllowed($controller, $action, Role::PROJECT_MEMBER); } else { $result = $this->projectAuthorization->isAllowed($controller, $action, $role); } 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; + } } diff --git a/app/Model/ColumnRestrictionModel.php b/app/Model/ColumnRestrictionModel.php new file mode 100644 index 00000000..92b2ac60 --- /dev/null +++ b/app/Model/ColumnRestrictionModel.php @@ -0,0 +1,152 @@ + 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(); + } +} diff --git a/app/Model/ProjectPermissionModel.php b/app/Model/ProjectPermissionModel.php index 4882343d..25b6a382 100644 --- a/app/Model/ProjectPermissionModel.php +++ b/app/Model/ProjectPermissionModel.php @@ -122,8 +122,13 @@ class ProjectPermissionModel extends Base */ public function isAssignable($project_id, $user_id) { - return $this->userModel->isActive($user_id) && - in_array($this->projectUserRoleModel->getUserRole($project_id, $user_id), array(Role::PROJECT_MEMBER, Role::PROJECT_MANAGER)); + if ($this->userModel->isActive($user_id)) { + $role = $this->projectUserRoleModel->getUserRole($project_id, $user_id); + + return ! empty($role) && $role !== Role::PROJECT_VIEWER; + } + + return false; } /** diff --git a/app/Model/ProjectRoleModel.php b/app/Model/ProjectRoleModel.php index ed86d6ed..962ff44f 100644 --- a/app/Model/ProjectRoleModel.php +++ b/app/Model/ProjectRoleModel.php @@ -71,10 +71,14 @@ class ProjectRoleModel extends Base { $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'); 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 = array_column_index($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) { - 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) ->eq('role_id', $role_id) ->eq('project_id', $project_id) ->update(array( 'role' => $role, )); + + if ($r1 && $r2 && $r3) { + $this->db->closeTransaction(); + return true; + } + + $this->db->cancelTransaction(); + return false; } /** diff --git a/app/Model/ProjectRoleRestrictionModel.php b/app/Model/ProjectRoleRestrictionModel.php index 7679f650..dc8abf79 100644 --- a/app/Model/ProjectRoleRestrictionModel.php +++ b/app/Model/ProjectRoleRestrictionModel.php @@ -17,15 +17,6 @@ class ProjectRoleRestrictionModel extends Base const RULE_TASK_CREATION = 'task_creation'; 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 * @@ -91,7 +82,7 @@ class ProjectRoleRestrictionModel extends Base */ public function getAllByRole($project_id, $role) { - $rules = $this->db + return $this->db ->table(self::TABLE) ->columns( self::TABLE.'.restriction_id', @@ -104,12 +95,6 @@ class ProjectRoleRestrictionModel extends Base ->eq('role', $role) ->left(ProjectRoleModel::TABLE, 'pr', 'role_id', self::TABLE, 'role_id') ->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(); } - - /** - * 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; - } } diff --git a/app/Model/ProjectUserRoleModel.php b/app/Model/ProjectUserRoleModel.php index a0df0cfa..76094431 100644 --- a/app/Model/ProjectUserRoleModel.php +++ b/app/Model/ProjectUserRoleModel.php @@ -166,7 +166,7 @@ class ProjectUserRoleModel extends Base ->join(UserModel::TABLE, 'id', 'user_id') ->eq(UserModel::TABLE.'.is_active', 1) ->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(); $groupMembers = $this->projectGroupRoleModel->getAssignableUsers($project_id); diff --git a/app/Model/TaskFinderModel.php b/app/Model/TaskFinderModel.php index 3c32e140..3185afb7 100644 --- a/app/Model/TaskFinderModel.php +++ b/app/Model/TaskFinderModel.php @@ -67,6 +67,7 @@ class TaskFinderModel extends Base TaskModel::TABLE.'.date_due', TaskModel::TABLE.'.date_creation', TaskModel::TABLE.'.project_id', + TaskModel::TABLE.'.column_id', TaskModel::TABLE.'.color_id', TaskModel::TABLE.'.priority', TaskModel::TABLE.'.time_spent', diff --git a/app/Schema/Mysql.php b/app/Schema/Mysql.php index 398b963e..274ce8c8 100644 --- a/app/Schema/Mysql.php +++ b/app/Schema/Mysql.php @@ -6,7 +6,25 @@ use PDO; use Kanboard\Core\Security\Token; 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) { diff --git a/app/Schema/Postgres.php b/app/Schema/Postgres.php index 56cd9de9..213d9869 100644 --- a/app/Schema/Postgres.php +++ b/app/Schema/Postgres.php @@ -6,7 +6,24 @@ use PDO; use Kanboard\Core\Security\Token; 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) { diff --git a/app/Schema/Sqlite.php b/app/Schema/Sqlite.php index c952d58f..f86a6af0 100644 --- a/app/Schema/Sqlite.php +++ b/app/Schema/Sqlite.php @@ -6,7 +6,24 @@ use Kanboard\Core\Security\Token; use Kanboard\Core\Security\Role; 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) { diff --git a/app/ServiceProvider/CacheProvider.php b/app/ServiceProvider/CacheProvider.php index 90d63f81..e93dd502 100644 --- a/app/ServiceProvider/CacheProvider.php +++ b/app/ServiceProvider/CacheProvider.php @@ -5,7 +5,9 @@ namespace Kanboard\ServiceProvider; use Kanboard\Core\Cache\FileCache; use Kanboard\Core\Cache\MemoryCache; use Kanboard\Decorator\ColumnMoveRestrictionCacheDecorator; +use Kanboard\Decorator\ColumnRestrictionCacheDecorator; use Kanboard\Decorator\MetadataCacheDecorator; +use Kanboard\Decorator\ProjectRoleRestrictionCacheDecorator; use Pimple\Container; 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; } } diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index 4841d1f0..c5bf0678 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -34,6 +34,7 @@ class ClassProvider implements ServiceProviderInterface 'CategoryModel', 'ColorModel', 'ColumnModel', + 'ColumnRestrictionModel', 'ColumnMoveRestrictionModel', 'CommentModel', 'ConfigModel', @@ -101,6 +102,7 @@ class ClassProvider implements ServiceProviderInterface 'AuthValidator', 'CategoryValidator', 'ColumnMoveRestrictionValidator', + 'ColumnRestrictionValidator', 'ColumnValidator', 'CommentValidator', 'CurrencyValidator', diff --git a/app/Template/board/table_column.php b/app/Template/board/table_column.php index c0b71eab..3daa8aed 100644 --- a/app/Template/board/table_column.php +++ b/app/Template/board/table_column.php @@ -12,7 +12,7 @@
- user->hasProjectAccess('TaskCreationController', 'show', $column['project_id'])): ?> + projectRole->canCreateTaskInColumn($column['project_id'], $column['id'])): ?>
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')) ?>
diff --git a/app/Template/column_move_restriction/create.php b/app/Template/column_move_restriction/create.php index 8d161c3e..1eb6d539 100644 --- a/app/Template/column_move_restriction/create.php +++ b/app/Template/column_move_restriction/create.php @@ -1,6 +1,6 @@
form->csrf() ?> diff --git a/app/Template/column_restriction/create.php b/app/Template/column_restriction/create.php new file mode 100644 index 00000000..982733b4 --- /dev/null +++ b/app/Template/column_restriction/create.php @@ -0,0 +1,22 @@ +
+ + + form->csrf() ?> + form->hidden('project_id', $values) ?> + form->hidden('role_id', $values) ?> + + form->label(t('Rule'), 'rule') ?> + form->select('rule', $rules, $values, $errors) ?> + + form->label(t('Column'), 'column_id') ?> + form->select('column_id', $columns, $values, $errors) ?> + +
+ + + url->link(t('cancel'), 'ProjectRoleController', 'show', array(), false, 'close-popover') ?> +
+ +
diff --git a/app/Template/column_restriction/remove.php b/app/Template/column_restriction/remove.php new file mode 100644 index 00000000..97650e2d --- /dev/null +++ b/app/Template/column_restriction/remove.php @@ -0,0 +1,14 @@ + + +
+

+ +

+ +
+ url->link(t('Yes'), 'ColumnRestrictionController', 'remove', array('project_id' => $project['id'], 'restriction_id' => $restriction['restriction_id']), true, 'btn btn-red') ?> + url->link(t('cancel'), 'ProjectRoleController', 'show', array('project_id' => $project['id']), false, 'close-popover') ?> +
+
diff --git a/app/Template/project_role/show.php b/app/Template/project_role/show.php index 81281a3e..59200fc9 100644 --- a/app/Template/project_role/show.php +++ b/app/Template/project_role/show.php @@ -24,7 +24,11 @@
  • - url->link(t('Add a new column restriction'), 'ColumnMoveRestrictionController', 'create', array('project_id' => $project['id'], 'role_id' => $role['role_id']), false, 'popover') ?> + url->link(t('Add a new drag and drop restriction'), 'ColumnMoveRestrictionController', 'create', array('project_id' => $project['id'], 'role_id' => $role['role_id']), false, 'popover') ?> +
  • +
  • + + url->link(t('Add a new column restriction'), 'ColumnRestrictionController', 'create', array('project_id' => $project['id'], 'role_id' => $role['role_id']), false, 'popover') ?>
  • @@ -41,7 +45,7 @@ - + @@ -49,6 +53,9 @@ + + + text->e($restriction['title']) ?> @@ -60,7 +67,28 @@ - + + + + + + text->e($restriction['column_title']) ?> + + text->e($restriction['title']) ?> + + + + url->link(t('Remove'), 'ColumnRestrictionController', 'confirm', array('project_id' => $project['id'], 'restriction_id' => $restriction['restriction_id']), false, 'popover') ?> + + + + + + + + text->e($restriction['src_column_title']) ?> / text->e($restriction['dst_column_title']) ?> + + diff --git a/app/Template/task/dropdown.php b/app/Template/task/dropdown.php index 127fc89c..f2423dd8 100644 --- a/app/Template/task/dropdown.php +++ b/app/Template/task/dropdown.php @@ -49,7 +49,7 @@ url->link(t('Remove'), 'TaskSuppressionController', 'confirm', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'popover') ?>
  • - user->hasProjectAccess('TaskStatusController', 'close', $task['project_id'])): ?> + projectRole->canChangeTaskStatusInColumn($task['project_id'], $task['column_id'])): ?>
  • diff --git a/app/Template/task/sidebar.php b/app/Template/task/sidebar.php index 87fe8cee..640423f4 100644 --- a/app/Template/task/sidebar.php +++ b/app/Template/task/sidebar.php @@ -78,7 +78,7 @@ url->link(t('Move to another project'), 'TaskDuplicationController', 'move', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'popover') ?>
  • - user->hasProjectAccess('TaskStatusController', 'close', $task['project_id'])): ?> + projectRole->canChangeTaskStatusInColumn($task['project_id'], $task['column_id'])): ?>
  • diff --git a/app/Validator/ColumnRestrictionValidator.php b/app/Validator/ColumnRestrictionValidator.php new file mode 100644 index 00000000..b1b2e5a0 --- /dev/null +++ b/app/Validator/ColumnRestrictionValidator.php @@ -0,0 +1,40 @@ +execute(), + $v->getErrors() + ); + } +} diff --git a/tests/units/Helper/ProjectRoleHelperTest.php b/tests/units/Helper/ProjectRoleHelperTest.php index cae22d71..4583d58e 100644 --- a/tests/units/Helper/ProjectRoleHelperTest.php +++ b/tests/units/Helper/ProjectRoleHelperTest.php @@ -4,8 +4,10 @@ use Kanboard\Core\Security\Role; use Kanboard\Core\User\UserSession; use Kanboard\Helper\ProjectRoleHelper; use Kanboard\Model\ColumnMoveRestrictionModel; +use Kanboard\Model\ColumnRestrictionModel; use Kanboard\Model\ProjectModel; use Kanboard\Model\ProjectRoleModel; +use Kanboard\Model\ProjectRoleRestrictionModel; use Kanboard\Model\ProjectUserRoleModel; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; @@ -16,6 +18,182 @@ require_once __DIR__.'/../Base.php'; 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() { $projectRoleHelper = new ProjectRoleHelper($this->container); diff --git a/tests/units/Model/ColumnRestrictionModelTest.php b/tests/units/Model/ColumnRestrictionModelTest.php new file mode 100644 index 00000000..6f66c258 --- /dev/null +++ b/tests/units/Model/ColumnRestrictionModelTest.php @@ -0,0 +1,100 @@ +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); + } +} diff --git a/tests/units/Model/ProjectPermissionModelTest.php b/tests/units/Model/ProjectPermissionModelTest.php new file mode 100644 index 00000000..3313cf2d --- /dev/null +++ b/tests/units/Model/ProjectPermissionModelTest.php @@ -0,0 +1,332 @@ +container); + $projectModel = new ProjectModel($this->container); + $groupModel = new GroupModel($this->container); + $groupMemberModel = new GroupMemberModel($this->container); + $groupRoleModel = new ProjectGroupRoleModel($this->container); + $userRoleModel = new ProjectUserRoleModel($this->container); + $projectPermissionModel = new ProjectPermissionModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); + + $this->assertEquals(2, $userModel->create(array('username' => 'user1'))); + $this->assertEquals(3, $userModel->create(array('username' => 'user2'))); + $this->assertEquals(4, $userModel->create(array('username' => 'user3'))); + + $this->assertEquals(1, $groupModel->create('Group A')); + $this->assertTrue($groupMemberModel->addUser(1, 2)); + + $this->assertTrue($groupRoleModel->addGroup(1, 1, Role::PROJECT_MEMBER)); + $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MANAGER)); + + $this->assertEquals(array('user1', 'user2'), $projectPermissionModel->findUsernames(1, 'us')); + $this->assertEmpty($projectPermissionModel->findUsernames(1, 'a')); + $this->assertEmpty($projectPermissionModel->findUsernames(2, 'user')); + } + + public function testGetQueryByRole() + { + $userModel = new UserModel($this->container); + $projectModel = new ProjectModel($this->container); + $userRoleModel = new ProjectUserRoleModel($this->container); + $projectPermission = new ProjectPermissionModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'Project 2'))); + $this->assertEquals(3, $projectModel->create(array('name' => 'Project 3'))); + + $this->assertEquals(2, $userModel->create(array('username' => 'user 1'))); + $this->assertEquals(3, $userModel->create(array('username' => 'user 2'))); + $this->assertEquals(4, $userModel->create(array('username' => 'user 3'))); + $this->assertEquals(5, $userModel->create(array('username' => 'user 4'))); + + $this->assertTrue($userRoleModel->addUser(1, 2, Role::PROJECT_MANAGER)); + $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MANAGER)); + $this->assertTrue($userRoleModel->addUser(1, 4, Role::PROJECT_MEMBER)); + $this->assertTrue($userRoleModel->addUser(1, 5, Role::PROJECT_MEMBER)); + + $this->assertTrue($userRoleModel->addUser(2, 2, Role::PROJECT_MEMBER)); + $this->assertTrue($userRoleModel->addUser(2, 3, Role::PROJECT_MEMBER)); + $this->assertTrue($userRoleModel->addUser(2, 5, Role::PROJECT_MANAGER)); + + $this->assertTrue($userRoleModel->addUser(3, 4, Role::PROJECT_MANAGER)); + $this->assertTrue($userRoleModel->addUser(3, 5, Role::PROJECT_VIEWER)); + + $this->assertEmpty($projectPermission->getQueryByRole(array(), Role::PROJECT_MANAGER)->findAll()); + + $users = $projectPermission->getQueryByRole(array(1, 2), Role::PROJECT_MANAGER)->findAll(); + $this->assertCount(3, $users); + $this->assertEquals('user 1', $users[0]['username']); + $this->assertEquals('Project 1', $users[0]['project_name']); + $this->assertEquals('user 2', $users[1]['username']); + $this->assertEquals('Project 1', $users[1]['project_name']); + $this->assertEquals('user 4', $users[2]['username']); + $this->assertEquals('Project 2', $users[2]['project_name']); + + $users = $projectPermission->getQueryByRole(array(1), Role::PROJECT_MANAGER)->findAll(); + $this->assertCount(2, $users); + $this->assertEquals('user 1', $users[0]['username']); + $this->assertEquals('Project 1', $users[0]['project_name']); + $this->assertEquals('user 2', $users[1]['username']); + $this->assertEquals('Project 1', $users[1]['project_name']); + + $users = $projectPermission->getQueryByRole(array(1, 2, 3), Role::PROJECT_MEMBER)->findAll(); + $this->assertCount(4, $users); + $this->assertEquals('user 3', $users[0]['username']); + $this->assertEquals('Project 1', $users[0]['project_name']); + $this->assertEquals('user 4', $users[1]['username']); + $this->assertEquals('Project 1', $users[1]['project_name']); + $this->assertEquals('user 1', $users[2]['username']); + $this->assertEquals('Project 2', $users[2]['project_name']); + $this->assertEquals('user 2', $users[3]['username']); + $this->assertEquals('Project 2', $users[3]['project_name']); + + $users = $projectPermission->getQueryByRole(array(1, 2, 3), Role::PROJECT_VIEWER)->findAll(); + $this->assertCount(1, $users); + $this->assertEquals('user 4', $users[0]['username']); + $this->assertEquals('Project 3', $users[0]['project_name']); + } + + public function testEverybodyAllowed() + { + $projectModel = new ProjectModel($this->container); + $projectPermission = new ProjectPermissionModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'Project 2', 'is_everybody_allowed' => 1))); + + $this->assertFalse($projectPermission->isEverybodyAllowed(1)); + $this->assertTrue($projectPermission->isEverybodyAllowed(2)); + } + + public function testIsUserAllowed() + { + $userModel = new UserModel($this->container); + $projectModel = new ProjectModel($this->container); + $groupModel = new GroupModel($this->container); + $groupRoleModel = new ProjectGroupRoleModel($this->container); + $groupMemberModel = new GroupMemberModel($this->container); + $userRoleModel = new ProjectUserRoleModel($this->container); + $projectPermission = new ProjectPermissionModel($this->container); + + $this->assertEquals(2, $userModel->create(array('username' => 'user 1'))); + $this->assertEquals(3, $userModel->create(array('username' => 'user 2'))); + $this->assertEquals(4, $userModel->create(array('username' => 'user 3'))); + $this->assertEquals(5, $userModel->create(array('username' => 'user 4'))); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'Project 2'))); + + $this->assertEquals(1, $groupModel->create('Group A')); + + $this->assertTrue($groupMemberModel->addUser(1, 2)); + $this->assertTrue($groupRoleModel->addGroup(1, 1, Role::PROJECT_VIEWER)); + + $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MEMBER)); + $this->assertTrue($userRoleModel->addUser(1, 4, Role::PROJECT_MANAGER)); + + $this->assertTrue($projectPermission->isUserAllowed(1, 2)); + $this->assertTrue($projectPermission->isUserAllowed(1, 3)); + $this->assertTrue($projectPermission->isUserAllowed(1, 4)); + $this->assertFalse($projectPermission->isUserAllowed(1, 5)); + + $this->assertFalse($projectPermission->isUserAllowed(2, 2)); + $this->assertFalse($projectPermission->isUserAllowed(2, 3)); + $this->assertFalse($projectPermission->isUserAllowed(2, 4)); + $this->assertFalse($projectPermission->isUserAllowed(2, 5)); + } + + public function testIsAssignable() + { + $userModel = new UserModel($this->container); + $projectModel = new ProjectModel($this->container); + $groupModel = new GroupModel($this->container); + $groupRoleModel = new ProjectGroupRoleModel($this->container); + $groupMemberModel = new GroupMemberModel($this->container); + $userRoleModel = new ProjectUserRoleModel($this->container); + $projectPermission = new ProjectPermissionModel($this->container); + + $this->assertEquals(2, $userModel->create(array('username' => 'user 1'))); + $this->assertEquals(3, $userModel->create(array('username' => 'user 2'))); + $this->assertEquals(4, $userModel->create(array('username' => 'user 3'))); + $this->assertEquals(5, $userModel->create(array('username' => 'user 4'))); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'Project 2'))); + + $this->assertEquals(1, $groupModel->create('Group A')); + + $this->assertTrue($groupMemberModel->addUser(1, 2)); + $this->assertTrue($groupRoleModel->addGroup(1, 1, Role::PROJECT_VIEWER)); + + $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MEMBER)); + $this->assertTrue($userRoleModel->addUser(1, 4, Role::PROJECT_MANAGER)); + + $this->assertFalse($projectPermission->isAssignable(1, 2)); + $this->assertTrue($projectPermission->isAssignable(1, 3)); + $this->assertTrue($projectPermission->isAssignable(1, 4)); + $this->assertFalse($projectPermission->isAssignable(1, 5)); + + $this->assertFalse($projectPermission->isAssignable(2, 2)); + $this->assertFalse($projectPermission->isAssignable(2, 3)); + $this->assertFalse($projectPermission->isAssignable(2, 4)); + $this->assertFalse($projectPermission->isAssignable(2, 5)); + } + + public function testIsAssignableWhenUserIsDisabled() + { + $userModel = new UserModel($this->container); + $projectModel = new ProjectModel($this->container); + $userRoleModel = new ProjectUserRoleModel($this->container); + $projectPermission = new ProjectPermissionModel($this->container); + + $this->assertEquals(2, $userModel->create(array('username' => 'user 1'))); + $this->assertEquals(3, $userModel->create(array('username' => 'user 2', 'is_active' => 0))); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); + + $this->assertTrue($userRoleModel->addUser(1, 2, Role::PROJECT_MEMBER)); + $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MEMBER)); + + $this->assertTrue($projectPermission->isAssignable(1, 2)); + $this->assertFalse($projectPermission->isAssignable(1, 3)); + } + + public function testIsMember() + { + $userModel = new UserModel($this->container); + $projectModel = new ProjectModel($this->container); + $groupModel = new GroupModel($this->container); + $groupRoleModel = new ProjectGroupRoleModel($this->container); + $groupMemberModel = new GroupMemberModel($this->container); + $userRoleModel = new ProjectUserRoleModel($this->container); + $projectPermission = new ProjectPermissionModel($this->container); + + $this->assertEquals(2, $userModel->create(array('username' => 'user 1'))); + $this->assertEquals(3, $userModel->create(array('username' => 'user 2'))); + $this->assertEquals(4, $userModel->create(array('username' => 'user 3'))); + $this->assertEquals(5, $userModel->create(array('username' => 'user 4'))); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'Project 2'))); + + $this->assertEquals(1, $groupModel->create('Group A')); + + $this->assertTrue($groupMemberModel->addUser(1, 2)); + $this->assertTrue($groupRoleModel->addGroup(1, 1, Role::PROJECT_VIEWER)); + + $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MEMBER)); + $this->assertTrue($userRoleModel->addUser(1, 4, Role::PROJECT_MANAGER)); + + $this->assertTrue($projectPermission->isMember(1, 2)); + $this->assertTrue($projectPermission->isMember(1, 3)); + $this->assertTrue($projectPermission->isMember(1, 4)); + $this->assertFalse($projectPermission->isMember(1, 5)); + + $this->assertFalse($projectPermission->isMember(2, 2)); + $this->assertFalse($projectPermission->isMember(2, 3)); + $this->assertFalse($projectPermission->isMember(2, 4)); + $this->assertFalse($projectPermission->isMember(2, 5)); + } + + public function testGetActiveProjectIds() + { + $userModel = new UserModel($this->container); + $projectModel = new ProjectModel($this->container); + $userRoleModel = new ProjectUserRoleModel($this->container); + $projectPermission = new ProjectPermissionModel($this->container); + + $this->assertEquals(2, $userModel->create(array('username' => 'user 1'))); + $this->assertEquals(3, $userModel->create(array('username' => 'user 2'))); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'Project 2', 'is_active' => 0))); + + $this->assertTrue($userRoleModel->addUser(1, 2, Role::PROJECT_MEMBER)); + $this->assertTrue($userRoleModel->addUser(2, 2, Role::PROJECT_VIEWER)); + $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_VIEWER)); + + $this->assertEmpty($projectPermission->getActiveProjectIds(1)); + $this->assertEquals(array(1), $projectPermission->getActiveProjectIds(2)); + $this->assertEquals(array(1), $projectPermission->getActiveProjectIds(3)); + } + + public function testGetProjectIds() + { + $userModel = new UserModel($this->container); + $projectModel = new ProjectModel($this->container); + $userRoleModel = new ProjectUserRoleModel($this->container); + $projectPermission = new ProjectPermissionModel($this->container); + + $this->assertEquals(2, $userModel->create(array('username' => 'user 1'))); + $this->assertEquals(3, $userModel->create(array('username' => 'user 2'))); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'Project 2', 'is_active' => 0))); + + $this->assertTrue($userRoleModel->addUser(1, 2, Role::PROJECT_MEMBER)); + $this->assertTrue($userRoleModel->addUser(2, 2, Role::PROJECT_MEMBER)); + $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MEMBER)); + $this->assertTrue($userRoleModel->addUser(2, 3, Role::PROJECT_MEMBER)); + + $this->assertEmpty($projectPermission->getProjectIds(1)); + $this->assertEquals(array(1, 2), $projectPermission->getProjectIds(2)); + $this->assertEquals(array(1, 2), $projectPermission->getProjectIds(3)); + } + + public function testDuplicate() + { + $userModel = new UserModel($this->container); + $projectModel = new ProjectModel($this->container); + $groupModel = new GroupModel($this->container); + $groupMemberModel = new GroupMemberModel($this->container); + $groupRoleModel = new ProjectGroupRoleModel($this->container); + $userRoleModel = new ProjectUserRoleModel($this->container); + $projectPermission = new ProjectPermissionModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'Project 2'))); + + $this->assertEquals(2, $userModel->create(array('username' => 'user 1', 'name' => 'User #1'))); + $this->assertEquals(3, $userModel->create(array('username' => 'user 2'))); + $this->assertEquals(4, $userModel->create(array('username' => 'user 3'))); + $this->assertEquals(5, $userModel->create(array('username' => 'user 4'))); + $this->assertEquals(6, $userModel->create(array('username' => 'user 5', 'name' => 'User #5'))); + + $this->assertEquals(1, $groupModel->create('Group C')); + $this->assertEquals(2, $groupModel->create('Group B')); + $this->assertEquals(3, $groupModel->create('Group A')); + + $this->assertTrue($groupMemberModel->addUser(1, 4)); + $this->assertTrue($groupMemberModel->addUser(2, 5)); + $this->assertTrue($groupMemberModel->addUser(3, 3)); + $this->assertTrue($groupMemberModel->addUser(3, 2)); + + $this->assertTrue($groupRoleModel->addGroup(1, 1, Role::PROJECT_VIEWER)); + $this->assertTrue($groupRoleModel->addGroup(1, 3, Role::PROJECT_MANAGER)); + + $this->assertTrue($userRoleModel->addUser(1, 5, Role::PROJECT_MANAGER)); + $this->assertTrue($userRoleModel->addUser(1, 6, Role::PROJECT_MEMBER)); + + $this->assertTrue($projectPermission->duplicate(1, 2)); + + $this->assertCount(2, $userRoleModel->getUsers(2)); + $this->assertCount(3, $groupRoleModel->getUsers(2)); + } +} diff --git a/tests/units/Model/ProjectPermissionTest.php b/tests/units/Model/ProjectPermissionTest.php deleted file mode 100644 index a9f8ab04..00000000 --- a/tests/units/Model/ProjectPermissionTest.php +++ /dev/null @@ -1,332 +0,0 @@ -container); - $projectModel = new ProjectModel($this->container); - $groupModel = new GroupModel($this->container); - $groupMemberModel = new GroupMemberModel($this->container); - $groupRoleModel = new ProjectGroupRoleModel($this->container); - $userRoleModel = new ProjectUserRoleModel($this->container); - $projectPermissionModel = new ProjectPermissionModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); - - $this->assertEquals(2, $userModel->create(array('username' => 'user1'))); - $this->assertEquals(3, $userModel->create(array('username' => 'user2'))); - $this->assertEquals(4, $userModel->create(array('username' => 'user3'))); - - $this->assertEquals(1, $groupModel->create('Group A')); - $this->assertTrue($groupMemberModel->addUser(1, 2)); - - $this->assertTrue($groupRoleModel->addGroup(1, 1, Role::PROJECT_MEMBER)); - $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MANAGER)); - - $this->assertEquals(array('user1', 'user2'), $projectPermissionModel->findUsernames(1, 'us')); - $this->assertEmpty($projectPermissionModel->findUsernames(1, 'a')); - $this->assertEmpty($projectPermissionModel->findUsernames(2, 'user')); - } - - public function testGetQueryByRole() - { - $userModel = new UserModel($this->container); - $projectModel = new ProjectModel($this->container); - $userRoleModel = new ProjectUserRoleModel($this->container); - $projectPermission = new ProjectPermissionModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); - $this->assertEquals(2, $projectModel->create(array('name' => 'Project 2'))); - $this->assertEquals(3, $projectModel->create(array('name' => 'Project 3'))); - - $this->assertEquals(2, $userModel->create(array('username' => 'user 1'))); - $this->assertEquals(3, $userModel->create(array('username' => 'user 2'))); - $this->assertEquals(4, $userModel->create(array('username' => 'user 3'))); - $this->assertEquals(5, $userModel->create(array('username' => 'user 4'))); - - $this->assertTrue($userRoleModel->addUser(1, 2, Role::PROJECT_MANAGER)); - $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MANAGER)); - $this->assertTrue($userRoleModel->addUser(1, 4, Role::PROJECT_MEMBER)); - $this->assertTrue($userRoleModel->addUser(1, 5, Role::PROJECT_MEMBER)); - - $this->assertTrue($userRoleModel->addUser(2, 2, Role::PROJECT_MEMBER)); - $this->assertTrue($userRoleModel->addUser(2, 3, Role::PROJECT_MEMBER)); - $this->assertTrue($userRoleModel->addUser(2, 5, Role::PROJECT_MANAGER)); - - $this->assertTrue($userRoleModel->addUser(3, 4, Role::PROJECT_MANAGER)); - $this->assertTrue($userRoleModel->addUser(3, 5, Role::PROJECT_VIEWER)); - - $this->assertEmpty($projectPermission->getQueryByRole(array(), Role::PROJECT_MANAGER)->findAll()); - - $users = $projectPermission->getQueryByRole(array(1, 2), Role::PROJECT_MANAGER)->findAll(); - $this->assertCount(3, $users); - $this->assertEquals('user 1', $users[0]['username']); - $this->assertEquals('Project 1', $users[0]['project_name']); - $this->assertEquals('user 2', $users[1]['username']); - $this->assertEquals('Project 1', $users[1]['project_name']); - $this->assertEquals('user 4', $users[2]['username']); - $this->assertEquals('Project 2', $users[2]['project_name']); - - $users = $projectPermission->getQueryByRole(array(1), Role::PROJECT_MANAGER)->findAll(); - $this->assertCount(2, $users); - $this->assertEquals('user 1', $users[0]['username']); - $this->assertEquals('Project 1', $users[0]['project_name']); - $this->assertEquals('user 2', $users[1]['username']); - $this->assertEquals('Project 1', $users[1]['project_name']); - - $users = $projectPermission->getQueryByRole(array(1, 2, 3), Role::PROJECT_MEMBER)->findAll(); - $this->assertCount(4, $users); - $this->assertEquals('user 3', $users[0]['username']); - $this->assertEquals('Project 1', $users[0]['project_name']); - $this->assertEquals('user 4', $users[1]['username']); - $this->assertEquals('Project 1', $users[1]['project_name']); - $this->assertEquals('user 1', $users[2]['username']); - $this->assertEquals('Project 2', $users[2]['project_name']); - $this->assertEquals('user 2', $users[3]['username']); - $this->assertEquals('Project 2', $users[3]['project_name']); - - $users = $projectPermission->getQueryByRole(array(1, 2, 3), Role::PROJECT_VIEWER)->findAll(); - $this->assertCount(1, $users); - $this->assertEquals('user 4', $users[0]['username']); - $this->assertEquals('Project 3', $users[0]['project_name']); - } - - public function testEverybodyAllowed() - { - $projectModel = new ProjectModel($this->container); - $projectPermission = new ProjectPermissionModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); - $this->assertEquals(2, $projectModel->create(array('name' => 'Project 2', 'is_everybody_allowed' => 1))); - - $this->assertFalse($projectPermission->isEverybodyAllowed(1)); - $this->assertTrue($projectPermission->isEverybodyAllowed(2)); - } - - public function testIsUserAllowed() - { - $userModel = new UserModel($this->container); - $projectModel = new ProjectModel($this->container); - $groupModel = new GroupModel($this->container); - $groupRoleModel = new ProjectGroupRoleModel($this->container); - $groupMemberModel = new GroupMemberModel($this->container); - $userRoleModel = new ProjectUserRoleModel($this->container); - $projectPermission = new ProjectPermissionModel($this->container); - - $this->assertEquals(2, $userModel->create(array('username' => 'user 1'))); - $this->assertEquals(3, $userModel->create(array('username' => 'user 2'))); - $this->assertEquals(4, $userModel->create(array('username' => 'user 3'))); - $this->assertEquals(5, $userModel->create(array('username' => 'user 4'))); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); - $this->assertEquals(2, $projectModel->create(array('name' => 'Project 2'))); - - $this->assertEquals(1, $groupModel->create('Group A')); - - $this->assertTrue($groupMemberModel->addUser(1, 2)); - $this->assertTrue($groupRoleModel->addGroup(1, 1, Role::PROJECT_VIEWER)); - - $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MEMBER)); - $this->assertTrue($userRoleModel->addUser(1, 4, Role::PROJECT_MANAGER)); - - $this->assertTrue($projectPermission->isUserAllowed(1, 2)); - $this->assertTrue($projectPermission->isUserAllowed(1, 3)); - $this->assertTrue($projectPermission->isUserAllowed(1, 4)); - $this->assertFalse($projectPermission->isUserAllowed(1, 5)); - - $this->assertFalse($projectPermission->isUserAllowed(2, 2)); - $this->assertFalse($projectPermission->isUserAllowed(2, 3)); - $this->assertFalse($projectPermission->isUserAllowed(2, 4)); - $this->assertFalse($projectPermission->isUserAllowed(2, 5)); - } - - public function testIsAssignable() - { - $userModel = new UserModel($this->container); - $projectModel = new ProjectModel($this->container); - $groupModel = new GroupModel($this->container); - $groupRoleModel = new ProjectGroupRoleModel($this->container); - $groupMemberModel = new GroupMemberModel($this->container); - $userRoleModel = new ProjectUserRoleModel($this->container); - $projectPermission = new ProjectPermissionModel($this->container); - - $this->assertEquals(2, $userModel->create(array('username' => 'user 1'))); - $this->assertEquals(3, $userModel->create(array('username' => 'user 2'))); - $this->assertEquals(4, $userModel->create(array('username' => 'user 3'))); - $this->assertEquals(5, $userModel->create(array('username' => 'user 4'))); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); - $this->assertEquals(2, $projectModel->create(array('name' => 'Project 2'))); - - $this->assertEquals(1, $groupModel->create('Group A')); - - $this->assertTrue($groupMemberModel->addUser(1, 2)); - $this->assertTrue($groupRoleModel->addGroup(1, 1, Role::PROJECT_VIEWER)); - - $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MEMBER)); - $this->assertTrue($userRoleModel->addUser(1, 4, Role::PROJECT_MANAGER)); - - $this->assertFalse($projectPermission->isAssignable(1, 2)); - $this->assertTrue($projectPermission->isAssignable(1, 3)); - $this->assertTrue($projectPermission->isAssignable(1, 4)); - $this->assertFalse($projectPermission->isAssignable(1, 5)); - - $this->assertFalse($projectPermission->isAssignable(2, 2)); - $this->assertFalse($projectPermission->isAssignable(2, 3)); - $this->assertFalse($projectPermission->isAssignable(2, 4)); - $this->assertFalse($projectPermission->isAssignable(2, 5)); - } - - public function testIsAssignableWhenUserIsDisabled() - { - $userModel = new UserModel($this->container); - $projectModel = new ProjectModel($this->container); - $userRoleModel = new ProjectUserRoleModel($this->container); - $projectPermission = new ProjectPermissionModel($this->container); - - $this->assertEquals(2, $userModel->create(array('username' => 'user 1'))); - $this->assertEquals(3, $userModel->create(array('username' => 'user 2', 'is_active' => 0))); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); - - $this->assertTrue($userRoleModel->addUser(1, 2, Role::PROJECT_MEMBER)); - $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MEMBER)); - - $this->assertTrue($projectPermission->isAssignable(1, 2)); - $this->assertFalse($projectPermission->isAssignable(1, 3)); - } - - public function testIsMember() - { - $userModel = new UserModel($this->container); - $projectModel = new ProjectModel($this->container); - $groupModel = new GroupModel($this->container); - $groupRoleModel = new ProjectGroupRoleModel($this->container); - $groupMemberModel = new GroupMemberModel($this->container); - $userRoleModel = new ProjectUserRoleModel($this->container); - $projectPermission = new ProjectPermissionModel($this->container); - - $this->assertEquals(2, $userModel->create(array('username' => 'user 1'))); - $this->assertEquals(3, $userModel->create(array('username' => 'user 2'))); - $this->assertEquals(4, $userModel->create(array('username' => 'user 3'))); - $this->assertEquals(5, $userModel->create(array('username' => 'user 4'))); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); - $this->assertEquals(2, $projectModel->create(array('name' => 'Project 2'))); - - $this->assertEquals(1, $groupModel->create('Group A')); - - $this->assertTrue($groupMemberModel->addUser(1, 2)); - $this->assertTrue($groupRoleModel->addGroup(1, 1, Role::PROJECT_VIEWER)); - - $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MEMBER)); - $this->assertTrue($userRoleModel->addUser(1, 4, Role::PROJECT_MANAGER)); - - $this->assertTrue($projectPermission->isMember(1, 2)); - $this->assertTrue($projectPermission->isMember(1, 3)); - $this->assertTrue($projectPermission->isMember(1, 4)); - $this->assertFalse($projectPermission->isMember(1, 5)); - - $this->assertFalse($projectPermission->isMember(2, 2)); - $this->assertFalse($projectPermission->isMember(2, 3)); - $this->assertFalse($projectPermission->isMember(2, 4)); - $this->assertFalse($projectPermission->isMember(2, 5)); - } - - public function testGetActiveProjectIds() - { - $userModel = new UserModel($this->container); - $projectModel = new ProjectModel($this->container); - $userRoleModel = new ProjectUserRoleModel($this->container); - $projectPermission = new ProjectPermissionModel($this->container); - - $this->assertEquals(2, $userModel->create(array('username' => 'user 1'))); - $this->assertEquals(3, $userModel->create(array('username' => 'user 2'))); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); - $this->assertEquals(2, $projectModel->create(array('name' => 'Project 2', 'is_active' => 0))); - - $this->assertTrue($userRoleModel->addUser(1, 2, Role::PROJECT_MEMBER)); - $this->assertTrue($userRoleModel->addUser(2, 2, Role::PROJECT_VIEWER)); - $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_VIEWER)); - - $this->assertEmpty($projectPermission->getActiveProjectIds(1)); - $this->assertEquals(array(1), $projectPermission->getActiveProjectIds(2)); - $this->assertEquals(array(1), $projectPermission->getActiveProjectIds(3)); - } - - public function testGetProjectIds() - { - $userModel = new UserModel($this->container); - $projectModel = new ProjectModel($this->container); - $userRoleModel = new ProjectUserRoleModel($this->container); - $projectPermission = new ProjectPermissionModel($this->container); - - $this->assertEquals(2, $userModel->create(array('username' => 'user 1'))); - $this->assertEquals(3, $userModel->create(array('username' => 'user 2'))); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); - $this->assertEquals(2, $projectModel->create(array('name' => 'Project 2', 'is_active' => 0))); - - $this->assertTrue($userRoleModel->addUser(1, 2, Role::PROJECT_MEMBER)); - $this->assertTrue($userRoleModel->addUser(2, 2, Role::PROJECT_MEMBER)); - $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MEMBER)); - $this->assertTrue($userRoleModel->addUser(2, 3, Role::PROJECT_MEMBER)); - - $this->assertEmpty($projectPermission->getProjectIds(1)); - $this->assertEquals(array(1, 2), $projectPermission->getProjectIds(2)); - $this->assertEquals(array(1, 2), $projectPermission->getProjectIds(3)); - } - - public function testDuplicate() - { - $userModel = new UserModel($this->container); - $projectModel = new ProjectModel($this->container); - $groupModel = new GroupModel($this->container); - $groupMemberModel = new GroupMemberModel($this->container); - $groupRoleModel = new ProjectGroupRoleModel($this->container); - $userRoleModel = new ProjectUserRoleModel($this->container); - $projectPermission = new ProjectPermissionModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); - $this->assertEquals(2, $projectModel->create(array('name' => 'Project 2'))); - - $this->assertEquals(2, $userModel->create(array('username' => 'user 1', 'name' => 'User #1'))); - $this->assertEquals(3, $userModel->create(array('username' => 'user 2'))); - $this->assertEquals(4, $userModel->create(array('username' => 'user 3'))); - $this->assertEquals(5, $userModel->create(array('username' => 'user 4'))); - $this->assertEquals(6, $userModel->create(array('username' => 'user 5', 'name' => 'User #5'))); - - $this->assertEquals(1, $groupModel->create('Group C')); - $this->assertEquals(2, $groupModel->create('Group B')); - $this->assertEquals(3, $groupModel->create('Group A')); - - $this->assertTrue($groupMemberModel->addUser(1, 4)); - $this->assertTrue($groupMemberModel->addUser(2, 5)); - $this->assertTrue($groupMemberModel->addUser(3, 3)); - $this->assertTrue($groupMemberModel->addUser(3, 2)); - - $this->assertTrue($groupRoleModel->addGroup(1, 1, Role::PROJECT_VIEWER)); - $this->assertTrue($groupRoleModel->addGroup(1, 3, Role::PROJECT_MANAGER)); - - $this->assertTrue($userRoleModel->addUser(1, 5, Role::PROJECT_MANAGER)); - $this->assertTrue($userRoleModel->addUser(1, 6, Role::PROJECT_MEMBER)); - - $this->assertTrue($projectPermission->duplicate(1, 2)); - - $this->assertCount(2, $userRoleModel->getUsers(2)); - $this->assertCount(3, $groupRoleModel->getUsers(2)); - } -} diff --git a/tests/units/Model/ProjectRoleModelTest.php b/tests/units/Model/ProjectRoleModelTest.php index 5dd78e20..65208e6a 100644 --- a/tests/units/Model/ProjectRoleModelTest.php +++ b/tests/units/Model/ProjectRoleModelTest.php @@ -41,14 +41,44 @@ class ProjectRoleModelTest extends Base $this->assertEquals('Role B', $roles[1]['role']); } - public function testModification() + public function testModificationWithUserRole() { $projectModel = new ProjectModel($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, $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->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() diff --git a/tests/units/Model/ProjectRoleRestrictionModelTest.php b/tests/units/Model/ProjectRoleRestrictionModelTest.php new file mode 100644 index 00000000..07473061 --- /dev/null +++ b/tests/units/Model/ProjectRoleRestrictionModelTest.php @@ -0,0 +1,96 @@ +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); + } +} diff --git a/tests/units/Model/TaskFinderModelTest.php b/tests/units/Model/TaskFinderModelTest.php index a9f018ff..9e0369ce 100644 --- a/tests/units/Model/TaskFinderModelTest.php +++ b/tests/units/Model/TaskFinderModelTest.php @@ -89,6 +89,7 @@ class TaskFinderModelTest extends Base $tasks = $taskFinderModel->getUserQuery(1)->findAll(); $this->assertCount(1, $tasks); $this->assertEquals('Task #1', $tasks[0]['title']); + $this->assertEquals(1, $tasks[0]['column_id']); $this->assertTrue($columnModel->update(2, 'Test', 0, '', 0)); -- cgit v1.2.3