diff --git a/datasette/templates/query.html b/datasette/templates/query.html index a7cb6647fe..7771b101b2 100644 --- a/datasette/templates/query.html +++ b/datasette/templates/query.html @@ -28,7 +28,7 @@ {% block content %} -

{{ metadata.title or database }}

+

{{ metadata.title or database }}{% if private %} 🔒{% endif %}

{% block description_source_license %}{% include "_description_source_license.html" %}{% endblock %} diff --git a/datasette/views/database.py b/datasette/views/database.py index 6f6404a706..30817106b8 100644 --- a/datasette/views/database.py +++ b/datasette/views/database.py @@ -147,10 +147,14 @@ async def data( # Respect canned query permissions await self.check_permission(request, "view-instance") await self.check_permission(request, "view-database", "database", database) + private = False if canned_query: await self.check_permission( request, "view-query", "query", (database, canned_query) ) + private = not await self.ds.permission_allowed( + None, "view-query", "query", (database, canned_query), default=True + ) else: await self.check_permission(request, "execute-sql", "database", database) # Extract any :named parameters @@ -214,6 +218,7 @@ async def extra_template(): "truncated": False, "columns": [], "query": {"sql": sql, "params": params}, + "private": private, }, extra_template, templates, @@ -282,6 +287,7 @@ async def extra_template(): "truncated": results.truncated, "columns": columns, "query": {"sql": sql, "params": params}, + "private": private, }, extra_template, templates, diff --git a/tests/test_permissions.py b/tests/test_permissions.py index 733afd5fb5..55b2d67394 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -136,10 +136,15 @@ def test_view_query(allow, expected_anon, expected_auth): ) as client: anon_response = client.get("/fixtures/q") assert expected_anon == anon_response.status + if allow and anon_response.status == 200: + # Should be no padlock + assert ">fixtures 🔒" not in anon_response.text auth_response = client.get( "/fixtures/q", cookies={"ds_actor": client.ds.sign({"id": "root"}, "actor")} ) assert expected_auth == auth_response.status + if allow and expected_anon == 403 and expected_auth == 200: + assert ">fixtures 🔒" in auth_response.text def test_query_list_respects_view_query():