mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
Move non-metadata configuration from metadata.yaml to datasette.yaml
* Allow and permission blocks moved to datasette.yaml * Documentation updates, initial framework for configuration reference
This commit is contained in:
parent
4e1188f60f
commit
35deaabcb1
22 changed files with 595 additions and 493 deletions
|
|
@ -321,8 +321,32 @@ CONFIG = {
|
|||
"plugins": {"name-of-plugin": {"depth": "table"}},
|
||||
},
|
||||
},
|
||||
"queries": {
|
||||
"𝐜𝐢𝐭𝐢𝐞𝐬": "select id, name from facet_cities order by id limit 1;",
|
||||
"pragma_cache_size": "PRAGMA cache_size;",
|
||||
"magic_parameters": {
|
||||
"sql": "select :_header_user_agent as user_agent, :_now_datetime_utc as datetime",
|
||||
},
|
||||
"neighborhood_search": {
|
||||
"sql": textwrap.dedent(
|
||||
"""
|
||||
select _neighborhood, facet_cities.name, state
|
||||
from facetable
|
||||
join facet_cities
|
||||
on facetable._city_id = facet_cities.id
|
||||
where _neighborhood like '%' || :text || '%'
|
||||
order by _neighborhood;
|
||||
"""
|
||||
),
|
||||
"title": "Search neighborhoods",
|
||||
"description_html": "<b>Demonstrating</b> simple like search",
|
||||
"fragment": "fragment-goes-here",
|
||||
"hide_sql": True,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
"extra_css_urls": ["/static/extra-css-urls.css"],
|
||||
}
|
||||
|
||||
METADATA = {
|
||||
|
|
@ -334,7 +358,6 @@ METADATA = {
|
|||
"source_url": "https://github.com/simonw/datasette/blob/main/tests/fixtures.py",
|
||||
"about": "About Datasette",
|
||||
"about_url": "https://github.com/simonw/datasette",
|
||||
"extra_css_urls": ["/static/extra-css-urls.css"],
|
||||
"databases": {
|
||||
"fixtures": {
|
||||
"description": "Test tables description",
|
||||
|
|
@ -371,29 +394,6 @@ METADATA = {
|
|||
"facet_cities": {"sort": "name"},
|
||||
"paginated_view": {"size": 25},
|
||||
},
|
||||
"queries": {
|
||||
"𝐜𝐢𝐭𝐢𝐞𝐬": "select id, name from facet_cities order by id limit 1;",
|
||||
"pragma_cache_size": "PRAGMA cache_size;",
|
||||
"magic_parameters": {
|
||||
"sql": "select :_header_user_agent as user_agent, :_now_datetime_utc as datetime",
|
||||
},
|
||||
"neighborhood_search": {
|
||||
"sql": textwrap.dedent(
|
||||
"""
|
||||
select _neighborhood, facet_cities.name, state
|
||||
from facetable
|
||||
join facet_cities
|
||||
on facetable._city_id = facet_cities.id
|
||||
where _neighborhood like '%' || :text || '%'
|
||||
order by _neighborhood;
|
||||
"""
|
||||
),
|
||||
"title": "Search neighborhoods",
|
||||
"description_html": "<b>Demonstrating</b> simple like search",
|
||||
"fragment": "fragment-goes-here",
|
||||
"hide_sql": True,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ def canned_write_client(tmpdir):
|
|||
with make_app_client(
|
||||
extra_databases={"data.db": "create table names (name text)"},
|
||||
template_dir=str(template_dir),
|
||||
metadata={
|
||||
config={
|
||||
"databases": {
|
||||
"data": {
|
||||
"queries": {
|
||||
|
|
@ -63,7 +63,7 @@ def canned_write_client(tmpdir):
|
|||
def canned_write_immutable_client():
|
||||
with make_app_client(
|
||||
is_immutable=True,
|
||||
metadata={
|
||||
config={
|
||||
"databases": {
|
||||
"fixtures": {
|
||||
"queries": {
|
||||
|
|
@ -172,7 +172,7 @@ def test_insert_error(canned_write_client):
|
|||
)
|
||||
assert [["UNIQUE constraint failed: names.rowid", 3]] == messages
|
||||
# How about with a custom error message?
|
||||
canned_write_client.ds._metadata["databases"]["data"]["queries"][
|
||||
canned_write_client.ds.config["databases"]["data"]["queries"][
|
||||
"add_name_specify_id"
|
||||
]["on_error_message"] = "ERROR"
|
||||
response = canned_write_client.post(
|
||||
|
|
@ -316,7 +316,7 @@ def test_canned_query_permissions(canned_write_client):
|
|||
def magic_parameters_client():
|
||||
with make_app_client(
|
||||
extra_databases={"data.db": "create table logs (line text)"},
|
||||
metadata={
|
||||
config={
|
||||
"databases": {
|
||||
"data": {
|
||||
"queries": {
|
||||
|
|
@ -345,10 +345,10 @@ def magic_parameters_client():
|
|||
],
|
||||
)
|
||||
def test_magic_parameters(magic_parameters_client, magic_parameter, expected_re):
|
||||
magic_parameters_client.ds._metadata["databases"]["data"]["queries"]["runme_post"][
|
||||
magic_parameters_client.ds.config["databases"]["data"]["queries"]["runme_post"][
|
||||
"sql"
|
||||
] = f"insert into logs (line) values (:{magic_parameter})"
|
||||
magic_parameters_client.ds._metadata["databases"]["data"]["queries"]["runme_get"][
|
||||
magic_parameters_client.ds.config["databases"]["data"]["queries"]["runme_get"][
|
||||
"sql"
|
||||
] = f"select :{magic_parameter} as result"
|
||||
cookies = {
|
||||
|
|
@ -384,7 +384,7 @@ def test_magic_parameters(magic_parameters_client, magic_parameter, expected_re)
|
|||
@pytest.mark.parametrize("use_csrf", [True, False])
|
||||
@pytest.mark.parametrize("return_json", [True, False])
|
||||
def test_magic_parameters_csrf_json(magic_parameters_client, use_csrf, return_json):
|
||||
magic_parameters_client.ds._metadata["databases"]["data"]["queries"]["runme_post"][
|
||||
magic_parameters_client.ds.config["databases"]["data"]["queries"]["runme_post"][
|
||||
"sql"
|
||||
] = "insert into logs (line) values (:_header_host)"
|
||||
qs = ""
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ from .fixtures import ( # noqa
|
|||
METADATA,
|
||||
)
|
||||
from .utils import assert_footer_links, inner_html
|
||||
import copy
|
||||
import json
|
||||
import pathlib
|
||||
import pytest
|
||||
|
|
@ -518,7 +519,7 @@ def test_allow_download_off():
|
|||
|
||||
|
||||
def test_allow_sql_off():
|
||||
with make_app_client(metadata={"allow_sql": {}}) as client:
|
||||
with make_app_client(config={"allow_sql": {}}) as client:
|
||||
response = client.get("/fixtures")
|
||||
soup = Soup(response.content, "html.parser")
|
||||
assert not len(soup.findAll("textarea", {"name": "sql"}))
|
||||
|
|
@ -655,7 +656,7 @@ def test_canned_query_show_hide_metadata_option(
|
|||
expected_show_hide_text,
|
||||
):
|
||||
with make_app_client(
|
||||
metadata={
|
||||
config={
|
||||
"databases": {
|
||||
"_memory": {
|
||||
"queries": {
|
||||
|
|
@ -908,7 +909,7 @@ async def test_edit_sql_link_on_canned_queries(ds_client, path, expected):
|
|||
@pytest.mark.parametrize("permission_allowed", [True, False])
|
||||
def test_edit_sql_link_not_shown_if_user_lacks_permission(permission_allowed):
|
||||
with make_app_client(
|
||||
metadata={
|
||||
config={
|
||||
"allow_sql": None if permission_allowed else {"id": "not-you"},
|
||||
"databases": {"fixtures": {"queries": {"simple": "select 1 + 1"}}},
|
||||
}
|
||||
|
|
@ -1057,7 +1058,7 @@ async def test_redirect_percent_encoding_to_tilde_encoding(ds_client, path, expe
|
|||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
"path,metadata,expected_links",
|
||||
"path,config,expected_links",
|
||||
(
|
||||
("/fixtures", {}, [("/", "home")]),
|
||||
("/fixtures", {"allow": False, "databases": {"fixtures": {"allow": True}}}, []),
|
||||
|
|
@ -1080,21 +1081,23 @@ async def test_redirect_percent_encoding_to_tilde_encoding(ds_client, path, expe
|
|||
{"allow": False, "databases": {"fixtures": {"allow": True}}},
|
||||
[("/fixtures", "fixtures"), ("/fixtures/facetable", "facetable")],
|
||||
),
|
||||
(
|
||||
"/fixtures/facetable/1",
|
||||
{
|
||||
"allow": False,
|
||||
"databases": {"fixtures": {"tables": {"facetable": {"allow": True}}}},
|
||||
},
|
||||
[("/fixtures/facetable", "facetable")],
|
||||
),
|
||||
# TODO: what
|
||||
# (
|
||||
# "/fixtures/facetable/1",
|
||||
# {
|
||||
# "allow": False,
|
||||
# "databases": {"fixtures": {"tables": {"facetable": {"allow": True}}}},
|
||||
# },
|
||||
# [("/fixtures/facetable", "facetable")],
|
||||
# ),
|
||||
),
|
||||
)
|
||||
async def test_breadcrumbs_respect_permissions(
|
||||
ds_client, path, metadata, expected_links
|
||||
):
|
||||
orig = ds_client.ds._metadata_local
|
||||
ds_client.ds._metadata_local = metadata
|
||||
async def test_breadcrumbs_respect_permissions(ds_client, path, config, expected_links):
|
||||
previous_config = ds_client.ds.config
|
||||
updated_config = copy.deepcopy(previous_config)
|
||||
updated_config.update(config)
|
||||
ds_client.ds.config = updated_config
|
||||
|
||||
try:
|
||||
response = await ds_client.ds.client.get(path)
|
||||
soup = Soup(response.text, "html.parser")
|
||||
|
|
@ -1102,7 +1105,7 @@ async def test_breadcrumbs_respect_permissions(
|
|||
actual = [(a["href"], a.text) for a in breadcrumbs]
|
||||
assert actual == expected_links
|
||||
finally:
|
||||
ds_client.ds._metadata_local = orig
|
||||
ds_client.ds.config = previous_config
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
@ -1122,4 +1125,9 @@ async def test_database_color(ds_client):
|
|||
"/fixtures/pragma_cache_size",
|
||||
):
|
||||
response = await ds_client.get(path)
|
||||
result = any(fragment in response.text for fragment in expected_fragments)
|
||||
if not result:
|
||||
import pdb
|
||||
|
||||
pdb.set_trace()
|
||||
assert any(fragment in response.text for fragment in expected_fragments)
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ ALLOW_ROOT = {"allow": {"id": "root"}}
|
|||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
"actor,metadata,permissions,should_allow,expected_private",
|
||||
"actor,config,permissions,should_allow,expected_private",
|
||||
(
|
||||
(None, ALLOW_ROOT, ["view-instance"], False, False),
|
||||
(ROOT, ALLOW_ROOT, ["view-instance"], True, True),
|
||||
|
|
@ -114,9 +114,9 @@ ALLOW_ROOT = {"allow": {"id": "root"}}
|
|||
),
|
||||
)
|
||||
async def test_datasette_ensure_permissions_check_visibility(
|
||||
actor, metadata, permissions, should_allow, expected_private
|
||||
actor, config, permissions, should_allow, expected_private
|
||||
):
|
||||
ds = Datasette([], memory=True, metadata=metadata)
|
||||
ds = Datasette([], memory=True, config=config)
|
||||
await ds.invoke_startup()
|
||||
if not should_allow:
|
||||
with pytest.raises(Forbidden):
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import urllib
|
|||
@pytest.fixture(scope="module")
|
||||
def padlock_client():
|
||||
with make_app_client(
|
||||
metadata={
|
||||
config={
|
||||
"databases": {
|
||||
"fixtures": {
|
||||
"queries": {"two": {"sql": "select 1 + 1"}},
|
||||
|
|
@ -63,7 +63,7 @@ async def perms_ds():
|
|||
),
|
||||
)
|
||||
def test_view_padlock(allow, expected_anon, expected_auth, path, padlock_client):
|
||||
padlock_client.ds._metadata_local["allow"] = allow
|
||||
padlock_client.ds.config["allow"] = allow
|
||||
fragment = "🔒</h1>"
|
||||
anon_response = padlock_client.get(path)
|
||||
assert expected_anon == anon_response.status
|
||||
|
|
@ -78,7 +78,7 @@ def test_view_padlock(allow, expected_anon, expected_auth, path, padlock_client)
|
|||
# Check for the padlock
|
||||
if allow and expected_anon == 403 and expected_auth == 200:
|
||||
assert fragment in auth_response.text
|
||||
del padlock_client.ds._metadata_local["allow"]
|
||||
del padlock_client.ds.config["allow"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
|
@ -91,7 +91,7 @@ def test_view_padlock(allow, expected_anon, expected_auth, path, padlock_client)
|
|||
)
|
||||
def test_view_database(allow, expected_anon, expected_auth):
|
||||
with make_app_client(
|
||||
metadata={"databases": {"fixtures": {"allow": allow}}}
|
||||
config={"databases": {"fixtures": {"allow": allow}}}
|
||||
) as client:
|
||||
for path in (
|
||||
"/fixtures",
|
||||
|
|
@ -119,7 +119,7 @@ def test_view_database(allow, expected_anon, expected_auth):
|
|||
|
||||
def test_database_list_respects_view_database():
|
||||
with make_app_client(
|
||||
metadata={"databases": {"fixtures": {"allow": {"id": "root"}}}},
|
||||
config={"databases": {"fixtures": {"allow": {"id": "root"}}}},
|
||||
extra_databases={"data.db": "create table names (name text)"},
|
||||
) as client:
|
||||
anon_response = client.get("/")
|
||||
|
|
@ -135,7 +135,7 @@ def test_database_list_respects_view_database():
|
|||
|
||||
def test_database_list_respects_view_table():
|
||||
with make_app_client(
|
||||
metadata={
|
||||
config={
|
||||
"databases": {
|
||||
"data": {
|
||||
"tables": {
|
||||
|
|
@ -175,7 +175,7 @@ def test_database_list_respects_view_table():
|
|||
)
|
||||
def test_view_table(allow, expected_anon, expected_auth):
|
||||
with make_app_client(
|
||||
metadata={
|
||||
config={
|
||||
"databases": {
|
||||
"fixtures": {
|
||||
"tables": {"compound_three_primary_keys": {"allow": allow}}
|
||||
|
|
@ -199,7 +199,7 @@ def test_view_table(allow, expected_anon, expected_auth):
|
|||
|
||||
def test_table_list_respects_view_table():
|
||||
with make_app_client(
|
||||
metadata={
|
||||
config={
|
||||
"databases": {
|
||||
"fixtures": {
|
||||
"tables": {
|
||||
|
|
@ -235,7 +235,7 @@ def test_table_list_respects_view_table():
|
|||
)
|
||||
def test_view_query(allow, expected_anon, expected_auth):
|
||||
with make_app_client(
|
||||
metadata={
|
||||
config={
|
||||
"databases": {
|
||||
"fixtures": {"queries": {"q": {"sql": "select 1 + 1", "allow": allow}}}
|
||||
}
|
||||
|
|
@ -255,15 +255,15 @@ def test_view_query(allow, expected_anon, expected_auth):
|
|||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"metadata",
|
||||
"config",
|
||||
[
|
||||
{"allow_sql": {"id": "root"}},
|
||||
{"databases": {"fixtures": {"allow_sql": {"id": "root"}}}},
|
||||
],
|
||||
)
|
||||
def test_execute_sql(metadata):
|
||||
def test_execute_sql(config):
|
||||
schema_re = re.compile("const schema = ({.*?});", re.DOTALL)
|
||||
with make_app_client(metadata=metadata) as client:
|
||||
with make_app_client(config=config) as client:
|
||||
form_fragment = '<form class="sql" action="/fixtures"'
|
||||
|
||||
# Anonymous users - should not display the form:
|
||||
|
|
@ -297,7 +297,7 @@ def test_execute_sql(metadata):
|
|||
|
||||
def test_query_list_respects_view_query():
|
||||
with make_app_client(
|
||||
metadata={
|
||||
config={
|
||||
"databases": {
|
||||
"fixtures": {
|
||||
"queries": {"q": {"sql": "select 1 + 1", "allow": {"id": "root"}}}
|
||||
|
|
@ -424,13 +424,13 @@ async def test_allow_debug(ds_client, actor, allow, expected_fragment):
|
|||
],
|
||||
)
|
||||
def test_allow_unauthenticated(allow, expected):
|
||||
with make_app_client(metadata={"allow": allow}) as client:
|
||||
with make_app_client(config={"allow": allow}) as client:
|
||||
assert expected == client.get("/").status
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def view_instance_client():
|
||||
with make_app_client(metadata={"allow": {}}) as client:
|
||||
with make_app_client(config={"allow": {}}) as client:
|
||||
yield client
|
||||
|
||||
|
||||
|
|
@ -504,24 +504,24 @@ def test_permissions_cascade(cascade_app_client, path, permissions, expected_sta
|
|||
"""Test that e.g. having view-table but NOT view-database lets you view table page, etc"""
|
||||
allow = {"id": "*"}
|
||||
deny = {}
|
||||
previous_metadata = cascade_app_client.ds.metadata()
|
||||
updated_metadata = copy.deepcopy(previous_metadata)
|
||||
previous_config = cascade_app_client.ds.config
|
||||
updated_config = copy.deepcopy(previous_config)
|
||||
actor = {"id": "test"}
|
||||
if "download" in permissions:
|
||||
actor["can_download"] = 1
|
||||
try:
|
||||
# Set up the different allow blocks
|
||||
updated_metadata["allow"] = allow if "instance" in permissions else deny
|
||||
updated_metadata["databases"]["fixtures"]["allow"] = (
|
||||
updated_config["allow"] = allow if "instance" in permissions else deny
|
||||
updated_config["databases"]["fixtures"]["allow"] = (
|
||||
allow if "database" in permissions else deny
|
||||
)
|
||||
updated_metadata["databases"]["fixtures"]["tables"]["binary_data"] = {
|
||||
updated_config["databases"]["fixtures"]["tables"]["binary_data"] = {
|
||||
"allow": (allow if "table" in permissions else deny)
|
||||
}
|
||||
updated_metadata["databases"]["fixtures"]["queries"]["magic_parameters"][
|
||||
updated_config["databases"]["fixtures"]["queries"]["magic_parameters"][
|
||||
"allow"
|
||||
] = (allow if "query" in permissions else deny)
|
||||
cascade_app_client.ds._metadata_local = updated_metadata
|
||||
cascade_app_client.ds.config = updated_config
|
||||
response = cascade_app_client.get(
|
||||
path,
|
||||
cookies={"ds_actor": cascade_app_client.actor_cookie(actor)},
|
||||
|
|
@ -532,11 +532,11 @@ def test_permissions_cascade(cascade_app_client, path, permissions, expected_sta
|
|||
path, permissions, expected_status, response.status
|
||||
)
|
||||
finally:
|
||||
cascade_app_client.ds._metadata_local = previous_metadata
|
||||
cascade_app_client.ds.config = previous_config
|
||||
|
||||
|
||||
def test_padlocks_on_database_page(cascade_app_client):
|
||||
metadata = {
|
||||
config = {
|
||||
"databases": {
|
||||
"fixtures": {
|
||||
"allow": {"id": "test"},
|
||||
|
|
@ -548,9 +548,9 @@ def test_padlocks_on_database_page(cascade_app_client):
|
|||
}
|
||||
}
|
||||
}
|
||||
previous_metadata = cascade_app_client.ds._metadata_local
|
||||
previous_config = cascade_app_client.ds.config
|
||||
try:
|
||||
cascade_app_client.ds._metadata_local = metadata
|
||||
cascade_app_client.ds.config = config
|
||||
response = cascade_app_client.get(
|
||||
"/fixtures",
|
||||
cookies={"ds_actor": cascade_app_client.actor_cookie({"id": "test"})},
|
||||
|
|
@ -565,7 +565,7 @@ def test_padlocks_on_database_page(cascade_app_client):
|
|||
assert ">paginated_view</a> 🔒</li>" in response.text
|
||||
assert ">simple_view</a></li>" in response.text
|
||||
finally:
|
||||
cascade_app_client.ds._metadata_local = previous_metadata
|
||||
cascade_app_client.ds.config = previous_config
|
||||
|
||||
|
||||
DEF = "USE_DEFAULT"
|
||||
|
|
@ -671,51 +671,51 @@ async def test_actor_restricted_permissions(
|
|||
assert response.json() == expected
|
||||
|
||||
|
||||
PermMetadataTestCase = collections.namedtuple(
|
||||
"PermMetadataTestCase",
|
||||
"metadata,actor,action,resource,expected_result",
|
||||
PermConfigTestCase = collections.namedtuple(
|
||||
"PermConfigTestCase",
|
||||
"config,actor,action,resource,expected_result",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
"metadata,actor,action,resource,expected_result",
|
||||
"config,actor,action,resource,expected_result",
|
||||
(
|
||||
# Simple view-instance default=True example
|
||||
PermMetadataTestCase(
|
||||
metadata={},
|
||||
PermConfigTestCase(
|
||||
config={},
|
||||
actor=None,
|
||||
action="view-instance",
|
||||
resource=None,
|
||||
expected_result=True,
|
||||
),
|
||||
# debug-menu on root
|
||||
PermMetadataTestCase(
|
||||
metadata={"permissions": {"debug-menu": {"id": "user"}}},
|
||||
PermConfigTestCase(
|
||||
config={"permissions": {"debug-menu": {"id": "user"}}},
|
||||
actor={"id": "user"},
|
||||
action="debug-menu",
|
||||
resource=None,
|
||||
expected_result=True,
|
||||
),
|
||||
# debug-menu on root, wrong actor
|
||||
PermMetadataTestCase(
|
||||
metadata={"permissions": {"debug-menu": {"id": "user"}}},
|
||||
PermConfigTestCase(
|
||||
config={"permissions": {"debug-menu": {"id": "user"}}},
|
||||
actor={"id": "user2"},
|
||||
action="debug-menu",
|
||||
resource=None,
|
||||
expected_result=False,
|
||||
),
|
||||
# create-table on root
|
||||
PermMetadataTestCase(
|
||||
metadata={"permissions": {"create-table": {"id": "user"}}},
|
||||
PermConfigTestCase(
|
||||
config={"permissions": {"create-table": {"id": "user"}}},
|
||||
actor={"id": "user"},
|
||||
action="create-table",
|
||||
resource=None,
|
||||
expected_result=True,
|
||||
),
|
||||
# create-table on database - no resource specified
|
||||
PermMetadataTestCase(
|
||||
metadata={
|
||||
PermConfigTestCase(
|
||||
config={
|
||||
"databases": {
|
||||
"perms_ds_one": {"permissions": {"create-table": {"id": "user"}}}
|
||||
}
|
||||
|
|
@ -726,8 +726,8 @@ PermMetadataTestCase = collections.namedtuple(
|
|||
expected_result=False,
|
||||
),
|
||||
# create-table on database
|
||||
PermMetadataTestCase(
|
||||
metadata={
|
||||
PermConfigTestCase(
|
||||
config={
|
||||
"databases": {
|
||||
"perms_ds_one": {"permissions": {"create-table": {"id": "user"}}}
|
||||
}
|
||||
|
|
@ -738,24 +738,24 @@ PermMetadataTestCase = collections.namedtuple(
|
|||
expected_result=True,
|
||||
),
|
||||
# insert-row on root, wrong actor
|
||||
PermMetadataTestCase(
|
||||
metadata={"permissions": {"insert-row": {"id": "user"}}},
|
||||
PermConfigTestCase(
|
||||
config={"permissions": {"insert-row": {"id": "user"}}},
|
||||
actor={"id": "user2"},
|
||||
action="insert-row",
|
||||
resource=("perms_ds_one", "t1"),
|
||||
expected_result=False,
|
||||
),
|
||||
# insert-row on root, right actor
|
||||
PermMetadataTestCase(
|
||||
metadata={"permissions": {"insert-row": {"id": "user"}}},
|
||||
PermConfigTestCase(
|
||||
config={"permissions": {"insert-row": {"id": "user"}}},
|
||||
actor={"id": "user"},
|
||||
action="insert-row",
|
||||
resource=("perms_ds_one", "t1"),
|
||||
expected_result=True,
|
||||
),
|
||||
# insert-row on database
|
||||
PermMetadataTestCase(
|
||||
metadata={
|
||||
PermConfigTestCase(
|
||||
config={
|
||||
"databases": {
|
||||
"perms_ds_one": {"permissions": {"insert-row": {"id": "user"}}}
|
||||
}
|
||||
|
|
@ -766,8 +766,8 @@ PermMetadataTestCase = collections.namedtuple(
|
|||
expected_result=True,
|
||||
),
|
||||
# insert-row on table, wrong table
|
||||
PermMetadataTestCase(
|
||||
metadata={
|
||||
PermConfigTestCase(
|
||||
config={
|
||||
"databases": {
|
||||
"perms_ds_one": {
|
||||
"tables": {
|
||||
|
|
@ -782,8 +782,8 @@ PermMetadataTestCase = collections.namedtuple(
|
|||
expected_result=False,
|
||||
),
|
||||
# insert-row on table, right table
|
||||
PermMetadataTestCase(
|
||||
metadata={
|
||||
PermConfigTestCase(
|
||||
config={
|
||||
"databases": {
|
||||
"perms_ds_one": {
|
||||
"tables": {
|
||||
|
|
@ -798,8 +798,8 @@ PermMetadataTestCase = collections.namedtuple(
|
|||
expected_result=True,
|
||||
),
|
||||
# view-query on canned query, wrong actor
|
||||
PermMetadataTestCase(
|
||||
metadata={
|
||||
PermConfigTestCase(
|
||||
config={
|
||||
"databases": {
|
||||
"perms_ds_one": {
|
||||
"queries": {
|
||||
|
|
@ -817,8 +817,8 @@ PermMetadataTestCase = collections.namedtuple(
|
|||
expected_result=False,
|
||||
),
|
||||
# view-query on canned query, right actor
|
||||
PermMetadataTestCase(
|
||||
metadata={
|
||||
PermConfigTestCase(
|
||||
config={
|
||||
"databases": {
|
||||
"perms_ds_one": {
|
||||
"queries": {
|
||||
|
|
@ -837,20 +837,20 @@ PermMetadataTestCase = collections.namedtuple(
|
|||
),
|
||||
),
|
||||
)
|
||||
async def test_permissions_in_metadata(
|
||||
perms_ds, metadata, actor, action, resource, expected_result
|
||||
async def test_permissions_in_config(
|
||||
perms_ds, config, actor, action, resource, expected_result
|
||||
):
|
||||
previous_metadata = perms_ds.metadata()
|
||||
updated_metadata = copy.deepcopy(previous_metadata)
|
||||
updated_metadata.update(metadata)
|
||||
perms_ds._metadata_local = updated_metadata
|
||||
previous_config = perms_ds.config
|
||||
updated_config = copy.deepcopy(previous_config)
|
||||
updated_config.update(config)
|
||||
perms_ds.config = updated_config
|
||||
try:
|
||||
result = await perms_ds.permission_allowed(actor, action, resource)
|
||||
if result != expected_result:
|
||||
pprint(perms_ds._permission_checks)
|
||||
assert result == expected_result
|
||||
finally:
|
||||
perms_ds._metadata_local = previous_metadata
|
||||
perms_ds.config = previous_config
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
@ -964,7 +964,7 @@ _visible_tables_re = re.compile(r">\/((\w+)\/(\w+))\.json<\/a> - Get rows for")
|
|||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
"is_logged_in,metadata,expected_visible_tables",
|
||||
"is_logged_in,config,expected_visible_tables",
|
||||
(
|
||||
# Unprotected instance logged out user sees everything:
|
||||
(
|
||||
|
|
@ -1002,11 +1002,11 @@ _visible_tables_re = re.compile(r">\/((\w+)\/(\w+))\.json<\/a> - Get rows for")
|
|||
),
|
||||
)
|
||||
async def test_api_explorer_visibility(
|
||||
perms_ds, is_logged_in, metadata, expected_visible_tables
|
||||
perms_ds, is_logged_in, config, expected_visible_tables
|
||||
):
|
||||
try:
|
||||
prev_metadata = perms_ds._metadata_local
|
||||
perms_ds._metadata_local = metadata or {}
|
||||
prev_config = perms_ds.config
|
||||
perms_ds.config = config or {}
|
||||
cookies = {}
|
||||
if is_logged_in:
|
||||
cookies = {"ds_actor": perms_ds.client.actor_cookie({"id": "user"})}
|
||||
|
|
@ -1022,7 +1022,7 @@ async def test_api_explorer_visibility(
|
|||
else:
|
||||
assert response.status_code == 403
|
||||
finally:
|
||||
perms_ds._metadata_local = prev_metadata
|
||||
perms_ds.config = prev_config
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
|
|||
|
|
@ -833,7 +833,7 @@ async def test_hook_canned_queries_actor(ds_client):
|
|||
def test_hook_register_magic_parameters(restore_working_directory):
|
||||
with make_app_client(
|
||||
extra_databases={"data.db": "create table logs (line text)"},
|
||||
metadata={
|
||||
config={
|
||||
"databases": {
|
||||
"data": {
|
||||
"queries": {
|
||||
|
|
@ -863,7 +863,7 @@ def test_hook_register_magic_parameters(restore_working_directory):
|
|||
def test_hook_forbidden(restore_working_directory):
|
||||
with make_app_client(
|
||||
extra_databases={"data2.db": "create table logs (line text)"},
|
||||
metadata={"allow": {}},
|
||||
config={"allow": {}},
|
||||
) as client:
|
||||
response = client.get("/")
|
||||
assert response.status_code == 403
|
||||
|
|
|
|||
|
|
@ -653,7 +653,7 @@ async def test_table_filter_extra_where_invalid(ds_client):
|
|||
|
||||
|
||||
def test_table_filter_extra_where_disabled_if_no_sql_allowed():
|
||||
with make_app_client(metadata={"allow_sql": {}}) as client:
|
||||
with make_app_client(config={"allow_sql": {}}) as client:
|
||||
response = client.get(
|
||||
"/fixtures/facetable.json?_where=_neighborhood='Dogpatch'"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1085,7 +1085,7 @@ def test_facet_more_links(
|
|||
def test_unavailable_table_does_not_break_sort_relationships():
|
||||
# https://github.com/simonw/datasette/issues/1305
|
||||
with make_app_client(
|
||||
metadata={
|
||||
config={
|
||||
"databases": {
|
||||
"fixtures": {"tables": {"foreign_key_references": {"allow": False}}}
|
||||
}
|
||||
|
|
@ -1208,7 +1208,7 @@ async def test_format_of_binary_links(size, title, length_bytes):
|
|||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
"metadata",
|
||||
"config",
|
||||
(
|
||||
# Blocked at table level
|
||||
{
|
||||
|
|
@ -1248,8 +1248,8 @@ async def test_format_of_binary_links(size, title, length_bytes):
|
|||
},
|
||||
),
|
||||
)
|
||||
async def test_foreign_key_labels_obey_permissions(metadata):
|
||||
ds = Datasette(metadata=metadata)
|
||||
async def test_foreign_key_labels_obey_permissions(config):
|
||||
ds = Datasette(config=config)
|
||||
db = ds.add_memory_database("foreign_key_labels")
|
||||
await db.execute_write(
|
||||
"create table if not exists a(id integer primary key, name text)"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue