From ece0ba6f4bc152af6f605fc5f536ffa46af95274 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Sun, 7 Jun 2020 14:23:16 -0700 Subject: [PATCH] Test + default impl for view-query permission, refs #811 --- datasette/default_permissions.py | 21 ++++++++++++++++++--- tests/test_permissions.py | 22 ++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 tests/test_permissions.py diff --git a/datasette/default_permissions.py b/datasette/default_permissions.py index 0b0d17f95c..40ae54ab51 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 0000000000..c90fdf7a61 --- /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