Permissions SQL API improvements (#2558)

* Neater design for PermissionSQL class, refs #2556
  - source is now automatically set to the source plugin
  - params is optional
* PermissionSQL.allow() and PermissionSQL.deny() shortcuts

Closes #2556

* Filter out temp database from attached_databases()

Refs https://github.com/simonw/datasette/issues/2557#issuecomment-3470510837
This commit is contained in:
Simon Willison 2025-10-30 15:48:46 -07:00 committed by GitHub
commit 6a71bde37f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 241 additions and 227 deletions

View file

@ -325,7 +325,11 @@ async def test_plugin_config_file(ds_client):
)
def test_hook_extra_body_script(app_client, path, expected_extra_body_script):
r = re.compile(r"<script type=\"module\">var extra_body_script = (.*?);</script>")
json_data = r.search(app_client.get(path).text).group(1)
response = app_client.get(path)
assert response.status_code == 200, response.text
match = r.search(response.text)
assert match is not None, "No extra_body_script found in HTML"
json_data = match.group(1)
actual_data = json.loads(json_data)
assert expected_extra_body_script == actual_data
@ -673,39 +677,11 @@ async def test_existing_scope_actor_respected(ds_client):
],
)
async def test_hook_permission_allowed(action, expected):
from datasette.permissions import Action
from datasette.resources import InstanceResource
class TestPlugin:
__name__ = "TestPlugin"
@hookimpl
def register_actions(self):
return [
Action(
name=name,
abbr=None,
description=None,
takes_parent=False,
takes_child=False,
resource_class=InstanceResource,
)
for name in (
"this_is_allowed",
"this_is_denied",
"this_is_allowed_async",
"this_is_denied_async",
)
]
pm.register(TestPlugin(), name="undo_register_extras")
try:
ds = Datasette(plugins_dir=PLUGINS_DIR)
await ds.invoke_startup()
actual = await ds.allowed(action=action, actor={"id": "actor"})
assert expected == actual
finally:
pm.unregister(name="undo_register_extras")
# Test actions and permission logic are defined in tests/plugins/my_plugin.py
ds = Datasette(plugins_dir=PLUGINS_DIR)
await ds.invoke_startup()
actual = await ds.allowed(action=action, actor={"id": "actor"})
assert expected == actual
@pytest.mark.asyncio