Label expand permission check respects cascade, closes #2178

This commit is contained in:
Simon Willison 2023-09-07 16:28:30 -07:00
commit c26370485a
2 changed files with 57 additions and 17 deletions

View file

@ -950,13 +950,19 @@ class Datasette:
except IndexError:
return {}
# Ensure user has permission to view the referenced table
if not await self.permission_allowed(
actor=actor,
action="view-table",
resource=(database, fk["other_table"]),
):
other_table = fk["other_table"]
other_column = fk["other_column"]
visible, _ = await self.check_visibility(
actor,
permissions=[
("view-table", (database, other_table)),
("view-database", database),
"view-instance",
],
)
if not visible:
return {}
label_column = await db.label_column_for_table(fk["other_table"])
label_column = await db.label_column_for_table(other_table)
if not label_column:
return {(fk["column"], value): str(value) for value in values}
labeled_fks = {}
@ -965,9 +971,9 @@ class Datasette:
from {other_table}
where {other_column} in ({placeholders})
""".format(
other_column=escape_sqlite(fk["other_column"]),
other_column=escape_sqlite(other_column),
label_column=escape_sqlite(label_column),
other_table=escape_sqlite(fk["other_table"]),
other_table=escape_sqlite(other_table),
placeholders=", ".join(["?"] * len(set(values))),
)
try:

View file

@ -1207,9 +1207,11 @@ async def test_format_of_binary_links(size, title, length_bytes):
@pytest.mark.asyncio
async def test_foreign_key_labels_obey_permissions():
ds = Datasette(
metadata={
@pytest.mark.parametrize(
"metadata",
(
# Blocked at table level
{
"databases": {
"foreign_key_labels": {
"tables": {
@ -1218,15 +1220,47 @@ async def test_foreign_key_labels_obey_permissions():
}
}
}
}
)
},
# Blocked at database level
{
"databases": {
"foreign_key_labels": {
# Only root can view this database
"allow": {"id": "root"},
"tables": {
# But table b is visible to everyone
"b": {"allow": True},
},
}
}
},
# Blocked at the instance level
{
"allow": {"id": "root"},
"databases": {
"foreign_key_labels": {
"tables": {
# Table b is visible to everyone
"b": {"allow": True},
}
}
},
},
),
)
async def test_foreign_key_labels_obey_permissions(metadata):
ds = Datasette(metadata=metadata)
db = ds.add_memory_database("foreign_key_labels")
await db.execute_write("create table a(id integer primary key, name text)")
await db.execute_write("insert into a (id, name) values (1, 'hello')")
await db.execute_write(
"create table b(id integer primary key, name text, a_id integer references a(id))"
"create table if not exists a(id integer primary key, name text)"
)
await db.execute_write("insert or replace into a (id, name) values (1, 'hello')")
await db.execute_write(
"create table if not exists b(id integer primary key, name text, a_id integer references a(id))"
)
await db.execute_write(
"insert or replace into b (id, name, a_id) values (1, 'world', 1)"
)
await db.execute_write("insert into b (id, name, a_id) values (1, 'world', 1)")
# Anonymous user can see table b but not table a
blah = await ds.client.get("/foreign_key_labels.json")
anon_a = await ds.client.get("/foreign_key_labels/a.json?_labels=on")