summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorFrederic Guillot <fred@kanboard.net>2016-09-08 22:33:16 -0400
committerFrederic Guillot <fred@kanboard.net>2016-09-08 22:33:16 -0400
commit75470c72428c8d8f278d160369558ab31b137fb1 (patch)
tree7fcad6cbc661e2762f1dfa5f643a5beac5217a17 /app
parentfedf4ea2de21fcf95fc5aa942cedc7924865f160 (diff)
Apply column restrictions to the board
Diffstat (limited to 'app')
-rw-r--r--app/Controller/BoardAjaxController.php12
-rw-r--r--app/Core/Base.php327
-rw-r--r--app/Core/Helper.php1
-rw-r--r--app/Decorator/ColumnMoveRestrictionCacheDecorator.php57
-rw-r--r--app/Formatter/BoardTaskFormatter.php5
-rw-r--r--app/Helper/BoardHelper.php16
-rw-r--r--app/Model/ColumnMoveRestrictionModel.php17
-rw-r--r--app/ServiceProvider/CacheProvider.php8
-rw-r--r--app/ServiceProvider/ClassProvider.php2
-rw-r--r--app/Template/board/task_private.php3
10 files changed, 283 insertions, 165 deletions
diff --git a/app/Controller/BoardAjaxController.php b/app/Controller/BoardAjaxController.php
index ccd47667..5e771fd6 100644
--- a/app/Controller/BoardAjaxController.php
+++ b/app/Controller/BoardAjaxController.php
@@ -28,11 +28,21 @@ class BoardAjaxController extends BaseController
}
$values = $this->request->getJson();
+ $canMoveTask = $this->columnMoveRestrictionModel->isAllowed(
+ $project_id,
+ $this->helper->user->getProjectUserRole($project_id),
+ $values['src_column_id'],
+ $values['dst_column_id']
+ );
+
+ if (! $canMoveTask) {
+ throw new AccessForbiddenException("You don't have the permission to move this task");
+ }
$result =$this->taskPositionModel->movePosition(
$project_id,
$values['task_id'],
- $values['column_id'],
+ $values['dst_column_id'],
$values['position'],
$values['swimlane_id']
);
diff --git a/app/Core/Base.php b/app/Core/Base.php
index 3b7c5e66..747b1917 100644
--- a/app/Core/Base.php
+++ b/app/Core/Base.php
@@ -10,168 +10,171 @@ use Pimple\Container;
* @package core
* @author Frederic Guillot
*
- * @property \Kanboard\Analytic\TaskDistributionAnalytic $taskDistributionAnalytic
- * @property \Kanboard\Analytic\UserDistributionAnalytic $userDistributionAnalytic
- * @property \Kanboard\Analytic\EstimatedTimeComparisonAnalytic $estimatedTimeComparisonAnalytic
- * @property \Kanboard\Analytic\AverageLeadCycleTimeAnalytic $averageLeadCycleTimeAnalytic
- * @property \Kanboard\Analytic\AverageTimeSpentColumnAnalytic $averageTimeSpentColumnAnalytic
- * @property \Kanboard\Core\Action\ActionManager $actionManager
- * @property \Kanboard\Core\ExternalLink\ExternalLinkManager $externalLinkManager
- * @property \Kanboard\Core\Cache\MemoryCache $memoryCache
- * @property \Kanboard\Core\Cache\BaseCache $cacheDriver
- * @property \Kanboard\Core\Event\EventManager $eventManager
- * @property \Kanboard\Core\Group\GroupManager $groupManager
- * @property \Kanboard\Core\Http\Client $httpClient
- * @property \Kanboard\Core\Http\OAuth2 $oauth
- * @property \Kanboard\Core\Http\RememberMeCookie $rememberMeCookie
- * @property \Kanboard\Core\Http\Request $request
- * @property \Kanboard\Core\Http\Response $response
- * @property \Kanboard\Core\Http\Router $router
- * @property \Kanboard\Core\Http\Route $route
- * @property \Kanboard\Core\Queue\QueueManager $queueManager
- * @property \Kanboard\Core\Mail\Client $emailClient
- * @property \Kanboard\Core\ObjectStorage\ObjectStorageInterface $objectStorage
- * @property \Kanboard\Core\Plugin\Hook $hook
- * @property \Kanboard\Core\Plugin\Loader $pluginLoader
- * @property \Kanboard\Core\Security\AuthenticationManager $authenticationManager
- * @property \Kanboard\Core\Security\AccessMap $applicationAccessMap
- * @property \Kanboard\Core\Security\AccessMap $projectAccessMap
- * @property \Kanboard\Core\Security\AccessMap $apiAccessMap
- * @property \Kanboard\Core\Security\AccessMap $apiProjectAccessMap
- * @property \Kanboard\Core\Security\Authorization $applicationAuthorization
- * @property \Kanboard\Core\Security\Authorization $projectAuthorization
- * @property \Kanboard\Core\Security\Authorization $apiAuthorization
- * @property \Kanboard\Core\Security\Authorization $apiProjectAuthorization
- * @property \Kanboard\Core\Security\Role $role
- * @property \Kanboard\Core\Security\Token $token
- * @property \Kanboard\Core\Session\FlashMessage $flash
- * @property \Kanboard\Core\Session\SessionManager $sessionManager
- * @property \Kanboard\Core\Session\SessionStorage $sessionStorage
- * @property \Kanboard\Core\User\Avatar\AvatarManager $avatarManager
- * @property \Kanboard\Core\User\GroupSync $groupSync
- * @property \Kanboard\Core\User\UserProfile $userProfile
- * @property \Kanboard\Core\User\UserSync $userSync
- * @property \Kanboard\Core\User\UserSession $userSession
- * @property \Kanboard\Core\DateParser $dateParser
- * @property \Kanboard\Core\Helper $helper
- * @property \Kanboard\Core\Paginator $paginator
- * @property \Kanboard\Core\Template $template
- * @property \Kanboard\Decorator\MetadataCacheDecorator $userMetadataCacheDecorator
- * @property \Kanboard\Model\ActionModel $actionModel
- * @property \Kanboard\Model\ActionParameterModel $actionParameterModel
- * @property \Kanboard\Model\AvatarFileModel $avatarFileModel
- * @property \Kanboard\Model\BoardModel $boardModel
- * @property \Kanboard\Model\CategoryModel $categoryModel
- * @property \Kanboard\Model\ColorModel $colorModel
- * @property \Kanboard\Model\ColumnModel $columnModel
- * @property \Kanboard\Model\CommentModel $commentModel
- * @property \Kanboard\Model\ConfigModel $configModel
- * @property \Kanboard\Model\CurrencyModel $currencyModel
- * @property \Kanboard\Model\CustomFilterModel $customFilterModel
- * @property \Kanboard\Model\TaskFileModel $taskFileModel
- * @property \Kanboard\Model\ProjectFileModel $projectFileModel
- * @property \Kanboard\Model\GroupModel $groupModel
- * @property \Kanboard\Model\GroupMemberModel $groupMemberModel
- * @property \Kanboard\Model\LanguageModel $languageModel
- * @property \Kanboard\Model\LastLoginModel $lastLoginModel
- * @property \Kanboard\Model\LinkModel $linkModel
- * @property \Kanboard\Model\NotificationModel $notificationModel
- * @property \Kanboard\Model\PasswordResetModel $passwordResetModel
- * @property \Kanboard\Model\ProjectModel $projectModel
- * @property \Kanboard\Model\ProjectActivityModel $projectActivityModel
- * @property \Kanboard\Model\ProjectDuplicationModel $projectDuplicationModel
- * @property \Kanboard\Model\ProjectDailyColumnStatsModel $projectDailyColumnStatsModel
- * @property \Kanboard\Model\ProjectDailyStatsModel $projectDailyStatsModel
- * @property \Kanboard\Model\ProjectMetadataModel $projectMetadataModel
- * @property \Kanboard\Model\ProjectPermissionModel $projectPermissionModel
- * @property \Kanboard\Model\ProjectUserRoleModel $projectUserRoleModel
- * @property \Kanboard\Model\ProjectGroupRoleModel $projectGroupRoleModel
- * @property \Kanboard\Model\ProjectNotificationModel $projectNotificationModel
- * @property \Kanboard\Model\ProjectNotificationTypeModel $projectNotificationTypeModel
- * @property \Kanboard\Model\ProjectTaskDuplicationModel $projectTaskDuplicationModel
- * @property \Kanboard\Model\ProjectTaskPriorityModel $projectTaskPriorityModel
- * @property \Kanboard\Model\RememberMeSessionModel $rememberMeSessionModel
- * @property \Kanboard\Model\SubtaskModel $subtaskModel
- * @property \Kanboard\Model\SubtaskPositionModel $subtaskPositionModel
- * @property \Kanboard\Model\SubtaskStatusModel $subtaskStatusModel
- * @property \Kanboard\Model\SubtaskTaskConversionModel $subtaskTaskConversionModel
- * @property \Kanboard\Model\SubtaskTimeTrackingModel $subtaskTimeTrackingModel
- * @property \Kanboard\Model\SwimlaneModel $swimlaneModel
- * @property \Kanboard\Model\TagDuplicationModel $tagDuplicationModel
- * @property \Kanboard\Model\TagModel $tagModel
- * @property \Kanboard\Model\TaskModel $taskModel
- * @property \Kanboard\Model\TaskAnalyticModel $taskAnalyticModel
- * @property \Kanboard\Model\TaskCreationModel $taskCreationModel
- * @property \Kanboard\Model\TaskDuplicationModel $taskDuplicationModel
- * @property \Kanboard\Model\TaskProjectDuplicationModel $taskProjectDuplicationModel
- * @property \Kanboard\Model\TaskProjectMoveModel $taskProjectMoveModel
- * @property \Kanboard\Model\TaskRecurrenceModel $taskRecurrenceModel
- * @property \Kanboard\Model\TaskExternalLinkModel $taskExternalLinkModel
- * @property \Kanboard\Model\TaskFinderModel $taskFinderModel
- * @property \Kanboard\Model\TaskLinkModel $taskLinkModel
- * @property \Kanboard\Model\TaskModificationModel $taskModificationModel
- * @property \Kanboard\Model\TaskPositionModel $taskPositionModel
- * @property \Kanboard\Model\TaskStatusModel $taskStatusModel
- * @property \Kanboard\Model\TaskTagModel $taskTagModel
- * @property \Kanboard\Model\TaskMetadataModel $taskMetadataModel
- * @property \Kanboard\Model\TimezoneModel $timezoneModel
- * @property \Kanboard\Model\TransitionModel $transitionModel
- * @property \Kanboard\Model\UserModel $userModel
- * @property \Kanboard\Model\UserLockingModel $userLockingModel
- * @property \Kanboard\Model\UserMentionModel $userMentionModel
- * @property \Kanboard\Model\UserNotificationModel $userNotificationModel
- * @property \Kanboard\Model\UserNotificationTypeModel $userNotificationTypeModel
- * @property \Kanboard\Model\UserNotificationFilterModel $userNotificationFilterModel
- * @property \Kanboard\Model\UserUnreadNotificationModel $userUnreadNotificationModel
- * @property \Kanboard\Model\UserMetadataModel $userMetadataModel
- * @property \Kanboard\Pagination\TaskPagination $taskPagination
- * @property \Kanboard\Pagination\SubtaskPagination $subtaskPagination
- * @property \Kanboard\Pagination\ProjectPagination $projectPagination
- * @property \Kanboard\Pagination\UserPagination $userPagination
- * @property \Kanboard\Validator\ActionValidator $actionValidator
- * @property \Kanboard\Validator\AuthValidator $authValidator
- * @property \Kanboard\Validator\ColumnValidator $columnValidator
- * @property \Kanboard\Validator\CategoryValidator $categoryValidator
- * @property \Kanboard\Validator\CommentValidator $commentValidator
- * @property \Kanboard\Validator\CurrencyValidator $currencyValidator
- * @property \Kanboard\Validator\CustomFilterValidator $customFilterValidator
- * @property \Kanboard\Validator\ExternalLinkValidator $externalLinkValidator
- * @property \Kanboard\Validator\GroupValidator $groupValidator
- * @property \Kanboard\Validator\LinkValidator $linkValidator
- * @property \Kanboard\Validator\PasswordResetValidator $passwordResetValidator
- * @property \Kanboard\Validator\ProjectValidator $projectValidator
- * @property \Kanboard\Validator\SubtaskValidator $subtaskValidator
- * @property \Kanboard\Validator\SwimlaneValidator $swimlaneValidator
- * @property \Kanboard\Validator\TagValidator $tagValidator
- * @property \Kanboard\Validator\TaskLinkValidator $taskLinkValidator
- * @property \Kanboard\Validator\TaskValidator $taskValidator
- * @property \Kanboard\Validator\UserValidator $userValidator
- * @property \Kanboard\Import\TaskImport $taskImport
- * @property \Kanboard\Import\UserImport $userImport
- * @property \Kanboard\Export\SubtaskExport $subtaskExport
- * @property \Kanboard\Export\TaskExport $taskExport
- * @property \Kanboard\Export\TransitionExport $transitionExport
- * @property \Kanboard\Core\Filter\QueryBuilder $projectGroupRoleQuery
- * @property \Kanboard\Core\Filter\QueryBuilder $projectUserRoleQuery
- * @property \Kanboard\Core\Filter\QueryBuilder $projectActivityQuery
- * @property \Kanboard\Core\Filter\QueryBuilder $userQuery
- * @property \Kanboard\Core\Filter\QueryBuilder $projectQuery
- * @property \Kanboard\Core\Filter\QueryBuilder $taskQuery
- * @property \Kanboard\Core\Filter\LexerBuilder $taskLexer
- * @property \Kanboard\Core\Filter\LexerBuilder $projectActivityLexer
- * @property \Kanboard\Job\CommentEventJob $commentEventJob
- * @property \Kanboard\Job\SubtaskEventJob $subtaskEventJob
- * @property \Kanboard\Job\TaskEventJob $taskEventJob
- * @property \Kanboard\Job\TaskFileEventJob $taskFileEventJob
- * @property \Kanboard\Job\TaskLinkEventJob $taskLinkEventJob
- * @property \Kanboard\Job\ProjectFileEventJob $projectFileEventJob
- * @property \Kanboard\Job\NotificationJob $notificationJob
- * @property \Kanboard\Job\ProjectMetricJob $projectMetricJob
- * @property \Psr\Log\LoggerInterface $logger
- * @property \PicoDb\Database $db
- * @property \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher
- * @property \Symfony\Component\Console\Application $cli
- * @property \JsonRPC\Server $api
+ * @property \Kanboard\Analytic\TaskDistributionAnalytic $taskDistributionAnalytic
+ * @property \Kanboard\Analytic\UserDistributionAnalytic $userDistributionAnalytic
+ * @property \Kanboard\Analytic\EstimatedTimeComparisonAnalytic $estimatedTimeComparisonAnalytic
+ * @property \Kanboard\Analytic\AverageLeadCycleTimeAnalytic $averageLeadCycleTimeAnalytic
+ * @property \Kanboard\Analytic\AverageTimeSpentColumnAnalytic $averageTimeSpentColumnAnalytic
+ * @property \Kanboard\Core\Action\ActionManager $actionManager
+ * @property \Kanboard\Core\ExternalLink\ExternalLinkManager $externalLinkManager
+ * @property \Kanboard\Core\Cache\MemoryCache $memoryCache
+ * @property \Kanboard\Core\Cache\BaseCache $cacheDriver
+ * @property \Kanboard\Core\Event\EventManager $eventManager
+ * @property \Kanboard\Core\Group\GroupManager $groupManager
+ * @property \Kanboard\Core\Http\Client $httpClient
+ * @property \Kanboard\Core\Http\OAuth2 $oauth
+ * @property \Kanboard\Core\Http\RememberMeCookie $rememberMeCookie
+ * @property \Kanboard\Core\Http\Request $request
+ * @property \Kanboard\Core\Http\Response $response
+ * @property \Kanboard\Core\Http\Router $router
+ * @property \Kanboard\Core\Http\Route $route
+ * @property \Kanboard\Core\Queue\QueueManager $queueManager
+ * @property \Kanboard\Core\Mail\Client $emailClient
+ * @property \Kanboard\Core\ObjectStorage\ObjectStorageInterface $objectStorage
+ * @property \Kanboard\Core\Plugin\Hook $hook
+ * @property \Kanboard\Core\Plugin\Loader $pluginLoader
+ * @property \Kanboard\Core\Security\AuthenticationManager $authenticationManager
+ * @property \Kanboard\Core\Security\AccessMap $applicationAccessMap
+ * @property \Kanboard\Core\Security\AccessMap $projectAccessMap
+ * @property \Kanboard\Core\Security\AccessMap $apiAccessMap
+ * @property \Kanboard\Core\Security\AccessMap $apiProjectAccessMap
+ * @property \Kanboard\Core\Security\Authorization $applicationAuthorization
+ * @property \Kanboard\Core\Security\Authorization $projectAuthorization
+ * @property \Kanboard\Core\Security\Authorization $apiAuthorization
+ * @property \Kanboard\Core\Security\Authorization $apiProjectAuthorization
+ * @property \Kanboard\Core\Security\Role $role
+ * @property \Kanboard\Core\Security\Token $token
+ * @property \Kanboard\Core\Session\FlashMessage $flash
+ * @property \Kanboard\Core\Session\SessionManager $sessionManager
+ * @property \Kanboard\Core\Session\SessionStorage $sessionStorage
+ * @property \Kanboard\Core\User\Avatar\AvatarManager $avatarManager
+ * @property \Kanboard\Core\User\GroupSync $groupSync
+ * @property \Kanboard\Core\User\UserProfile $userProfile
+ * @property \Kanboard\Core\User\UserSync $userSync
+ * @property \Kanboard\Core\User\UserSession $userSession
+ * @property \Kanboard\Core\DateParser $dateParser
+ * @property \Kanboard\Core\Helper $helper
+ * @property \Kanboard\Core\Paginator $paginator
+ * @property \Kanboard\Core\Template $template
+ * @property \Kanboard\Decorator\MetadataCacheDecorator $userMetadataCacheDecorator
+ * @property \Kanboard\Decorator\ColumnMoveRestrictionCacheDecorator $columnMoveRestrictionCacheDecorator
+ * @property \Kanboard\Model\ActionModel $actionModel
+ * @property \Kanboard\Model\ActionParameterModel $actionParameterModel
+ * @property \Kanboard\Model\AvatarFileModel $avatarFileModel
+ * @property \Kanboard\Model\BoardModel $boardModel
+ * @property \Kanboard\Model\CategoryModel $categoryModel
+ * @property \Kanboard\Model\ColorModel $colorModel
+ * @property \Kanboard\Model\ColumnModel $columnModel
+ * @property \Kanboard\Model\ColumnMoveRestrictionModel $columnMoveRestrictionModel
+ * @property \Kanboard\Model\CommentModel $commentModel
+ * @property \Kanboard\Model\ConfigModel $configModel
+ * @property \Kanboard\Model\CurrencyModel $currencyModel
+ * @property \Kanboard\Model\CustomFilterModel $customFilterModel
+ * @property \Kanboard\Model\TaskFileModel $taskFileModel
+ * @property \Kanboard\Model\ProjectFileModel $projectFileModel
+ * @property \Kanboard\Model\GroupModel $groupModel
+ * @property \Kanboard\Model\GroupMemberModel $groupMemberModel
+ * @property \Kanboard\Model\LanguageModel $languageModel
+ * @property \Kanboard\Model\LastLoginModel $lastLoginModel
+ * @property \Kanboard\Model\LinkModel $linkModel
+ * @property \Kanboard\Model\NotificationModel $notificationModel
+ * @property \Kanboard\Model\PasswordResetModel $passwordResetModel
+ * @property \Kanboard\Model\ProjectModel $projectModel
+ * @property \Kanboard\Model\ProjectActivityModel $projectActivityModel
+ * @property \Kanboard\Model\ProjectDuplicationModel $projectDuplicationModel
+ * @property \Kanboard\Model\ProjectDailyColumnStatsModel $projectDailyColumnStatsModel
+ * @property \Kanboard\Model\ProjectDailyStatsModel $projectDailyStatsModel
+ * @property \Kanboard\Model\ProjectMetadataModel $projectMetadataModel
+ * @property \Kanboard\Model\ProjectPermissionModel $projectPermissionModel
+ * @property \Kanboard\Model\ProjectUserRoleModel $projectUserRoleModel
+ * @property \Kanboard\Model\ProjectGroupRoleModel $projectGroupRoleModel
+ * @property \Kanboard\Model\ProjectNotificationModel $projectNotificationModel
+ * @property \Kanboard\Model\ProjectNotificationTypeModel $projectNotificationTypeModel
+ * @property \Kanboard\Model\ProjectRoleModel $projectRoleModel
+ * @property \Kanboard\Model\ProjectTaskDuplicationModel $projectTaskDuplicationModel
+ * @property \Kanboard\Model\ProjectTaskPriorityModel $projectTaskPriorityModel
+ * @property \Kanboard\Model\RememberMeSessionModel $rememberMeSessionModel
+ * @property \Kanboard\Model\SubtaskModel $subtaskModel
+ * @property \Kanboard\Model\SubtaskPositionModel $subtaskPositionModel
+ * @property \Kanboard\Model\SubtaskStatusModel $subtaskStatusModel
+ * @property \Kanboard\Model\SubtaskTaskConversionModel $subtaskTaskConversionModel
+ * @property \Kanboard\Model\SubtaskTimeTrackingModel $subtaskTimeTrackingModel
+ * @property \Kanboard\Model\SwimlaneModel $swimlaneModel
+ * @property \Kanboard\Model\TagDuplicationModel $tagDuplicationModel
+ * @property \Kanboard\Model\TagModel $tagModel
+ * @property \Kanboard\Model\TaskModel $taskModel
+ * @property \Kanboard\Model\TaskAnalyticModel $taskAnalyticModel
+ * @property \Kanboard\Model\TaskCreationModel $taskCreationModel
+ * @property \Kanboard\Model\TaskDuplicationModel $taskDuplicationModel
+ * @property \Kanboard\Model\TaskProjectDuplicationModel $taskProjectDuplicationModel
+ * @property \Kanboard\Model\TaskProjectMoveModel $taskProjectMoveModel
+ * @property \Kanboard\Model\TaskRecurrenceModel $taskRecurrenceModel
+ * @property \Kanboard\Model\TaskExternalLinkModel $taskExternalLinkModel
+ * @property \Kanboard\Model\TaskFinderModel $taskFinderModel
+ * @property \Kanboard\Model\TaskLinkModel $taskLinkModel
+ * @property \Kanboard\Model\TaskModificationModel $taskModificationModel
+ * @property \Kanboard\Model\TaskPositionModel $taskPositionModel
+ * @property \Kanboard\Model\TaskStatusModel $taskStatusModel
+ * @property \Kanboard\Model\TaskTagModel $taskTagModel
+ * @property \Kanboard\Model\TaskMetadataModel $taskMetadataModel
+ * @property \Kanboard\Model\TimezoneModel $timezoneModel
+ * @property \Kanboard\Model\TransitionModel $transitionModel
+ * @property \Kanboard\Model\UserModel $userModel
+ * @property \Kanboard\Model\UserLockingModel $userLockingModel
+ * @property \Kanboard\Model\UserMentionModel $userMentionModel
+ * @property \Kanboard\Model\UserNotificationModel $userNotificationModel
+ * @property \Kanboard\Model\UserNotificationTypeModel $userNotificationTypeModel
+ * @property \Kanboard\Model\UserNotificationFilterModel $userNotificationFilterModel
+ * @property \Kanboard\Model\UserUnreadNotificationModel $userUnreadNotificationModel
+ * @property \Kanboard\Model\UserMetadataModel $userMetadataModel
+ * @property \Kanboard\Pagination\TaskPagination $taskPagination
+ * @property \Kanboard\Pagination\SubtaskPagination $subtaskPagination
+ * @property \Kanboard\Pagination\ProjectPagination $projectPagination
+ * @property \Kanboard\Pagination\UserPagination $userPagination
+ * @property \Kanboard\Validator\ActionValidator $actionValidator
+ * @property \Kanboard\Validator\AuthValidator $authValidator
+ * @property \Kanboard\Validator\ColumnValidator $columnValidator
+ * @property \Kanboard\Validator\CategoryValidator $categoryValidator
+ * @property \Kanboard\Validator\CommentValidator $commentValidator
+ * @property \Kanboard\Validator\CurrencyValidator $currencyValidator
+ * @property \Kanboard\Validator\CustomFilterValidator $customFilterValidator
+ * @property \Kanboard\Validator\ExternalLinkValidator $externalLinkValidator
+ * @property \Kanboard\Validator\GroupValidator $groupValidator
+ * @property \Kanboard\Validator\LinkValidator $linkValidator
+ * @property \Kanboard\Validator\PasswordResetValidator $passwordResetValidator
+ * @property \Kanboard\Validator\ProjectValidator $projectValidator
+ * @property \Kanboard\Validator\SubtaskValidator $subtaskValidator
+ * @property \Kanboard\Validator\SwimlaneValidator $swimlaneValidator
+ * @property \Kanboard\Validator\TagValidator $tagValidator
+ * @property \Kanboard\Validator\TaskLinkValidator $taskLinkValidator
+ * @property \Kanboard\Validator\TaskValidator $taskValidator
+ * @property \Kanboard\Validator\UserValidator $userValidator
+ * @property \Kanboard\Import\TaskImport $taskImport
+ * @property \Kanboard\Import\UserImport $userImport
+ * @property \Kanboard\Export\SubtaskExport $subtaskExport
+ * @property \Kanboard\Export\TaskExport $taskExport
+ * @property \Kanboard\Export\TransitionExport $transitionExport
+ * @property \Kanboard\Core\Filter\QueryBuilder $projectGroupRoleQuery
+ * @property \Kanboard\Core\Filter\QueryBuilder $projectUserRoleQuery
+ * @property \Kanboard\Core\Filter\QueryBuilder $projectActivityQuery
+ * @property \Kanboard\Core\Filter\QueryBuilder $userQuery
+ * @property \Kanboard\Core\Filter\QueryBuilder $projectQuery
+ * @property \Kanboard\Core\Filter\QueryBuilder $taskQuery
+ * @property \Kanboard\Core\Filter\LexerBuilder $taskLexer
+ * @property \Kanboard\Core\Filter\LexerBuilder $projectActivityLexer
+ * @property \Kanboard\Job\CommentEventJob $commentEventJob
+ * @property \Kanboard\Job\SubtaskEventJob $subtaskEventJob
+ * @property \Kanboard\Job\TaskEventJob $taskEventJob
+ * @property \Kanboard\Job\TaskFileEventJob $taskFileEventJob
+ * @property \Kanboard\Job\TaskLinkEventJob $taskLinkEventJob
+ * @property \Kanboard\Job\ProjectFileEventJob $projectFileEventJob
+ * @property \Kanboard\Job\NotificationJob $notificationJob
+ * @property \Kanboard\Job\ProjectMetricJob $projectMetricJob
+ * @property \Psr\Log\LoggerInterface $logger
+ * @property \PicoDb\Database $db
+ * @property \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher
+ * @property \Symfony\Component\Console\Application $cli
+ * @property \JsonRPC\Server $api
*/
abstract class Base
{
diff --git a/app/Core/Helper.php b/app/Core/Helper.php
index 43151be8..c98b3c5e 100644
--- a/app/Core/Helper.php
+++ b/app/Core/Helper.php
@@ -12,6 +12,7 @@ use Pimple\Container;
*
* @property \Kanboard\Helper\AppHelper $app
* @property \Kanboard\Helper\AssetHelper $asset
+ * @property \Kanboard\Helper\BoardHelper $board
* @property \Kanboard\Helper\CalendarHelper $calendar
* @property \Kanboard\Helper\DateHelper $dt
* @property \Kanboard\Helper\FileHelper $file
diff --git a/app/Decorator/ColumnMoveRestrictionCacheDecorator.php b/app/Decorator/ColumnMoveRestrictionCacheDecorator.php
new file mode 100644
index 00000000..331bdebb
--- /dev/null
+++ b/app/Decorator/ColumnMoveRestrictionCacheDecorator.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace Kanboard\Decorator;
+
+use Kanboard\Core\Cache\CacheInterface;
+use Kanboard\Model\ColumnMoveRestrictionModel;
+
+/**
+ * Class ColumnMoveRestrictionCacheDecorator
+ *
+ * @package Kanboard\Decorator
+ * @author Frederic Guillot
+ */
+class ColumnMoveRestrictionCacheDecorator
+{
+ protected $cachePrefix = 'column_move_restriction:';
+
+ /**
+ * @var CacheInterface
+ */
+ protected $cache;
+
+ /**
+ * @var ColumnMoveRestrictionModel
+ */
+ protected $columnMoveRestrictionModel;
+
+ /**
+ * ColumnMoveRestrictionDecorator constructor.
+ *
+ * @param CacheInterface $cache
+ * @param ColumnMoveRestrictionModel $columnMoveRestrictionModel
+ */
+ public function __construct(CacheInterface $cache, ColumnMoveRestrictionModel $columnMoveRestrictionModel)
+ {
+ $this->cache = $cache;
+ $this->columnMoveRestrictionModel = $columnMoveRestrictionModel;
+ }
+
+ /**
+ * Proxy method to get column Ids
+ * @param int $project_id
+ * @return array|mixed
+ */
+ public function getAllSrcColumns($project_id)
+ {
+ $key = $this->cachePrefix.$project_id;
+ $columnIds = $this->cache->get($key);
+
+ if ($columnIds === null) {
+ $columnIds = $this->columnMoveRestrictionModel->getAllSrcColumns($project_id);
+ $this->cache->set($key, $columnIds);
+ }
+
+ return $columnIds;
+ }
+}
diff --git a/app/Formatter/BoardTaskFormatter.php b/app/Formatter/BoardTaskFormatter.php
index 3bf171b1..5956ae35 100644
--- a/app/Formatter/BoardTaskFormatter.php
+++ b/app/Formatter/BoardTaskFormatter.php
@@ -79,6 +79,11 @@ class BoardTaskFormatter extends BaseFormatter implements FormatterInterface
{
$tasks = array_values(array_filter($this->tasks, array($this, 'filterTasks')));
array_merge_relation($tasks, $this->tags, 'tags', 'id');
+
+ foreach ($tasks as &$task) {
+ $task['is_draggable'] = $this->helper->board->isDraggable($task);
+ }
+
return $tasks;
}
diff --git a/app/Helper/BoardHelper.php b/app/Helper/BoardHelper.php
index f5df3db2..c3d28dc4 100644
--- a/app/Helper/BoardHelper.php
+++ b/app/Helper/BoardHelper.php
@@ -24,4 +24,20 @@ class BoardHelper extends Base
{
return $this->userMetadataCacheDecorator->get(UserMetadataModel::KEY_BOARD_COLLAPSED.$project_id, 0) == 1;
}
+
+ /**
+ * Return true if the task can be moved by the connected user
+ *
+ * @param array $task
+ * @return bool
+ */
+ public function isDraggable(array $task)
+ {
+ if ($task['is_active'] == 1 && $this->helper->user->hasProjectAccess('BoardViewController', 'save', $task['project_id'])) {
+ $srcColumnIds = $this->columnMoveRestrictionCacheDecorator->getAllSrcColumns($task['project_id']);
+ return ! isset($srcColumnIds[$task['column_id']]);
+ }
+
+ return false;
+ }
}
diff --git a/app/Model/ColumnMoveRestrictionModel.php b/app/Model/ColumnMoveRestrictionModel.php
index fa44edd1..63e739bf 100644
--- a/app/Model/ColumnMoveRestrictionModel.php
+++ b/app/Model/ColumnMoveRestrictionModel.php
@@ -42,7 +42,8 @@ class ColumnMoveRestrictionModel extends Base
*/
public function getAll($project_id)
{
- return $this->db->table(self::TABLE)
+ return $this->db
+ ->table(self::TABLE)
->columns(
'restriction_id',
'src_column_id',
@@ -59,6 +60,20 @@ class ColumnMoveRestrictionModel extends Base
}
/**
+ * Get all source column Ids
+ *
+ * @param int $project_id
+ * @return array
+ */
+ public function getAllSrcColumns($project_id)
+ {
+ return $this->db
+ ->hashtable(self::TABLE)
+ ->eq(self::TABLE.'.project_id', $project_id)
+ ->getAll('src_column_id', 'src_column_id');
+ }
+
+ /**
* Create a new column restriction
*
* @param int $project_id
diff --git a/app/ServiceProvider/CacheProvider.php b/app/ServiceProvider/CacheProvider.php
index fac44d53..90d63f81 100644
--- a/app/ServiceProvider/CacheProvider.php
+++ b/app/ServiceProvider/CacheProvider.php
@@ -4,6 +4,7 @@ namespace Kanboard\ServiceProvider;
use Kanboard\Core\Cache\FileCache;
use Kanboard\Core\Cache\MemoryCache;
+use Kanboard\Decorator\ColumnMoveRestrictionCacheDecorator;
use Kanboard\Decorator\MetadataCacheDecorator;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
@@ -46,6 +47,13 @@ class CacheProvider implements ServiceProviderInterface
);
};
+ $container['columnMoveRestrictionCacheDecorator'] = function($c) {
+ return new ColumnMoveRestrictionCacheDecorator(
+ $c['memoryCache'],
+ $c['columnMoveRestrictionModel']
+ );
+ };
+
return $container;
}
}
diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php
index d837500a..e79ffcee 100644
--- a/app/ServiceProvider/ClassProvider.php
+++ b/app/ServiceProvider/ClassProvider.php
@@ -34,6 +34,7 @@ class ClassProvider implements ServiceProviderInterface
'CategoryModel',
'ColorModel',
'ColumnModel',
+ 'ColumnMoveRestrictionModel',
'CommentModel',
'ConfigModel',
'CurrencyModel',
@@ -55,6 +56,7 @@ class ClassProvider implements ServiceProviderInterface
'ProjectNotificationModel',
'ProjectMetadataModel',
'ProjectGroupRoleModel',
+ 'ProjectRoleModel',
'ProjectTaskDuplicationModel',
'ProjectTaskPriorityModel',
'ProjectUserRoleModel',
diff --git a/app/Template/board/task_private.php b/app/Template/board/task_private.php
index 94b396a6..01da46db 100644
--- a/app/Template/board/task_private.php
+++ b/app/Template/board/task_private.php
@@ -1,6 +1,7 @@
<div class="
task-board
- <?= $task['is_active'] == 1 ? ($this->user->hasProjectAccess('BoardViewController', 'save', $task['project_id']) ? 'draggable-item ' : '').'task-board-status-open '.($task['date_modification'] > (time() - $board_highlight_period) ? 'task-board-recent' : '') : 'task-board-status-closed' ?>
+ <?= $task['is_draggable'] ? 'draggable-item ' : '' ?>
+ <?= $task['is_active'] == 1 ? 'task-board-status-open '.($task['date_modification'] > (time() - $board_highlight_period) ? 'task-board-recent' : '') : 'task-board-status-closed' ?>
color-<?= $task['color_id'] ?>"
data-task-id="<?= $task['id'] ?>"
data-column-id="<?= $task['column_id'] ?>"