Server settings → Plugins: Install takes the first catalogue listing the name, not the row that was pressed #601
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#601
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found on 2026-09-29 in a read-only review of postulo at
95348908d, reading the catalogue refresh, the install form andcatalogue.install.Checked again on 2026-10-01 against
mainat0a5cad587: still present. The code is now atcore/server_views.py:1438-1453(_install, the call at:1444); the template,plugins/catalogue.pyandplugins/models.py:66have not moved.After Check for updates, the page shows one row per catalogue per plugin, each tagged with its catalogue's name. The Install/Reinstall form posts only the plugin's name, and
catalogue.install(name)installs whateverfind()returns from the first configured catalogue that lists that name. Catalogue rows are ordered by(tier, name), andcustomsorts beforeofficial, so a custom catalogue's package of the same name always wins over the official one, and among custom catalogues the alphabetically first wins.templates/server/plugins.html:408-413(the form: hiddennameandactiononly),core/server_views.py:1438-1452(_install:catalogue.install(name, ...)),plugins/catalogue.py:321-341(install),plugins/catalogue.py:262-287(find, first listing in catalogue order),plugins/catalogue.py:237-245(fetch_all, inconfigured()order) andplugins/models.py:66(ordering = ("tier", "name")).postulo-imap. The administrator presses Install, or Reinstall on an installed plugin, on the row labelled with one catalogue. Postulo downloads and installs the other catalogue's wheel, signed with that catalogue's key, and recordsoriginascatalogue:<other>. The compatibility shown on the pressed row is also not the one checked. Only the provenance mark afterwards reveals the swap.catalogue.install()andfind()catalogue=andversion=parameters that fetch and search only that catalogue, and refuse when that catalogue no longer lists that release. Do the same for the command (plugins install <name>), which should refuse an ambiguous name unless a catalogue is given.Done when
tests/test_plugin_install.pyhas a test with two catalogues listing the same name in which installing withcatalogue=<the second>installs the second's wheel and recordsorigincatalogue:<the second>, and a view test that the install form posts the catalogue.