diff --git a/administrator/components/com_scheduler/src/Model/TasksModel.php b/administrator/components/com_scheduler/src/Model/TasksModel.php index 92bc2780ff135..d42b6879d9687 100644 --- a/administrator/components/com_scheduler/src/Model/TasksModel.php +++ b/administrator/components/com_scheduler/src/Model/TasksModel.php @@ -137,6 +137,7 @@ protected function getListQuery(): QueryInterface $db->quoteName('a.priority'), $db->quoteName('a.ordering'), $db->quoteName('a.note'), + $db->quoteName('a.created_by'), $db->quoteName('a.checked_out'), $db->quoteName('a.checked_out_time'), ] diff --git a/administrator/components/com_scheduler/src/Scheduler/Scheduler.php b/administrator/components/com_scheduler/src/Scheduler/Scheduler.php index 600d25b2da308..9aa254ed5adec 100644 --- a/administrator/components/com_scheduler/src/Scheduler/Scheduler.php +++ b/administrator/components/com_scheduler/src/Scheduler/Scheduler.php @@ -14,6 +14,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; +use Joomla\CMS\User\User; use Joomla\Component\Scheduler\Administrator\Extension\SchedulerComponent; use Joomla\Component\Scheduler\Administrator\Model\TaskModel; use Joomla\Component\Scheduler\Administrator\Model\TasksModel; @@ -325,4 +326,31 @@ public function fetchTaskRecords(array $filters, array $listConfig): array return $model->getItems() ?: []; } + + /** + * Determine whether a {@see User} is allowed to run a task record. Expects a task as an object from + * {@see fetchTaskRecords}. + * + * @param object $taskRecord The task record to check authorization against. + * @param User $user The user to check authorization for. + * + * @return boolean True if the user is authorized to run the task. + * + * @since __DEPLOY_VERSION__ + */ + public static function isAuthorizedToRun(object $taskRecord, User $user): bool + { + /** + * We allow the user to run a task if they have the permission or if they created the task & still have the authority + * to create tasks. + */ + if ( + $user->authorise('core.testrun', 'com_scheduler.task.' . $taskRecord->id) + || ($user->id == $taskRecord->created_by && $user->authorise('core.create', 'com_scheduler')) + ) { + return true; + } + + return false; + } } diff --git a/administrator/components/com_scheduler/tmpl/tasks/default.php b/administrator/components/com_scheduler/tmpl/tasks/default.php index 60ef2e27c9295..1cb5d49c3d452 100644 --- a/administrator/components/com_scheduler/tmpl/tasks/default.php +++ b/administrator/components/com_scheduler/tmpl/tasks/default.php @@ -18,6 +18,7 @@ use Joomla\CMS\Layout\LayoutHelper; use Joomla\CMS\Router\Route; use Joomla\CMS\Session\Session; +use Joomla\Component\Scheduler\Administrator\Scheduler\Scheduler; use Joomla\Component\Scheduler\Administrator\Task\Status; use Joomla\Component\Scheduler\Administrator\View\Tasks\HtmlView; @@ -257,13 +258,23 @@ class="js-draggable" data-url="" data-direction=" - +
state < 0 || !Scheduler::isAuthorizedToRun($item, $user)); + if ($disabled) : + $reason = Text::_($item->state < 0 ? "COM_SCHEDULER_MANAGER_TOOLTIP_TASK_TRASHED" : "COM_SCHEDULER_MANAGER_TOOLTIP_NOT_AUTHORIZED"); + echo ' data-toggle="tooltip" data-placement="top" title="' . $reason . '"'; + endif; + ?> + > + +
diff --git a/administrator/language/en-GB/com_scheduler.ini b/administrator/language/en-GB/com_scheduler.ini index f5eee988a7c2c..eedfd73587338 100644 --- a/administrator/language/en-GB/com_scheduler.ini +++ b/administrator/language/en-GB/com_scheduler.ini @@ -83,7 +83,9 @@ COM_SCHEDULER_LAST_RUN_DESC="Last Run descending" COM_SCHEDULER_MANAGER_TASKS="Scheduled Tasks" COM_SCHEDULER_MANAGER_TASK_EDIT="Edit Task" COM_SCHEDULER_MANAGER_TASK_NEW="New Task" +COM_SCHEDULER_MANAGER_TOOLTIP_NOT_AUTHORIZED="Not authorized" COM_SCHEDULER_MANAGER_TOOLTIP_TASK_FAILING="Task failed. Exit code: %1$d" +COM_SCHEDULER_MANAGER_TOOLTIP_TASK_TRASHED="Task has been trashed" COM_SCHEDULER_MSG_DUETASKS="There is at least one due task which should have already run. Please make sure that at least one cron scheduler is enabled and running." COM_SCHEDULER_MSG_MANAGE_NO_TASK_PLUGINS="There are no task types matching your query." COM_SCHEDULER_NEW_TASK="New Task" diff --git a/plugins/system/schedulerunner/src/Extension/ScheduleRunner.php b/plugins/system/schedulerunner/src/Extension/ScheduleRunner.php index 65438995db52b..247d67e59b7b7 100644 --- a/plugins/system/schedulerunner/src/Extension/ScheduleRunner.php +++ b/plugins/system/schedulerunner/src/Extension/ScheduleRunner.php @@ -233,9 +233,15 @@ public function runTestCron(Event $event) $id = (int) $this->getApplication()->getInput()->getInt('id'); $allowConcurrent = $this->getApplication()->getInput()->getBool('allowConcurrent', false); - $user = $this->getApplication()->getIdentity(); + if (empty($id)) { + throw new \Exception($this->getApplication()->getLanguage()->_('JERROR_ALERTNOAUTHOR'), 403); + } + + $scheduler = new Scheduler(); + $taskRecord = $scheduler->fetchTaskRecord($id, true); + $user = $this->getApplication()->getIdentity(); - if (empty($id) || !$user->authorise('core.testrun', 'com_scheduler.task.' . $id)) { + if (empty($taskRecord) || !Scheduler::isAuthorizedToRun($taskRecord, $user)) { throw new \Exception($this->getApplication()->getLanguage()->_('JERROR_ALERTNOAUTHOR'), 403); } @@ -245,7 +251,7 @@ public function runTestCron(Event $event) * We will allow CLI exclusive tasks to be fetched and executed, it's left to routines to do a runtime check * if they want to refuse normal operation. */ - $task = (new Scheduler())->getTask( + $task = $scheduler->getTask( [ 'id' => $id, 'allowDisabled' => true,