From 81575e46ca83a7c68204f603488915d94432894d Mon Sep 17 00:00:00 2001 From: cproudlock Date: Fri, 21 Aug 2026 16:07:28 -0400 Subject: [PATCH] Give the guest setting somewhere to be changed Reported: no Tools section in Settings. The setting existed in the database and had no page, which from a person's side is indistinguishable from the feature not existing. get_settings_defaults SEEDS a setting. get_settings_cards (ADR-010) is what puts it in the rail. Declaring only the first is a silent half-feature: nothing fails, no test notices, and the switch is unreachable. The page states the cost where the DECISION is made rather than in a document nobody opens - turn it on and it says a guest-created link records no creator, so the audit trail can say when and from where but never who. Admin-only, like every other settings page, because this one decides whether an unauthenticated caller may write to the site. Also caught while wiring it: the card asked for a 'shield' icon, which is not in the settings iconMap, so it would have rendered the fallback puzzle piece - the glyph that reads as "nobody chose this". Uses wrench, matching Tech Tools. The row still comes from `flask plugin upgrade-all`; the card appears either way, and without the row the page loads empty. --- plugins/tools/frontend/routes.js | 8 ++ .../frontend/views/SecureSendSettings.vue | 77 +++++++++++++++++++ plugins/tools/plugin.py | 22 ++++++ 3 files changed, 107 insertions(+) create mode 100644 plugins/tools/frontend/views/SecureSendSettings.vue diff --git a/plugins/tools/frontend/routes.js b/plugins/tools/frontend/routes.js index f306aa24..7e15889b 100644 --- a/plugins/tools/frontend/routes.js +++ b/plugins/tools/frontend/routes.js @@ -28,6 +28,14 @@ export default [ // Browser-only: no API, no data, nothing to protect. meta: { plugin: 'tools' } }, + { + path: 'settings/secure-send', + name: 'secure-send-settings', + component: () => import('./views/SecureSendSettings.vue'), + // Admin, like every other settings page: this decides whether an + // unauthenticated caller may write to the site. + meta: { requiresAuth: true, requiresAdmin: true, plugin: 'tools' } + }, { path: 'tools/secure-send', name: 'tools-secure-send', diff --git a/plugins/tools/frontend/views/SecureSendSettings.vue b/plugins/tools/frontend/views/SecureSendSettings.vue new file mode 100644 index 00000000..3c1a345d --- /dev/null +++ b/plugins/tools/frontend/views/SecureSendSettings.vue @@ -0,0 +1,77 @@ + + + + + diff --git a/plugins/tools/plugin.py b/plugins/tools/plugin.py index 6f369519..b86a564b 100644 --- a/plugins/tools/plugin.py +++ b/plugins/tools/plugin.py @@ -92,6 +92,28 @@ class ToolsPlugin(BasePlugin): }, ] + def get_settings_cards(self) -> List[dict]: + """A page for the one switch this plugin owns (ADR-010). + + get_settings_defaults SEEDS the row; this is what gives somebody a place + to change it. Declaring only the first left the setting in the database + with no way to reach it, which is indistinguishable from the feature not + existing. + """ + return [ + { + 'group': 'Tools', + 'to': '/settings/secure-send', + # From the settings iconMap; an unknown key falls back to a + # puzzle piece, which reads as "nobody chose this". + 'icon': 'wrench', + 'title': 'Secure Send', + 'description': 'Whether people without an account can create ' + 'one-view password links', + 'position': 60, + }, + ] + def get_navigation_items(self) -> List[dict]: return [ {