mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
Include SQL schema for CodeMirror on query pages, closes #1897
Refs #1893
This commit is contained in:
parent
22bade4562
commit
98611b3da0
2 changed files with 40 additions and 9 deletions
|
|
@ -141,6 +141,9 @@ class DatabaseView(DataView):
|
|||
|
||||
attached_databases = [d.name for d in await db.attached_databases()]
|
||||
|
||||
allow_execute_sql = await self.ds.permission_allowed(
|
||||
request.actor, "execute-sql", database, default=True
|
||||
)
|
||||
return (
|
||||
{
|
||||
"database": database,
|
||||
|
|
@ -151,9 +154,10 @@ class DatabaseView(DataView):
|
|||
"hidden_count": len([t for t in tables if t["hidden"]]),
|
||||
"views": views,
|
||||
"queries": canned_queries,
|
||||
"allow_execute_sql": await self.ds.permission_allowed(
|
||||
request.actor, "execute-sql", database, default=True
|
||||
),
|
||||
"allow_execute_sql": allow_execute_sql,
|
||||
"table_columns": await _table_columns(self.ds, database)
|
||||
if allow_execute_sql
|
||||
else {},
|
||||
},
|
||||
{
|
||||
"database_actions": database_actions,
|
||||
|
|
@ -510,6 +514,9 @@ class QueryView(DataView):
|
|||
"show_hide_text": show_hide_text,
|
||||
"show_hide_hidden": markupsafe.Markup(show_hide_hidden),
|
||||
"hide_sql": hide_sql,
|
||||
"table_columns": await _table_columns(self.ds, database)
|
||||
if allow_execute_sql
|
||||
else {},
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -685,3 +692,15 @@ class TableCreateView(BaseView):
|
|||
if rows:
|
||||
details["row_count"] = len(rows)
|
||||
return Response.json(details, status=201)
|
||||
|
||||
|
||||
async def _table_columns(datasette, database_name):
|
||||
internal = datasette.get_database("_internal")
|
||||
result = await internal.execute(
|
||||
"select table_name, name from columns where database_name = ?",
|
||||
[database_name],
|
||||
)
|
||||
table_columns = {}
|
||||
for row in result.rows:
|
||||
table_columns.setdefault(row["table_name"], []).append(row["name"])
|
||||
return table_columns
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import copy
|
|||
import json
|
||||
import pytest_asyncio
|
||||
import pytest
|
||||
import re
|
||||
import urllib
|
||||
|
||||
|
||||
|
|
@ -252,24 +253,35 @@ def test_view_query(allow, expected_anon, expected_auth):
|
|||
],
|
||||
)
|
||||
def test_execute_sql(metadata):
|
||||
schema_re = re.compile("const schema = ({.*?});", re.DOTALL)
|
||||
with make_app_client(metadata=metadata) as client:
|
||||
form_fragment = '<form class="sql" action="/fixtures"'
|
||||
|
||||
# Anonymous users - should not display the form:
|
||||
assert form_fragment not in client.get("/fixtures").text
|
||||
anon_html = client.get("/fixtures").text
|
||||
assert form_fragment not in anon_html
|
||||
# And const schema should be an empty object:
|
||||
assert "const schema = {};" in anon_html
|
||||
# This should 403:
|
||||
assert 403 == client.get("/fixtures?sql=select+1").status
|
||||
assert client.get("/fixtures?sql=select+1").status == 403
|
||||
# ?_where= not allowed on tables:
|
||||
assert 403 == client.get("/fixtures/facet_cities?_where=id=3").status
|
||||
assert client.get("/fixtures/facet_cities?_where=id=3").status == 403
|
||||
|
||||
# But for logged in user all of these should work:
|
||||
cookies = {"ds_actor": client.actor_cookie({"id": "root"})}
|
||||
response_text = client.get("/fixtures", cookies=cookies).text
|
||||
# Extract the schema= portion of the JavaScript
|
||||
schema_json = schema_re.search(response_text).group(1)
|
||||
schema = json.loads(schema_json)
|
||||
assert set(schema["attraction_characteristic"]) == {"name", "pk"}
|
||||
assert form_fragment in response_text
|
||||
assert 200 == client.get("/fixtures?sql=select+1", cookies=cookies).status
|
||||
query_response = client.get("/fixtures?sql=select+1", cookies=cookies)
|
||||
assert query_response.status == 200
|
||||
schema2 = json.loads(schema_re.search(query_response.text).group(1))
|
||||
assert set(schema2["attraction_characteristic"]) == {"name", "pk"}
|
||||
assert (
|
||||
200
|
||||
== client.get("/fixtures/facet_cities?_where=id=3", cookies=cookies).status
|
||||
client.get("/fixtures/facet_cities?_where=id=3", cookies=cookies).status
|
||||
== 200
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue