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():