Skip to content

Commit

Permalink
[5.2] Fix Permissions for Manually Running Scheduled Tasks (#36719)
Browse files Browse the repository at this point in the history
  • Loading branch information
ditsuke authored Jan 18, 2025
1 parent ca1a8e6 commit 0bb707c
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
]
Expand Down
28 changes: 28 additions & 0 deletions administrator/components/com_scheduler/src/Scheduler/Scheduler.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
25 changes: 18 additions & 7 deletions administrator/components/com_scheduler/tmpl/tasks/default.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

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

<!-- Test task -->
<td class="small d-none d-md-table-cell">
<button type="button" class="btn btn-sm btn-warning" <?php echo $item->state < 0 ? 'disabled' : ''; ?>
data-scheduler-run
data-id="<?php echo (int) $item->id; ?>" data-title="<?php echo htmlspecialchars($item->title); ?>"
data-url="<?php echo Route::_('index.php?option=com_ajax&format=json&plugin=RunSchedulerTest&group=system&id=' . (int) $item->id); ?>">
<span class="fa fa-play fa-sm me-2"></span>
<?php echo Text::_('COM_SCHEDULER_TEST_RUN'); ?>
</button>
<div id="run-task-btn-wrapper"
<?php
$disabled = ($item->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;
?>
>
<button type="button" class="btn btn-sm btn-warning" <?php echo $disabled ? 'disabled' : ''; ?>
data-scheduler-run
data-id="<?php echo (int) $item->id; ?>" data-title="<?php echo htmlspecialchars($item->title); ?>"
data-url="<?php echo Route::_('index.php?option=com_ajax&format=json&plugin=RunSchedulerTest&group=system&id=' . (int) $item->id); ?>">
<span class="fa fa-play fa-sm me-2"></span>
<?php echo Text::_('COM_SCHEDULER_TEST_RUN'); ?>
</button>
</div>
</td>

<!-- Priority -->
Expand Down
2 changes: 2 additions & 0 deletions administrator/language/en-GB/com_scheduler.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
12 changes: 9 additions & 3 deletions plugins/system/schedulerunner/src/Extension/ScheduleRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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,
Expand Down

0 comments on commit 0bb707c

Please sign in to comment.