Apply column restrictions to the board
This commit is contained in:
@@ -28,11 +28,21 @@ class BoardAjaxController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
$values = $this->request->getJson();
|
$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(
|
$result =$this->taskPositionModel->movePosition(
|
||||||
$project_id,
|
$project_id,
|
||||||
$values['task_id'],
|
$values['task_id'],
|
||||||
$values['column_id'],
|
$values['dst_column_id'],
|
||||||
$values['position'],
|
$values['position'],
|
||||||
$values['swimlane_id']
|
$values['swimlane_id']
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,168 +10,171 @@ use Pimple\Container;
|
|||||||
* @package core
|
* @package core
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*
|
*
|
||||||
* @property \Kanboard\Analytic\TaskDistributionAnalytic $taskDistributionAnalytic
|
* @property \Kanboard\Analytic\TaskDistributionAnalytic $taskDistributionAnalytic
|
||||||
* @property \Kanboard\Analytic\UserDistributionAnalytic $userDistributionAnalytic
|
* @property \Kanboard\Analytic\UserDistributionAnalytic $userDistributionAnalytic
|
||||||
* @property \Kanboard\Analytic\EstimatedTimeComparisonAnalytic $estimatedTimeComparisonAnalytic
|
* @property \Kanboard\Analytic\EstimatedTimeComparisonAnalytic $estimatedTimeComparisonAnalytic
|
||||||
* @property \Kanboard\Analytic\AverageLeadCycleTimeAnalytic $averageLeadCycleTimeAnalytic
|
* @property \Kanboard\Analytic\AverageLeadCycleTimeAnalytic $averageLeadCycleTimeAnalytic
|
||||||
* @property \Kanboard\Analytic\AverageTimeSpentColumnAnalytic $averageTimeSpentColumnAnalytic
|
* @property \Kanboard\Analytic\AverageTimeSpentColumnAnalytic $averageTimeSpentColumnAnalytic
|
||||||
* @property \Kanboard\Core\Action\ActionManager $actionManager
|
* @property \Kanboard\Core\Action\ActionManager $actionManager
|
||||||
* @property \Kanboard\Core\ExternalLink\ExternalLinkManager $externalLinkManager
|
* @property \Kanboard\Core\ExternalLink\ExternalLinkManager $externalLinkManager
|
||||||
* @property \Kanboard\Core\Cache\MemoryCache $memoryCache
|
* @property \Kanboard\Core\Cache\MemoryCache $memoryCache
|
||||||
* @property \Kanboard\Core\Cache\BaseCache $cacheDriver
|
* @property \Kanboard\Core\Cache\BaseCache $cacheDriver
|
||||||
* @property \Kanboard\Core\Event\EventManager $eventManager
|
* @property \Kanboard\Core\Event\EventManager $eventManager
|
||||||
* @property \Kanboard\Core\Group\GroupManager $groupManager
|
* @property \Kanboard\Core\Group\GroupManager $groupManager
|
||||||
* @property \Kanboard\Core\Http\Client $httpClient
|
* @property \Kanboard\Core\Http\Client $httpClient
|
||||||
* @property \Kanboard\Core\Http\OAuth2 $oauth
|
* @property \Kanboard\Core\Http\OAuth2 $oauth
|
||||||
* @property \Kanboard\Core\Http\RememberMeCookie $rememberMeCookie
|
* @property \Kanboard\Core\Http\RememberMeCookie $rememberMeCookie
|
||||||
* @property \Kanboard\Core\Http\Request $request
|
* @property \Kanboard\Core\Http\Request $request
|
||||||
* @property \Kanboard\Core\Http\Response $response
|
* @property \Kanboard\Core\Http\Response $response
|
||||||
* @property \Kanboard\Core\Http\Router $router
|
* @property \Kanboard\Core\Http\Router $router
|
||||||
* @property \Kanboard\Core\Http\Route $route
|
* @property \Kanboard\Core\Http\Route $route
|
||||||
* @property \Kanboard\Core\Queue\QueueManager $queueManager
|
* @property \Kanboard\Core\Queue\QueueManager $queueManager
|
||||||
* @property \Kanboard\Core\Mail\Client $emailClient
|
* @property \Kanboard\Core\Mail\Client $emailClient
|
||||||
* @property \Kanboard\Core\ObjectStorage\ObjectStorageInterface $objectStorage
|
* @property \Kanboard\Core\ObjectStorage\ObjectStorageInterface $objectStorage
|
||||||
* @property \Kanboard\Core\Plugin\Hook $hook
|
* @property \Kanboard\Core\Plugin\Hook $hook
|
||||||
* @property \Kanboard\Core\Plugin\Loader $pluginLoader
|
* @property \Kanboard\Core\Plugin\Loader $pluginLoader
|
||||||
* @property \Kanboard\Core\Security\AuthenticationManager $authenticationManager
|
* @property \Kanboard\Core\Security\AuthenticationManager $authenticationManager
|
||||||
* @property \Kanboard\Core\Security\AccessMap $applicationAccessMap
|
* @property \Kanboard\Core\Security\AccessMap $applicationAccessMap
|
||||||
* @property \Kanboard\Core\Security\AccessMap $projectAccessMap
|
* @property \Kanboard\Core\Security\AccessMap $projectAccessMap
|
||||||
* @property \Kanboard\Core\Security\AccessMap $apiAccessMap
|
* @property \Kanboard\Core\Security\AccessMap $apiAccessMap
|
||||||
* @property \Kanboard\Core\Security\AccessMap $apiProjectAccessMap
|
* @property \Kanboard\Core\Security\AccessMap $apiProjectAccessMap
|
||||||
* @property \Kanboard\Core\Security\Authorization $applicationAuthorization
|
* @property \Kanboard\Core\Security\Authorization $applicationAuthorization
|
||||||
* @property \Kanboard\Core\Security\Authorization $projectAuthorization
|
* @property \Kanboard\Core\Security\Authorization $projectAuthorization
|
||||||
* @property \Kanboard\Core\Security\Authorization $apiAuthorization
|
* @property \Kanboard\Core\Security\Authorization $apiAuthorization
|
||||||
* @property \Kanboard\Core\Security\Authorization $apiProjectAuthorization
|
* @property \Kanboard\Core\Security\Authorization $apiProjectAuthorization
|
||||||
* @property \Kanboard\Core\Security\Role $role
|
* @property \Kanboard\Core\Security\Role $role
|
||||||
* @property \Kanboard\Core\Security\Token $token
|
* @property \Kanboard\Core\Security\Token $token
|
||||||
* @property \Kanboard\Core\Session\FlashMessage $flash
|
* @property \Kanboard\Core\Session\FlashMessage $flash
|
||||||
* @property \Kanboard\Core\Session\SessionManager $sessionManager
|
* @property \Kanboard\Core\Session\SessionManager $sessionManager
|
||||||
* @property \Kanboard\Core\Session\SessionStorage $sessionStorage
|
* @property \Kanboard\Core\Session\SessionStorage $sessionStorage
|
||||||
* @property \Kanboard\Core\User\Avatar\AvatarManager $avatarManager
|
* @property \Kanboard\Core\User\Avatar\AvatarManager $avatarManager
|
||||||
* @property \Kanboard\Core\User\GroupSync $groupSync
|
* @property \Kanboard\Core\User\GroupSync $groupSync
|
||||||
* @property \Kanboard\Core\User\UserProfile $userProfile
|
* @property \Kanboard\Core\User\UserProfile $userProfile
|
||||||
* @property \Kanboard\Core\User\UserSync $userSync
|
* @property \Kanboard\Core\User\UserSync $userSync
|
||||||
* @property \Kanboard\Core\User\UserSession $userSession
|
* @property \Kanboard\Core\User\UserSession $userSession
|
||||||
* @property \Kanboard\Core\DateParser $dateParser
|
* @property \Kanboard\Core\DateParser $dateParser
|
||||||
* @property \Kanboard\Core\Helper $helper
|
* @property \Kanboard\Core\Helper $helper
|
||||||
* @property \Kanboard\Core\Paginator $paginator
|
* @property \Kanboard\Core\Paginator $paginator
|
||||||
* @property \Kanboard\Core\Template $template
|
* @property \Kanboard\Core\Template $template
|
||||||
* @property \Kanboard\Decorator\MetadataCacheDecorator $userMetadataCacheDecorator
|
* @property \Kanboard\Decorator\MetadataCacheDecorator $userMetadataCacheDecorator
|
||||||
* @property \Kanboard\Model\ActionModel $actionModel
|
* @property \Kanboard\Decorator\ColumnMoveRestrictionCacheDecorator $columnMoveRestrictionCacheDecorator
|
||||||
* @property \Kanboard\Model\ActionParameterModel $actionParameterModel
|
* @property \Kanboard\Model\ActionModel $actionModel
|
||||||
* @property \Kanboard\Model\AvatarFileModel $avatarFileModel
|
* @property \Kanboard\Model\ActionParameterModel $actionParameterModel
|
||||||
* @property \Kanboard\Model\BoardModel $boardModel
|
* @property \Kanboard\Model\AvatarFileModel $avatarFileModel
|
||||||
* @property \Kanboard\Model\CategoryModel $categoryModel
|
* @property \Kanboard\Model\BoardModel $boardModel
|
||||||
* @property \Kanboard\Model\ColorModel $colorModel
|
* @property \Kanboard\Model\CategoryModel $categoryModel
|
||||||
* @property \Kanboard\Model\ColumnModel $columnModel
|
* @property \Kanboard\Model\ColorModel $colorModel
|
||||||
* @property \Kanboard\Model\CommentModel $commentModel
|
* @property \Kanboard\Model\ColumnModel $columnModel
|
||||||
* @property \Kanboard\Model\ConfigModel $configModel
|
* @property \Kanboard\Model\ColumnMoveRestrictionModel $columnMoveRestrictionModel
|
||||||
* @property \Kanboard\Model\CurrencyModel $currencyModel
|
* @property \Kanboard\Model\CommentModel $commentModel
|
||||||
* @property \Kanboard\Model\CustomFilterModel $customFilterModel
|
* @property \Kanboard\Model\ConfigModel $configModel
|
||||||
* @property \Kanboard\Model\TaskFileModel $taskFileModel
|
* @property \Kanboard\Model\CurrencyModel $currencyModel
|
||||||
* @property \Kanboard\Model\ProjectFileModel $projectFileModel
|
* @property \Kanboard\Model\CustomFilterModel $customFilterModel
|
||||||
* @property \Kanboard\Model\GroupModel $groupModel
|
* @property \Kanboard\Model\TaskFileModel $taskFileModel
|
||||||
* @property \Kanboard\Model\GroupMemberModel $groupMemberModel
|
* @property \Kanboard\Model\ProjectFileModel $projectFileModel
|
||||||
* @property \Kanboard\Model\LanguageModel $languageModel
|
* @property \Kanboard\Model\GroupModel $groupModel
|
||||||
* @property \Kanboard\Model\LastLoginModel $lastLoginModel
|
* @property \Kanboard\Model\GroupMemberModel $groupMemberModel
|
||||||
* @property \Kanboard\Model\LinkModel $linkModel
|
* @property \Kanboard\Model\LanguageModel $languageModel
|
||||||
* @property \Kanboard\Model\NotificationModel $notificationModel
|
* @property \Kanboard\Model\LastLoginModel $lastLoginModel
|
||||||
* @property \Kanboard\Model\PasswordResetModel $passwordResetModel
|
* @property \Kanboard\Model\LinkModel $linkModel
|
||||||
* @property \Kanboard\Model\ProjectModel $projectModel
|
* @property \Kanboard\Model\NotificationModel $notificationModel
|
||||||
* @property \Kanboard\Model\ProjectActivityModel $projectActivityModel
|
* @property \Kanboard\Model\PasswordResetModel $passwordResetModel
|
||||||
* @property \Kanboard\Model\ProjectDuplicationModel $projectDuplicationModel
|
* @property \Kanboard\Model\ProjectModel $projectModel
|
||||||
* @property \Kanboard\Model\ProjectDailyColumnStatsModel $projectDailyColumnStatsModel
|
* @property \Kanboard\Model\ProjectActivityModel $projectActivityModel
|
||||||
* @property \Kanboard\Model\ProjectDailyStatsModel $projectDailyStatsModel
|
* @property \Kanboard\Model\ProjectDuplicationModel $projectDuplicationModel
|
||||||
* @property \Kanboard\Model\ProjectMetadataModel $projectMetadataModel
|
* @property \Kanboard\Model\ProjectDailyColumnStatsModel $projectDailyColumnStatsModel
|
||||||
* @property \Kanboard\Model\ProjectPermissionModel $projectPermissionModel
|
* @property \Kanboard\Model\ProjectDailyStatsModel $projectDailyStatsModel
|
||||||
* @property \Kanboard\Model\ProjectUserRoleModel $projectUserRoleModel
|
* @property \Kanboard\Model\ProjectMetadataModel $projectMetadataModel
|
||||||
* @property \Kanboard\Model\ProjectGroupRoleModel $projectGroupRoleModel
|
* @property \Kanboard\Model\ProjectPermissionModel $projectPermissionModel
|
||||||
* @property \Kanboard\Model\ProjectNotificationModel $projectNotificationModel
|
* @property \Kanboard\Model\ProjectUserRoleModel $projectUserRoleModel
|
||||||
* @property \Kanboard\Model\ProjectNotificationTypeModel $projectNotificationTypeModel
|
* @property \Kanboard\Model\ProjectGroupRoleModel $projectGroupRoleModel
|
||||||
* @property \Kanboard\Model\ProjectTaskDuplicationModel $projectTaskDuplicationModel
|
* @property \Kanboard\Model\ProjectNotificationModel $projectNotificationModel
|
||||||
* @property \Kanboard\Model\ProjectTaskPriorityModel $projectTaskPriorityModel
|
* @property \Kanboard\Model\ProjectNotificationTypeModel $projectNotificationTypeModel
|
||||||
* @property \Kanboard\Model\RememberMeSessionModel $rememberMeSessionModel
|
* @property \Kanboard\Model\ProjectRoleModel $projectRoleModel
|
||||||
* @property \Kanboard\Model\SubtaskModel $subtaskModel
|
* @property \Kanboard\Model\ProjectTaskDuplicationModel $projectTaskDuplicationModel
|
||||||
* @property \Kanboard\Model\SubtaskPositionModel $subtaskPositionModel
|
* @property \Kanboard\Model\ProjectTaskPriorityModel $projectTaskPriorityModel
|
||||||
* @property \Kanboard\Model\SubtaskStatusModel $subtaskStatusModel
|
* @property \Kanboard\Model\RememberMeSessionModel $rememberMeSessionModel
|
||||||
* @property \Kanboard\Model\SubtaskTaskConversionModel $subtaskTaskConversionModel
|
* @property \Kanboard\Model\SubtaskModel $subtaskModel
|
||||||
* @property \Kanboard\Model\SubtaskTimeTrackingModel $subtaskTimeTrackingModel
|
* @property \Kanboard\Model\SubtaskPositionModel $subtaskPositionModel
|
||||||
* @property \Kanboard\Model\SwimlaneModel $swimlaneModel
|
* @property \Kanboard\Model\SubtaskStatusModel $subtaskStatusModel
|
||||||
* @property \Kanboard\Model\TagDuplicationModel $tagDuplicationModel
|
* @property \Kanboard\Model\SubtaskTaskConversionModel $subtaskTaskConversionModel
|
||||||
* @property \Kanboard\Model\TagModel $tagModel
|
* @property \Kanboard\Model\SubtaskTimeTrackingModel $subtaskTimeTrackingModel
|
||||||
* @property \Kanboard\Model\TaskModel $taskModel
|
* @property \Kanboard\Model\SwimlaneModel $swimlaneModel
|
||||||
* @property \Kanboard\Model\TaskAnalyticModel $taskAnalyticModel
|
* @property \Kanboard\Model\TagDuplicationModel $tagDuplicationModel
|
||||||
* @property \Kanboard\Model\TaskCreationModel $taskCreationModel
|
* @property \Kanboard\Model\TagModel $tagModel
|
||||||
* @property \Kanboard\Model\TaskDuplicationModel $taskDuplicationModel
|
* @property \Kanboard\Model\TaskModel $taskModel
|
||||||
* @property \Kanboard\Model\TaskProjectDuplicationModel $taskProjectDuplicationModel
|
* @property \Kanboard\Model\TaskAnalyticModel $taskAnalyticModel
|
||||||
* @property \Kanboard\Model\TaskProjectMoveModel $taskProjectMoveModel
|
* @property \Kanboard\Model\TaskCreationModel $taskCreationModel
|
||||||
* @property \Kanboard\Model\TaskRecurrenceModel $taskRecurrenceModel
|
* @property \Kanboard\Model\TaskDuplicationModel $taskDuplicationModel
|
||||||
* @property \Kanboard\Model\TaskExternalLinkModel $taskExternalLinkModel
|
* @property \Kanboard\Model\TaskProjectDuplicationModel $taskProjectDuplicationModel
|
||||||
* @property \Kanboard\Model\TaskFinderModel $taskFinderModel
|
* @property \Kanboard\Model\TaskProjectMoveModel $taskProjectMoveModel
|
||||||
* @property \Kanboard\Model\TaskLinkModel $taskLinkModel
|
* @property \Kanboard\Model\TaskRecurrenceModel $taskRecurrenceModel
|
||||||
* @property \Kanboard\Model\TaskModificationModel $taskModificationModel
|
* @property \Kanboard\Model\TaskExternalLinkModel $taskExternalLinkModel
|
||||||
* @property \Kanboard\Model\TaskPositionModel $taskPositionModel
|
* @property \Kanboard\Model\TaskFinderModel $taskFinderModel
|
||||||
* @property \Kanboard\Model\TaskStatusModel $taskStatusModel
|
* @property \Kanboard\Model\TaskLinkModel $taskLinkModel
|
||||||
* @property \Kanboard\Model\TaskTagModel $taskTagModel
|
* @property \Kanboard\Model\TaskModificationModel $taskModificationModel
|
||||||
* @property \Kanboard\Model\TaskMetadataModel $taskMetadataModel
|
* @property \Kanboard\Model\TaskPositionModel $taskPositionModel
|
||||||
* @property \Kanboard\Model\TimezoneModel $timezoneModel
|
* @property \Kanboard\Model\TaskStatusModel $taskStatusModel
|
||||||
* @property \Kanboard\Model\TransitionModel $transitionModel
|
* @property \Kanboard\Model\TaskTagModel $taskTagModel
|
||||||
* @property \Kanboard\Model\UserModel $userModel
|
* @property \Kanboard\Model\TaskMetadataModel $taskMetadataModel
|
||||||
* @property \Kanboard\Model\UserLockingModel $userLockingModel
|
* @property \Kanboard\Model\TimezoneModel $timezoneModel
|
||||||
* @property \Kanboard\Model\UserMentionModel $userMentionModel
|
* @property \Kanboard\Model\TransitionModel $transitionModel
|
||||||
* @property \Kanboard\Model\UserNotificationModel $userNotificationModel
|
* @property \Kanboard\Model\UserModel $userModel
|
||||||
* @property \Kanboard\Model\UserNotificationTypeModel $userNotificationTypeModel
|
* @property \Kanboard\Model\UserLockingModel $userLockingModel
|
||||||
* @property \Kanboard\Model\UserNotificationFilterModel $userNotificationFilterModel
|
* @property \Kanboard\Model\UserMentionModel $userMentionModel
|
||||||
* @property \Kanboard\Model\UserUnreadNotificationModel $userUnreadNotificationModel
|
* @property \Kanboard\Model\UserNotificationModel $userNotificationModel
|
||||||
* @property \Kanboard\Model\UserMetadataModel $userMetadataModel
|
* @property \Kanboard\Model\UserNotificationTypeModel $userNotificationTypeModel
|
||||||
* @property \Kanboard\Pagination\TaskPagination $taskPagination
|
* @property \Kanboard\Model\UserNotificationFilterModel $userNotificationFilterModel
|
||||||
* @property \Kanboard\Pagination\SubtaskPagination $subtaskPagination
|
* @property \Kanboard\Model\UserUnreadNotificationModel $userUnreadNotificationModel
|
||||||
* @property \Kanboard\Pagination\ProjectPagination $projectPagination
|
* @property \Kanboard\Model\UserMetadataModel $userMetadataModel
|
||||||
* @property \Kanboard\Pagination\UserPagination $userPagination
|
* @property \Kanboard\Pagination\TaskPagination $taskPagination
|
||||||
* @property \Kanboard\Validator\ActionValidator $actionValidator
|
* @property \Kanboard\Pagination\SubtaskPagination $subtaskPagination
|
||||||
* @property \Kanboard\Validator\AuthValidator $authValidator
|
* @property \Kanboard\Pagination\ProjectPagination $projectPagination
|
||||||
* @property \Kanboard\Validator\ColumnValidator $columnValidator
|
* @property \Kanboard\Pagination\UserPagination $userPagination
|
||||||
* @property \Kanboard\Validator\CategoryValidator $categoryValidator
|
* @property \Kanboard\Validator\ActionValidator $actionValidator
|
||||||
* @property \Kanboard\Validator\CommentValidator $commentValidator
|
* @property \Kanboard\Validator\AuthValidator $authValidator
|
||||||
* @property \Kanboard\Validator\CurrencyValidator $currencyValidator
|
* @property \Kanboard\Validator\ColumnValidator $columnValidator
|
||||||
* @property \Kanboard\Validator\CustomFilterValidator $customFilterValidator
|
* @property \Kanboard\Validator\CategoryValidator $categoryValidator
|
||||||
* @property \Kanboard\Validator\ExternalLinkValidator $externalLinkValidator
|
* @property \Kanboard\Validator\CommentValidator $commentValidator
|
||||||
* @property \Kanboard\Validator\GroupValidator $groupValidator
|
* @property \Kanboard\Validator\CurrencyValidator $currencyValidator
|
||||||
* @property \Kanboard\Validator\LinkValidator $linkValidator
|
* @property \Kanboard\Validator\CustomFilterValidator $customFilterValidator
|
||||||
* @property \Kanboard\Validator\PasswordResetValidator $passwordResetValidator
|
* @property \Kanboard\Validator\ExternalLinkValidator $externalLinkValidator
|
||||||
* @property \Kanboard\Validator\ProjectValidator $projectValidator
|
* @property \Kanboard\Validator\GroupValidator $groupValidator
|
||||||
* @property \Kanboard\Validator\SubtaskValidator $subtaskValidator
|
* @property \Kanboard\Validator\LinkValidator $linkValidator
|
||||||
* @property \Kanboard\Validator\SwimlaneValidator $swimlaneValidator
|
* @property \Kanboard\Validator\PasswordResetValidator $passwordResetValidator
|
||||||
* @property \Kanboard\Validator\TagValidator $tagValidator
|
* @property \Kanboard\Validator\ProjectValidator $projectValidator
|
||||||
* @property \Kanboard\Validator\TaskLinkValidator $taskLinkValidator
|
* @property \Kanboard\Validator\SubtaskValidator $subtaskValidator
|
||||||
* @property \Kanboard\Validator\TaskValidator $taskValidator
|
* @property \Kanboard\Validator\SwimlaneValidator $swimlaneValidator
|
||||||
* @property \Kanboard\Validator\UserValidator $userValidator
|
* @property \Kanboard\Validator\TagValidator $tagValidator
|
||||||
* @property \Kanboard\Import\TaskImport $taskImport
|
* @property \Kanboard\Validator\TaskLinkValidator $taskLinkValidator
|
||||||
* @property \Kanboard\Import\UserImport $userImport
|
* @property \Kanboard\Validator\TaskValidator $taskValidator
|
||||||
* @property \Kanboard\Export\SubtaskExport $subtaskExport
|
* @property \Kanboard\Validator\UserValidator $userValidator
|
||||||
* @property \Kanboard\Export\TaskExport $taskExport
|
* @property \Kanboard\Import\TaskImport $taskImport
|
||||||
* @property \Kanboard\Export\TransitionExport $transitionExport
|
* @property \Kanboard\Import\UserImport $userImport
|
||||||
* @property \Kanboard\Core\Filter\QueryBuilder $projectGroupRoleQuery
|
* @property \Kanboard\Export\SubtaskExport $subtaskExport
|
||||||
* @property \Kanboard\Core\Filter\QueryBuilder $projectUserRoleQuery
|
* @property \Kanboard\Export\TaskExport $taskExport
|
||||||
* @property \Kanboard\Core\Filter\QueryBuilder $projectActivityQuery
|
* @property \Kanboard\Export\TransitionExport $transitionExport
|
||||||
* @property \Kanboard\Core\Filter\QueryBuilder $userQuery
|
* @property \Kanboard\Core\Filter\QueryBuilder $projectGroupRoleQuery
|
||||||
* @property \Kanboard\Core\Filter\QueryBuilder $projectQuery
|
* @property \Kanboard\Core\Filter\QueryBuilder $projectUserRoleQuery
|
||||||
* @property \Kanboard\Core\Filter\QueryBuilder $taskQuery
|
* @property \Kanboard\Core\Filter\QueryBuilder $projectActivityQuery
|
||||||
* @property \Kanboard\Core\Filter\LexerBuilder $taskLexer
|
* @property \Kanboard\Core\Filter\QueryBuilder $userQuery
|
||||||
* @property \Kanboard\Core\Filter\LexerBuilder $projectActivityLexer
|
* @property \Kanboard\Core\Filter\QueryBuilder $projectQuery
|
||||||
* @property \Kanboard\Job\CommentEventJob $commentEventJob
|
* @property \Kanboard\Core\Filter\QueryBuilder $taskQuery
|
||||||
* @property \Kanboard\Job\SubtaskEventJob $subtaskEventJob
|
* @property \Kanboard\Core\Filter\LexerBuilder $taskLexer
|
||||||
* @property \Kanboard\Job\TaskEventJob $taskEventJob
|
* @property \Kanboard\Core\Filter\LexerBuilder $projectActivityLexer
|
||||||
* @property \Kanboard\Job\TaskFileEventJob $taskFileEventJob
|
* @property \Kanboard\Job\CommentEventJob $commentEventJob
|
||||||
* @property \Kanboard\Job\TaskLinkEventJob $taskLinkEventJob
|
* @property \Kanboard\Job\SubtaskEventJob $subtaskEventJob
|
||||||
* @property \Kanboard\Job\ProjectFileEventJob $projectFileEventJob
|
* @property \Kanboard\Job\TaskEventJob $taskEventJob
|
||||||
* @property \Kanboard\Job\NotificationJob $notificationJob
|
* @property \Kanboard\Job\TaskFileEventJob $taskFileEventJob
|
||||||
* @property \Kanboard\Job\ProjectMetricJob $projectMetricJob
|
* @property \Kanboard\Job\TaskLinkEventJob $taskLinkEventJob
|
||||||
* @property \Psr\Log\LoggerInterface $logger
|
* @property \Kanboard\Job\ProjectFileEventJob $projectFileEventJob
|
||||||
* @property \PicoDb\Database $db
|
* @property \Kanboard\Job\NotificationJob $notificationJob
|
||||||
* @property \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher
|
* @property \Kanboard\Job\ProjectMetricJob $projectMetricJob
|
||||||
* @property \Symfony\Component\Console\Application $cli
|
* @property \Psr\Log\LoggerInterface $logger
|
||||||
* @property \JsonRPC\Server $api
|
* @property \PicoDb\Database $db
|
||||||
|
* @property \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher
|
||||||
|
* @property \Symfony\Component\Console\Application $cli
|
||||||
|
* @property \JsonRPC\Server $api
|
||||||
*/
|
*/
|
||||||
abstract class Base
|
abstract class Base
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use Pimple\Container;
|
|||||||
*
|
*
|
||||||
* @property \Kanboard\Helper\AppHelper $app
|
* @property \Kanboard\Helper\AppHelper $app
|
||||||
* @property \Kanboard\Helper\AssetHelper $asset
|
* @property \Kanboard\Helper\AssetHelper $asset
|
||||||
|
* @property \Kanboard\Helper\BoardHelper $board
|
||||||
* @property \Kanboard\Helper\CalendarHelper $calendar
|
* @property \Kanboard\Helper\CalendarHelper $calendar
|
||||||
* @property \Kanboard\Helper\DateHelper $dt
|
* @property \Kanboard\Helper\DateHelper $dt
|
||||||
* @property \Kanboard\Helper\FileHelper $file
|
* @property \Kanboard\Helper\FileHelper $file
|
||||||
|
|||||||
57
app/Decorator/ColumnMoveRestrictionCacheDecorator.php
Normal file
57
app/Decorator/ColumnMoveRestrictionCacheDecorator.php
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -79,6 +79,11 @@ class BoardTaskFormatter extends BaseFormatter implements FormatterInterface
|
|||||||
{
|
{
|
||||||
$tasks = array_values(array_filter($this->tasks, array($this, 'filterTasks')));
|
$tasks = array_values(array_filter($this->tasks, array($this, 'filterTasks')));
|
||||||
array_merge_relation($tasks, $this->tags, 'tags', 'id');
|
array_merge_relation($tasks, $this->tags, 'tags', 'id');
|
||||||
|
|
||||||
|
foreach ($tasks as &$task) {
|
||||||
|
$task['is_draggable'] = $this->helper->board->isDraggable($task);
|
||||||
|
}
|
||||||
|
|
||||||
return $tasks;
|
return $tasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,4 +24,20 @@ class BoardHelper extends Base
|
|||||||
{
|
{
|
||||||
return $this->userMetadataCacheDecorator->get(UserMetadataModel::KEY_BOARD_COLLAPSED.$project_id, 0) == 1;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ class ColumnMoveRestrictionModel extends Base
|
|||||||
*/
|
*/
|
||||||
public function getAll($project_id)
|
public function getAll($project_id)
|
||||||
{
|
{
|
||||||
return $this->db->table(self::TABLE)
|
return $this->db
|
||||||
|
->table(self::TABLE)
|
||||||
->columns(
|
->columns(
|
||||||
'restriction_id',
|
'restriction_id',
|
||||||
'src_column_id',
|
'src_column_id',
|
||||||
@@ -58,6 +59,20 @@ class ColumnMoveRestrictionModel extends Base
|
|||||||
->findAll();
|
->findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* Create a new column restriction
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace Kanboard\ServiceProvider;
|
|||||||
|
|
||||||
use Kanboard\Core\Cache\FileCache;
|
use Kanboard\Core\Cache\FileCache;
|
||||||
use Kanboard\Core\Cache\MemoryCache;
|
use Kanboard\Core\Cache\MemoryCache;
|
||||||
|
use Kanboard\Decorator\ColumnMoveRestrictionCacheDecorator;
|
||||||
use Kanboard\Decorator\MetadataCacheDecorator;
|
use Kanboard\Decorator\MetadataCacheDecorator;
|
||||||
use Pimple\Container;
|
use Pimple\Container;
|
||||||
use Pimple\ServiceProviderInterface;
|
use Pimple\ServiceProviderInterface;
|
||||||
@@ -46,6 +47,13 @@ class CacheProvider implements ServiceProviderInterface
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$container['columnMoveRestrictionCacheDecorator'] = function($c) {
|
||||||
|
return new ColumnMoveRestrictionCacheDecorator(
|
||||||
|
$c['memoryCache'],
|
||||||
|
$c['columnMoveRestrictionModel']
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return $container;
|
return $container;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ class ClassProvider implements ServiceProviderInterface
|
|||||||
'CategoryModel',
|
'CategoryModel',
|
||||||
'ColorModel',
|
'ColorModel',
|
||||||
'ColumnModel',
|
'ColumnModel',
|
||||||
|
'ColumnMoveRestrictionModel',
|
||||||
'CommentModel',
|
'CommentModel',
|
||||||
'ConfigModel',
|
'ConfigModel',
|
||||||
'CurrencyModel',
|
'CurrencyModel',
|
||||||
@@ -55,6 +56,7 @@ class ClassProvider implements ServiceProviderInterface
|
|||||||
'ProjectNotificationModel',
|
'ProjectNotificationModel',
|
||||||
'ProjectMetadataModel',
|
'ProjectMetadataModel',
|
||||||
'ProjectGroupRoleModel',
|
'ProjectGroupRoleModel',
|
||||||
|
'ProjectRoleModel',
|
||||||
'ProjectTaskDuplicationModel',
|
'ProjectTaskDuplicationModel',
|
||||||
'ProjectTaskPriorityModel',
|
'ProjectTaskPriorityModel',
|
||||||
'ProjectUserRoleModel',
|
'ProjectUserRoleModel',
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<div class="
|
<div class="
|
||||||
task-board
|
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'] ?>"
|
color-<?= $task['color_id'] ?>"
|
||||||
data-task-id="<?= $task['id'] ?>"
|
data-task-id="<?= $task['id'] ?>"
|
||||||
data-column-id="<?= $task['column_id'] ?>"
|
data-column-id="<?= $task['column_id'] ?>"
|
||||||
|
|||||||
2
assets/js/app.min.js
vendored
2
assets/js/app.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -34,7 +34,7 @@ Kanboard.BoardDragAndDrop.prototype.dragAndDrop = function() {
|
|||||||
|
|
||||||
if (newColumnId != taskColumnId || newSwimlaneId != taskSwimlaneId || newPosition != taskPosition) {
|
if (newColumnId != taskColumnId || newSwimlaneId != taskSwimlaneId || newPosition != taskPosition) {
|
||||||
self.changeTaskState(taskId);
|
self.changeTaskState(taskId);
|
||||||
self.save(taskId, newColumnId, newPosition, newSwimlaneId);
|
self.save(taskId, taskColumnId, newColumnId, newPosition, newSwimlaneId);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
start: function(event, ui) {
|
start: function(event, ui) {
|
||||||
@@ -62,7 +62,7 @@ Kanboard.BoardDragAndDrop.prototype.changeTaskState = function(taskId) {
|
|||||||
task.find('.task-board-saving-icon').show();
|
task.find('.task-board-saving-icon').show();
|
||||||
};
|
};
|
||||||
|
|
||||||
Kanboard.BoardDragAndDrop.prototype.save = function(taskId, columnId, position, swimlaneId) {
|
Kanboard.BoardDragAndDrop.prototype.save = function(taskId, srcColumnId, dstColumnId, position, swimlaneId) {
|
||||||
var self = this;
|
var self = this;
|
||||||
self.app.showLoadingIcon();
|
self.app.showLoadingIcon();
|
||||||
self.savingInProgress = true;
|
self.savingInProgress = true;
|
||||||
@@ -75,7 +75,8 @@ Kanboard.BoardDragAndDrop.prototype.save = function(taskId, columnId, position,
|
|||||||
processData: false,
|
processData: false,
|
||||||
data: JSON.stringify({
|
data: JSON.stringify({
|
||||||
"task_id": taskId,
|
"task_id": taskId,
|
||||||
"column_id": columnId,
|
"src_column_id": srcColumnId,
|
||||||
|
"dst_column_id": dstColumnId,
|
||||||
"swimlane_id": swimlaneId,
|
"swimlane_id": swimlaneId,
|
||||||
"position": position
|
"position": position
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ class BoardFormatterTest extends Base
|
|||||||
$this->assertSame(0, $board[2]['columns'][3]['nb_tasks']);
|
$this->assertSame(0, $board[2]['columns'][3]['nb_tasks']);
|
||||||
|
|
||||||
$this->assertEquals('Task 8', $board[2]['columns'][2]['tasks'][0]['title']);
|
$this->assertEquals('Task 8', $board[2]['columns'][2]['tasks'][0]['title']);
|
||||||
|
$this->assertArrayHasKey('is_draggable', $board[2]['columns'][2]['tasks'][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testFormatWithoutDefaultSwimlane()
|
public function testFormatWithoutDefaultSwimlane()
|
||||||
|
|||||||
94
tests/units/Helper/BoardHelperTest.php
Normal file
94
tests/units/Helper/BoardHelperTest.php
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Kanboard\Core\Security\Role;
|
||||||
|
use Kanboard\Helper\BoardHelper;
|
||||||
|
use Kanboard\Model\ColumnMoveRestrictionModel;
|
||||||
|
use Kanboard\Model\ProjectModel;
|
||||||
|
use Kanboard\Model\ProjectRoleModel;
|
||||||
|
use Kanboard\Model\ProjectUserRoleModel;
|
||||||
|
use Kanboard\Model\TaskCreationModel;
|
||||||
|
use Kanboard\Model\TaskFinderModel;
|
||||||
|
use Kanboard\Model\TaskStatusModel;
|
||||||
|
use Kanboard\Model\UserModel;
|
||||||
|
|
||||||
|
require_once __DIR__.'/../Base.php';
|
||||||
|
|
||||||
|
class BoardHelperTest extends Base
|
||||||
|
{
|
||||||
|
public function testIsDraggableWithProjectMember()
|
||||||
|
{
|
||||||
|
$boardHelper = new BoardHelper($this->container);
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$taskCreationModel = new TaskCreationModel($this->container);
|
||||||
|
$taskFinderModel = new TaskFinderModel($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->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test')));
|
||||||
|
|
||||||
|
$task = $taskFinderModel->getById(1);
|
||||||
|
$this->assertTrue($boardHelper->isDraggable($task));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsDraggableWithClosedTask()
|
||||||
|
{
|
||||||
|
$boardHelper = new BoardHelper($this->container);
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$taskCreationModel = new TaskCreationModel($this->container);
|
||||||
|
$taskFinderModel = new TaskFinderModel($this->container);
|
||||||
|
$taskStatusModel = new TaskStatusModel($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->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test')));
|
||||||
|
$this->assertTrue($taskStatusModel->close(1));
|
||||||
|
|
||||||
|
$task = $taskFinderModel->getById(1);
|
||||||
|
$this->assertFalse($boardHelper->isDraggable($task));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsDraggableWithColumnRestrictions()
|
||||||
|
{
|
||||||
|
$boardHelper = new BoardHelper($this->container);
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$taskCreationModel = new TaskCreationModel($this->container);
|
||||||
|
$taskFinderModel = new TaskFinderModel($this->container);
|
||||||
|
$projectUserRole = new ProjectUserRoleModel($this->container);
|
||||||
|
$userModel = new UserModel($this->container);
|
||||||
|
$projectRoleModel = new ProjectRoleModel($this->container);
|
||||||
|
$columnMoveRestrictionModel = new ColumnMoveRestrictionModel($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->assertEquals(1, $columnMoveRestrictionModel->create(1, 1, 2, 3));
|
||||||
|
|
||||||
|
$this->assertTrue($projectUserRole->addUser(1, 2, 'Custom Role'));
|
||||||
|
$this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test', 'column_id' => 2)));
|
||||||
|
|
||||||
|
$task = $taskFinderModel->getById(1);
|
||||||
|
$this->assertFalse($boardHelper->isDraggable($task));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user