Skip to content

Commit 0bb707c

Browse files
authored
[5.2] Fix Permissions for Manually Running Scheduled Tasks (#36719)
1 parent ca1a8e6 commit 0bb707c

File tree

5 files changed

+58
-10
lines changed

5 files changed

+58
-10
lines changed

administrator/components/com_scheduler/src/Model/TasksModel.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ protected function getListQuery(): QueryInterface
137137
$db->quoteName('a.priority'),
138138
$db->quoteName('a.ordering'),
139139
$db->quoteName('a.note'),
140+
$db->quoteName('a.created_by'),
140141
$db->quoteName('a.checked_out'),
141142
$db->quoteName('a.checked_out_time'),
142143
]

administrator/components/com_scheduler/src/Scheduler/Scheduler.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Joomla\CMS\Factory;
1515
use Joomla\CMS\Language\Text;
1616
use Joomla\CMS\Log\Log;
17+
use Joomla\CMS\User\User;
1718
use Joomla\Component\Scheduler\Administrator\Extension\SchedulerComponent;
1819
use Joomla\Component\Scheduler\Administrator\Model\TaskModel;
1920
use Joomla\Component\Scheduler\Administrator\Model\TasksModel;
@@ -325,4 +326,31 @@ public function fetchTaskRecords(array $filters, array $listConfig): array
325326

326327
return $model->getItems() ?: [];
327328
}
329+
330+
/**
331+
* Determine whether a {@see User} is allowed to run a task record. Expects a task as an object from
332+
* {@see fetchTaskRecords}.
333+
*
334+
* @param object $taskRecord The task record to check authorization against.
335+
* @param User $user The user to check authorization for.
336+
*
337+
* @return boolean True if the user is authorized to run the task.
338+
*
339+
* @since __DEPLOY_VERSION__
340+
*/
341+
public static function isAuthorizedToRun(object $taskRecord, User $user): bool
342+
{
343+
/**
344+
* We allow the user to run a task if they have the permission or if they created the task & still have the authority
345+
* to create tasks.
346+
*/
347+
if (
348+
$user->authorise('core.testrun', 'com_scheduler.task.' . $taskRecord->id)
349+
|| ($user->id == $taskRecord->created_by && $user->authorise('core.create', 'com_scheduler'))
350+
) {
351+
return true;
352+
}
353+
354+
return false;
355+
}
328356
}

administrator/components/com_scheduler/tmpl/tasks/default.php

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Joomla\CMS\Layout\LayoutHelper;
1919
use Joomla\CMS\Router\Route;
2020
use Joomla\CMS\Session\Session;
21+
use Joomla\Component\Scheduler\Administrator\Scheduler\Scheduler;
2122
use Joomla\Component\Scheduler\Administrator\Task\Status;
2223
use Joomla\Component\Scheduler\Administrator\View\Tasks\HtmlView;
2324

@@ -257,13 +258,23 @@ class="js-draggable" data-url="<?php echo $saveOrderingUrl; ?>" data-direction="
257258

258259
<!-- Test task -->
259260
<td class="small d-none d-md-table-cell">
260-
<button type="button" class="btn btn-sm btn-warning" <?php echo $item->state < 0 ? 'disabled' : ''; ?>
261-
data-scheduler-run
262-
data-id="<?php echo (int) $item->id; ?>" data-title="<?php echo htmlspecialchars($item->title); ?>"
263-
data-url="<?php echo Route::_('index.php?option=com_ajax&format=json&plugin=RunSchedulerTest&group=system&id=' . (int) $item->id); ?>">
264-
<span class="fa fa-play fa-sm me-2"></span>
265-
<?php echo Text::_('COM_SCHEDULER_TEST_RUN'); ?>
266-
</button>
261+
<div id="run-task-btn-wrapper"
262+
<?php
263+
$disabled = ($item->state < 0 || !Scheduler::isAuthorizedToRun($item, $user));
264+
if ($disabled) :
265+
$reason = Text::_($item->state < 0 ? "COM_SCHEDULER_MANAGER_TOOLTIP_TASK_TRASHED" : "COM_SCHEDULER_MANAGER_TOOLTIP_NOT_AUTHORIZED");
266+
echo ' data-toggle="tooltip" data-placement="top" title="' . $reason . '"';
267+
endif;
268+
?>
269+
>
270+
<button type="button" class="btn btn-sm btn-warning" <?php echo $disabled ? 'disabled' : ''; ?>
271+
data-scheduler-run
272+
data-id="<?php echo (int) $item->id; ?>" data-title="<?php echo htmlspecialchars($item->title); ?>"
273+
data-url="<?php echo Route::_('index.php?option=com_ajax&format=json&plugin=RunSchedulerTest&group=system&id=' . (int) $item->id); ?>">
274+
<span class="fa fa-play fa-sm me-2"></span>
275+
<?php echo Text::_('COM_SCHEDULER_TEST_RUN'); ?>
276+
</button>
277+
</div>
267278
</td>
268279

269280
<!-- Priority -->

administrator/language/en-GB/com_scheduler.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ COM_SCHEDULER_LAST_RUN_DESC="Last Run descending"
8383
COM_SCHEDULER_MANAGER_TASKS="Scheduled Tasks"
8484
COM_SCHEDULER_MANAGER_TASK_EDIT="Edit Task"
8585
COM_SCHEDULER_MANAGER_TASK_NEW="New Task"
86+
COM_SCHEDULER_MANAGER_TOOLTIP_NOT_AUTHORIZED="Not authorized"
8687
COM_SCHEDULER_MANAGER_TOOLTIP_TASK_FAILING="Task failed. Exit code: %1$d"
88+
COM_SCHEDULER_MANAGER_TOOLTIP_TASK_TRASHED="Task has been trashed"
8789
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."
8890
COM_SCHEDULER_MSG_MANAGE_NO_TASK_PLUGINS="There are no task types matching your query."
8991
COM_SCHEDULER_NEW_TASK="New Task"

plugins/system/schedulerunner/src/Extension/ScheduleRunner.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,15 @@ public function runTestCron(Event $event)
233233
$id = (int) $this->getApplication()->getInput()->getInt('id');
234234
$allowConcurrent = $this->getApplication()->getInput()->getBool('allowConcurrent', false);
235235

236-
$user = $this->getApplication()->getIdentity();
236+
if (empty($id)) {
237+
throw new \Exception($this->getApplication()->getLanguage()->_('JERROR_ALERTNOAUTHOR'), 403);
238+
}
239+
240+
$scheduler = new Scheduler();
241+
$taskRecord = $scheduler->fetchTaskRecord($id, true);
242+
$user = $this->getApplication()->getIdentity();
237243

238-
if (empty($id) || !$user->authorise('core.testrun', 'com_scheduler.task.' . $id)) {
244+
if (empty($taskRecord) || !Scheduler::isAuthorizedToRun($taskRecord, $user)) {
239245
throw new \Exception($this->getApplication()->getLanguage()->_('JERROR_ALERTNOAUTHOR'), 403);
240246
}
241247

@@ -245,7 +251,7 @@ public function runTestCron(Event $event)
245251
* We will allow CLI exclusive tasks to be fetched and executed, it's left to routines to do a runtime check
246252
* if they want to refuse normal operation.
247253
*/
248-
$task = (new Scheduler())->getTask(
254+
$task = $scheduler->getTask(
249255
[
250256
'id' => $id,
251257
'allowDisabled' => true,

0 commit comments

Comments
 (0)