Blogs Engineering

A Dead Edit Link in Leantime's Ideas Kanban, Fixed and Verified

Leantime's Ideas Kanban 'Edit' option never opened a dialog. The merged fix reuses the working route and tightens the permission check.

PHPLeantime/leantimeproject managementUI bugauthorization

A two-line change, a permission question raised in review, and a maintainer who checked both.

Short answer

In Leantime's Ideas module, choosing "Edit" from the board menu worked in Idea Wall view but did nothing in Idea Kanban view. The fix points the Kanban link at the same hash-routed board dialog the Idea Wall uses. During review it also raised the permission on the dialog's write endpoint from view to edit. It was merged as PR #3752 and closed issue #3743.

The problem

Leantime is an open-source project management system. Issue #3743 described it simply. In "Ideas" under "Think", Idea Wall's "Edit" opens a modal to rename the board. Switch to Idea Kanban, choose "Edit", and no modal opens.

Root cause

The Kanban template rendered <a href="javascript:void(0)" class="editCanvasLink">, relying on a JavaScript handler to open the modal. According to the PR description, the Ideas controller's handler for that class had an empty body. The maintainer confirmed it when merging: ".editCanvasLink is bound in blueprintsController.js and canvasController.js, but ideasController.js never had that binding", so "the Ideas board's Edit link was genuinely dead."

The fix

-<li><a href="javascript:void(0)" class="editCanvasLink ">{!! __('links.icon.edit') !!}</a></li>
+<li><a href="#/ideas/boardDialog/{{ $currentCanvas }}">{!! __('links.icon.edit') !!}</a></li>
-    #[RequiresPermission(IdeasPermissions::VIEW)]
+    #[RequiresPermission(IdeasPermissions::EDIT, entityScoped: true)]
     public function post(array $params): Response

By the numbers

  • Repository: Leantime/leantime, 11,958 stars (Nov 3, 2026), PHP, AGPL-3.0
  • Files changed: 2
  • Lines: +2 / -2
  • Commits: 2
  • Opened: Aug 21, 2026. Merged: Sep 7, 2026. Time to merge: 17 days
  • Review: approved and merged by a maintainer; CLA signed

How the review went

An automated reviewer pointed out that routing the link to BoardDialog exposed an existing gap. Its post() handler, which creates and renames boards, only required the ideas.view permission. The follow-up commit changed the attribute to an entity-scoped EDIT permission, matching the Blueprints board dialog.

The maintainer then reviewed both parts in detail. They wrote that they "verified the fix routes through the global hash-modal router" and checked the permission change: "the Ideas service does fence properly ... So no IDOR gap; the marker is honest." The approval read: "Verified the modal mechanism and the service-layer authorization. LGTM."

They also noted one cleanup for the project itself: the fix "orphans the inline #editCanvas modal ... which is now dead markup."

Takeaways

  • Reusing a route that already works beats writing a new JavaScript handler.
  • A small UI fix can surface an authorization question. Answering it in the same PR kept the change honest.

FAQ

Did the fix add tests?

No. The PR author's review reply notes that no tests were run in their environment. The maintainer reported CI as green, apart from a security audit failure that already existed on master.

Where can I read more?

See the pull request and the original issue.

The goal

The best small fixes leave the codebase more consistent than they found it. Here, one view now uses the same dialog route as its siblings, with a permission check that matches what the endpoint does.

Run the loop

Turn production signals into reviewed fixes.

Start a free trial and see how Prilog maps real incidents to code-level pull requests.