mirror of
https://github.com/simonw/datasette.git
synced 2026-05-31 06:07:05 +02:00
parent
ef43c10388
commit
b7505a9fc2
3 changed files with 57 additions and 0 deletions
22
datasette/default_database_actions.py
Normal file
22
datasette/default_database_actions.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
from datasette import hookimpl
|
||||
from datasette.resources import DatabaseResource
|
||||
|
||||
|
||||
@hookimpl
|
||||
def database_actions(datasette, actor, database, request):
|
||||
async def inner():
|
||||
if not await datasette.allowed(
|
||||
action="execute-write-sql",
|
||||
resource=DatabaseResource(database),
|
||||
actor=actor,
|
||||
):
|
||||
return []
|
||||
return [
|
||||
{
|
||||
"href": datasette.urls.database(database) + "/-/execute-write",
|
||||
"label": "Execute write SQL",
|
||||
"description": "Run writable SQL with table permission checks.",
|
||||
}
|
||||
]
|
||||
|
||||
return inner
|
||||
|
|
@ -30,6 +30,7 @@ DEFAULT_PLUGINS = (
|
|||
"datasette.blob_renderer",
|
||||
"datasette.default_debug_menu",
|
||||
"datasette.default_jump_items",
|
||||
"datasette.default_database_actions",
|
||||
"datasette.handle_exception",
|
||||
"datasette.forbidden",
|
||||
"datasette.events",
|
||||
|
|
|
|||
|
|
@ -515,6 +515,40 @@ async def test_execute_write_get_prepopulates_without_executing():
|
|||
assert (await db.execute("select count(*) from dogs")).first()[0] == 0
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_database_action_menu_links_to_execute_write_for_permitted_actor():
|
||||
ds = Datasette(
|
||||
memory=True,
|
||||
default_deny=True,
|
||||
config={
|
||||
"databases": {
|
||||
"data": {
|
||||
"permissions": {
|
||||
"view-database": {
|
||||
"id": ["writer", "viewer"],
|
||||
},
|
||||
"execute-write-sql": {"id": "writer"},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
ds.add_memory_database("execute_write_menu", name="data")
|
||||
await ds.invoke_startup()
|
||||
|
||||
anonymous_response = await ds.client.get("/data")
|
||||
viewer_response = await ds.client.get("/data", actor={"id": "viewer"})
|
||||
writer_response = await ds.client.get("/data", actor={"id": "writer"})
|
||||
|
||||
assert anonymous_response.status_code == 403
|
||||
assert viewer_response.status_code == 200
|
||||
assert "Execute write SQL" not in viewer_response.text
|
||||
assert writer_response.status_code == 200
|
||||
assert "Database actions" in writer_response.text
|
||||
assert 'href="/data/-/execute-write"' in writer_response.text
|
||||
assert "Execute write SQL" in writer_response.text
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_execute_write_post_requires_database_and_table_permissions():
|
||||
ds = Datasette(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue