From b5f41772cadb3d2a288bc57b964c36dbf94d41b6 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Fri, 24 Oct 2025 16:54:06 -0700 Subject: [PATCH] Fix view-database-download permission handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two fixes for database download permissions: 1. Added also_requires="view-database" to view-database-download action - You should only be able to download a database if you can view it 2. Added view-database-download to default_allow_actions list - This action should be allowed by default, like view-database 3. Implemented also_requires checking in allowed() method - The allowed() method now checks action.also_requires before checking the action itself - This ensures execute-sql requires view-database, etc. Fixes test_database_download_for_immutable and test_database_download_disallowed_for_memory. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- datasette/app.py | 11 +++++++++++ datasette/default_actions.py | 1 + datasette/default_permissions.py | 1 + 3 files changed, 13 insertions(+) diff --git a/datasette/app.py b/datasette/app.py index 0e7e35b8..528b11bf 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -1249,6 +1249,17 @@ class Datasette: if resource is None: resource = InstanceResource() + # Check if this action has also_requires - if so, check that action first + action_obj = self.actions.get(action) + if action_obj and action_obj.also_requires: + # Must have the required action first + if not await self.allowed( + action=action_obj.also_requires, + resource=resource, + actor=actor, + ): + return False + result = await check_permission_for_resource( datasette=self, actor=actor, diff --git a/datasette/default_actions.py b/datasette/default_actions.py index 1a79838a..e06e906b 100644 --- a/datasette/default_actions.py +++ b/datasette/default_actions.py @@ -36,6 +36,7 @@ def register_actions(): takes_parent=True, takes_child=False, resource_class=DatabaseResource, + also_requires="view-database", ), Action( name="view-table", diff --git a/datasette/default_permissions.py b/datasette/default_permissions.py index cd92ba73..7eda09c8 100644 --- a/datasette/default_permissions.py +++ b/datasette/default_permissions.py @@ -122,6 +122,7 @@ async def permission_resources_sql(datasette, actor, action): default_allow_actions = { "view-instance", "view-database", + "view-database-download", "view-table", "execute-sql", }