Settings → Plugins: a plugin switched off for the person shows a broken logo #594

Closed
opened 2026-10-01 10:48:08 +00:00 by tiagoagueda · 0 comments
Owner

Found on 2026-09-29 in a read-only review of postulo at 95348908d, by comparing the rows Settings → Plugins lists with the rule the logo view applies, and requesting the logo in a test.

Related to #288.

Checked again on 2026-10-01 against main at 0a5cad587: still present. The code is now at plugins/views.py:96-100 (the check on decide(name, request.user).on), core/templatetags/postulo.py:251-273 (plugin_logo, the <img> branch at :268-270) and plugins/policy.py:279-281 (overview keeping every row that is offered); templates/settings/plugins.html:74 is where it was.

policy.overview() deliberately lists plugins that are off for the person: their own choice, or forced off by an administrator. {% plugin_logo %} draws an <img> for any plugin that ships a logo, but PluginLogoView answers 404 to anyone not staff when decide(name, user).on is false. Exactly those rows get a broken image instead of the initials tile; administrators never see it, because staff skip the check.

  • Where: plugins/views.py:94-99 (if not decide(name, request.user).on: raise Http404); core/templatetags/postulo.py:284-305 (plugin_logo, the <img> at :300-302 whenever logos.logo_for(plugin) is not None); templates/settings/plugins.html:74; plugins/policy.py:288-290 (overview keeps every row whose decision is offered).
  • What happens: a person unticks a plugin that declares a logo, or an administrator forces one off for them. On their next visit the row's avatar is an empty box. In a test with a notifier declaring a logo and switched off by the person, the row was listed with on == False, the tag rendered <img src="/settings/connections/logo/logoplug/" alt="">, and that URL answered 404 to the same person.
  • Why it matters: the page shows a broken image for the rows that most need to be recognised, and the view's own reason ("the set of plugins an instance has installed is a fact about the instance") does not hold, since the same page already names the plugin. No official plugin declares a logo yet, so this reaches third-party plugins first.
  • Fix: gate the logo view on decide(...).offered rather than .on, which is exactly the set overview() shows to the person; update the view's docstring to match.

Done when

  • A test in tests/test_plugin_logos.py that switches a logo-declaring plugin off for a non-staff person and asserts connections:logo answers 200 for them, and still 404 for a plugin that is unavailable to them.
Found on 2026-09-29 in a read-only review of postulo at 95348908d, by comparing the rows *Settings → Plugins* lists with the rule the logo view applies, and requesting the logo in a test. Related to #288. Checked again on 2026-10-01 against `main` at `0a5cad587`: still present. The code is now at `plugins/views.py:96-100` (the check on `decide(name, request.user).on`), `core/templatetags/postulo.py:251-273` (`plugin_logo`, the `<img>` branch at :268-270) and `plugins/policy.py:279-281` (`overview` keeping every row that is `offered`); `templates/settings/plugins.html:74` is where it was. `policy.overview()` deliberately lists plugins that are off for the person: their own choice, or forced off by an administrator. `{% plugin_logo %}` draws an `<img>` for any plugin that ships a logo, but `PluginLogoView` answers 404 to anyone not staff when `decide(name, user).on` is false. Exactly those rows get a broken image instead of the initials tile; administrators never see it, because staff skip the check. - **Where:** `plugins/views.py:94-99` (`if not decide(name, request.user).on: raise Http404`); `core/templatetags/postulo.py:284-305` (`plugin_logo`, the `<img>` at :300-302 whenever `logos.logo_for(plugin)` is not `None`); `templates/settings/plugins.html:74`; `plugins/policy.py:288-290` (`overview` keeps every row whose decision is `offered`). - **What happens:** a person unticks a plugin that declares a logo, or an administrator forces one off for them. On their next visit the row's avatar is an empty box. In a test with a notifier declaring a logo and switched off by the person, the row was listed with `on == False`, the tag rendered `<img src="/settings/connections/logo/logoplug/" alt="">`, and that URL answered 404 to the same person. - **Why it matters:** the page shows a broken image for the rows that most need to be recognised, and the view's own reason ("the set of plugins an instance has installed is a fact about the instance") does not hold, since the same page already names the plugin. No official plugin declares a logo yet, so this reaches third-party plugins first. - **Fix:** gate the logo view on `decide(...).offered` rather than `.on`, which is exactly the set `overview()` shows to the person; update the view's docstring to match. ## Done when - A test in `tests/test_plugin_logos.py` that switches a logo-declaring plugin off for a non-staff person and asserts `connections:logo` answers 200 for them, and still 404 for a plugin that is unavailable to them.
tiagoagueda added this to the 0.6.0 milestone 2026-10-01 10:48:08 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo#594
No description provided.