diff --git a/datasette/default_permissions.py b/datasette/default_permissions.py index 0b0d17f9..40ae54ab 100644 --- a/datasette/default_permissions.py +++ b/datasette/default_permissions.py @@ -1,7 +1,22 @@ from datasette import hookimpl +from datasette.utils import actor_matches_allow @hookimpl -def permission_allowed(actor, action, resource_type, resource_identifier): - if actor and actor.get("id") == "root" and action == "permissions-debug": - return True +def permission_allowed(datasette, actor, action, resource_type, resource_identifier): + if action == "permissions-debug": + if actor and actor.get("id") == "root": + return True + elif action == "view-query": + # Check if this query has a "allow" block in metadata + assert resource_type == "query" + database, query_name = resource_identifier + queries_metadata = datasette.metadata("queries", database=database) + assert query_name in queries_metadata + if isinstance(queries_metadata[query_name], str): + return True + allow = queries_metadata[query_name].get("allow") + print("checking allow - actor = {}, allow = {}".format(actor, allow)) + if allow is None: + return True + return actor_matches_allow(actor, allow) diff --git a/tests/test_permissions.py b/tests/test_permissions.py new file mode 100644 index 00000000..c90fdf7a --- /dev/null +++ b/tests/test_permissions.py @@ -0,0 +1,22 @@ +from .fixtures import make_app_client +import pytest + + +@pytest.mark.parametrize( + "allow,expected_anon,expected_auth", + [(None, 200, 200), ({}, 403, 403), ({"id": "root"}, 403, 200),], +) +def test_execute_sql(allow, expected_anon, expected_auth): + with make_app_client( + metadata={ + "databases": { + "fixtures": {"queries": {"q": {"sql": "select 1 + 1", "allow": allow}}} + } + } + ) as client: + anon_response = client.get("/fixtures/q") + assert expected_anon == anon_response.status + auth_response = client.get( + "/fixtures/q", cookies={"ds_actor": client.ds.sign({"id": "root"}, "actor")} + ) + assert expected_auth == auth_response.status