Leantime/leantime · error · Leantime\Core\Exceptions\AuthorizationException

-32001

-32001

Error message

You are not allowed to re-sort tasks.

What it means

Tickets::sortTickets() (Gantt/kanban drag-drop re-sorting) first checks the SESSION-wide role with Auth::userIsAtLeast(Roles::$editor); anyone below editor (commenter, viewer) gets AuthorizationException (JSON-RPC -32001) regardless of project membership. Note the distinction: this first gate looks at the user's global session role, while the subsequent per-ticket loop checks project-scoped access — a user can pass this gate and still fail the later assignment check.

Source

Thrown at app/Domain/Tickets/Services/Tickets.php:3443

    /**
     * Authorized JSON-RPC entry point for Gantt re-sorting of tickets/milestones.
     *
     * Enforces editor+ and per-ticket project access (the RPC endpoint has no
     * controller-level gate), then delegates to the internal updateTicketSorting().
     *
     * @param  array  $params  Array of ticketId => sortPosition from Gantt drag-drop
     * @return bool True on success (false only if the underlying write fails)
     *
     * @throws AuthorizationException If the caller is not an editor, or is not assigned to a referenced task's project
     * @throws NotFoundException If a referenced task does not exist
     *
     * @api
     */
    #[RequiresPermission(TicketsPermissions::EDIT, entityScoped: true)]
    public function sortTickets(array $params): bool
    {
        if (! Auth::userIsAtLeast(Roles::$editor)) {
            throw new AuthorizationException('You are not allowed to re-sort tasks.');
        }

        $userId = session('userdata.id');
        foreach (array_keys($params) as $ticketId) {
            $ticket = $this->getTicket((int) $ticketId);
            if (! $ticket) {
                throw new NotFoundException('A task referenced in the sort order could not be found.');
            }
            if (! $this->projectService->isUserAssignedToProject($userId, $ticket->projectId)) {
                throw new AuthorizationException('You are not allowed to re-sort this task.');
            }
        }

        return $this->updateTicketSorting($params);
    }

    /**
     * Update ticket sorting with hierarchical cascade for milestone children

View on GitHub (pinned to 9a9f49f100)

Solutions

  1. Perform sort calls with an editor+ (or higher) account
  2. Raise the user's role if they legitimately need to re-sort tasks
  3. Hide/disable drag-drop re-sorting for non-editor roles in the UI, and catch AuthorizationException (-32001) to show a clear message

Example fix

// before
$ticketsService->sortTickets($params); // fails for commenter role

// after
if (! \Leantime\Domain\Auth\Services\Auth::userIsAtLeast(\Leantime\Domain\Auth\Models\Roles::$editor)) {
    return 'Sorting requires an editor role';
}
$ticketsService->sortTickets($params);
Defensive patterns

Strategy: validation

Validate before calling

use Leantime\Domain\Auth\Models\Roles;
use Leantime\Domain\Auth\Services\Auth;

if (! Auth::userIsAtLeast(Roles::$editor)) {
    return ['error' => 'Sorting tasks requires the editor role'];
}
$ok = $ticketsService->sortTickets($params);

Try / catch

try {
    $ok = $ticketsService->sortTickets($params);
} catch (\Leantime\Core\Exceptions\AuthorizationException $e) {
    // -32001: session role below editor — disable drag-drop for this user
    $ui->disableSorting();
}

Prevention

When it happens

Trigger: A commenter or viewer account dragging tasks to re-sort; an API key whose underlying service-account user has a low role; a session carrying a stale role after the user's role was downgraded (session data predates the change).

Common situations: Drag-drop sort enabled in the UI for all roles; automations using a commenter-level API key; role downgrades that only take effect after re-login because the session still carries the old role.

Related errors


AI-assisted analysis of Leantime/leantime@9a9f49f100 (2026-08-21). Data as JSON: /api/errors/b909921fdcb04417. Report an issue: GitHub.