kopia lustrzana https://github.com/simonw/datasette
134 wiersze
4.7 KiB
Python
134 wiersze
4.7 KiB
Python
"""
|
|
Test for actor restrictions bug with database-level config.
|
|
|
|
This test currently FAILS, demonstrating the bug where database-level
|
|
config allow blocks can bypass table-level restrictions.
|
|
"""
|
|
|
|
import pytest
|
|
from datasette.app import Datasette
|
|
from datasette.resources import TableResource
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_table_restrictions_not_bypassed_by_database_level_config():
|
|
"""
|
|
Actor restrictions should act as hard limits that config cannot override.
|
|
|
|
BUG: When an actor has table-level restrictions (e.g., only table2 and table3)
|
|
but config has a database-level allow block, the database-level config rule
|
|
currently allows ALL tables, not just those in the restriction allowlist.
|
|
|
|
This test documents the expected behavior and will FAIL until the bug is fixed.
|
|
"""
|
|
# Config grants access at DATABASE level (not table level)
|
|
config = {
|
|
"databases": {
|
|
"test_db_rnbbdlc": {
|
|
"allow": {
|
|
"id": "user"
|
|
} # Database-level allow - grants access to all tables
|
|
}
|
|
}
|
|
}
|
|
|
|
ds = Datasette(config=config)
|
|
await ds.invoke_startup()
|
|
db = ds.add_memory_database("test_db_rnbbdlc")
|
|
await db.execute_write("create table table1 (id integer primary key)")
|
|
await db.execute_write("create table table2 (id integer primary key)")
|
|
await db.execute_write("create table table3 (id integer primary key)")
|
|
await db.execute_write("create table table4 (id integer primary key)")
|
|
|
|
# Actor restricted to ONLY table2 and table3
|
|
# Even though config allows the whole database, restrictions should limit access
|
|
actor = {
|
|
"id": "user",
|
|
"_r": {
|
|
"r": { # Resource-level (table-level) restrictions
|
|
"test_db_rnbbdlc": {
|
|
"table2": ["vt"], # vt = view-table abbreviation
|
|
"table3": ["vt"],
|
|
}
|
|
}
|
|
},
|
|
}
|
|
|
|
# table2 should be allowed (in restriction allowlist AND config allows)
|
|
result = await ds.allowed(
|
|
action="view-table",
|
|
resource=TableResource("test_db_rnbbdlc", "table2"),
|
|
actor=actor,
|
|
)
|
|
assert result is True, "table2 should be allowed - in restriction allowlist"
|
|
|
|
# table3 should be allowed (in restriction allowlist AND config allows)
|
|
result = await ds.allowed(
|
|
action="view-table",
|
|
resource=TableResource("test_db_rnbbdlc", "table3"),
|
|
actor=actor,
|
|
)
|
|
assert result is True, "table3 should be allowed - in restriction allowlist"
|
|
|
|
# table1 should be DENIED (NOT in restriction allowlist)
|
|
# Even though database-level config allows it, restrictions should deny it
|
|
result = await ds.allowed(
|
|
action="view-table",
|
|
resource=TableResource("test_db_rnbbdlc", "table1"),
|
|
actor=actor,
|
|
)
|
|
assert (
|
|
result is False
|
|
), "table1 should be DENIED - not in restriction allowlist, config cannot override"
|
|
|
|
# table4 should be DENIED (NOT in restriction allowlist)
|
|
# Even though database-level config allows it, restrictions should deny it
|
|
result = await ds.allowed(
|
|
action="view-table",
|
|
resource=TableResource("test_db_rnbbdlc", "table4"),
|
|
actor=actor,
|
|
)
|
|
assert (
|
|
result is False
|
|
), "table4 should be DENIED - not in restriction allowlist, config cannot override"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_database_restrictions_with_database_level_config():
|
|
"""
|
|
Verify that database-level restrictions work correctly with database-level config.
|
|
|
|
This should pass - it's testing the case where restriction granularity
|
|
matches config granularity.
|
|
"""
|
|
config = {
|
|
"databases": {"test_db_rwdl": {"allow": {"id": "user"}}} # Database-level allow
|
|
}
|
|
|
|
ds = Datasette(config=config)
|
|
await ds.invoke_startup()
|
|
db = ds.add_memory_database("test_db_rwdl")
|
|
await db.execute_write("create table table1 (id integer primary key)")
|
|
await db.execute_write("create table table2 (id integer primary key)")
|
|
|
|
# Actor has database-level restriction (all tables in test_db_rwdl)
|
|
actor = {
|
|
"id": "user",
|
|
"_r": {"d": {"test_db_rwdl": ["vt"]}}, # Database-level restrictions
|
|
}
|
|
|
|
# Both tables should be allowed (database-level restriction matches database-level config)
|
|
result = await ds.allowed(
|
|
action="view-table",
|
|
resource=TableResource("test_db_rwdl", "table1"),
|
|
actor=actor,
|
|
)
|
|
assert result is True, "table1 should be allowed"
|
|
|
|
result = await ds.allowed(
|
|
action="view-table",
|
|
resource=TableResource("test_db_rwdl", "table2"),
|
|
actor=actor,
|
|
)
|
|
assert result is True, "table2 should be allowed"
|