mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
New --root mechanism with datasette.root_enabled, closes #2521
This commit is contained in:
parent
1d37d30c2a
commit
5fc58c8775
7 changed files with 191 additions and 31 deletions
|
|
@ -4,6 +4,11 @@ from .utils import cookie_was_deleted, last_event
|
|||
from click.testing import CliRunner
|
||||
from datasette.utils import baseconv
|
||||
from datasette.cli import cli
|
||||
from datasette.resources import (
|
||||
InstanceResource,
|
||||
DatabaseResource,
|
||||
TableResource,
|
||||
)
|
||||
import pytest
|
||||
import time
|
||||
|
||||
|
|
@ -337,3 +342,123 @@ def test_cli_create_token(app_client, expires):
|
|||
else:
|
||||
expected_actor = None
|
||||
assert response.json == {"actor": expected_actor}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_root_with_root_enabled_gets_all_permissions(ds_client):
|
||||
"""Root user with root_enabled=True gets all permissions"""
|
||||
# Ensure catalog tables are populated
|
||||
await ds_client.ds.invoke_startup()
|
||||
await ds_client.ds._refresh_schemas()
|
||||
|
||||
# Set root_enabled to simulate --root flag
|
||||
ds_client.ds.root_enabled = True
|
||||
|
||||
root_actor = {"id": "root"}
|
||||
|
||||
# Test instance-level permissions (no resource)
|
||||
assert await ds_client.ds.permission_allowed(root_actor, "permissions-debug", None) is True
|
||||
assert await ds_client.ds.permission_allowed(root_actor, "debug-menu", None) is True
|
||||
|
||||
# Test view permissions using the new ds.allowed() method
|
||||
assert await ds_client.ds.allowed(
|
||||
action="view-instance",
|
||||
resource=InstanceResource(),
|
||||
actor=root_actor
|
||||
) is True
|
||||
|
||||
assert await ds_client.ds.allowed(
|
||||
action="view-database",
|
||||
resource=DatabaseResource("fixtures"),
|
||||
actor=root_actor
|
||||
) is True
|
||||
|
||||
assert await ds_client.ds.allowed(
|
||||
action="view-table",
|
||||
resource=TableResource("fixtures", "facetable"),
|
||||
actor=root_actor
|
||||
) is True
|
||||
|
||||
# Test write permissions using ds.allowed()
|
||||
assert await ds_client.ds.allowed(
|
||||
action="insert-row",
|
||||
resource=TableResource("fixtures", "facetable"),
|
||||
actor=root_actor
|
||||
) is True
|
||||
|
||||
assert await ds_client.ds.allowed(
|
||||
action="delete-row",
|
||||
resource=TableResource("fixtures", "facetable"),
|
||||
actor=root_actor
|
||||
) is True
|
||||
|
||||
assert await ds_client.ds.allowed(
|
||||
action="update-row",
|
||||
resource=TableResource("fixtures", "facetable"),
|
||||
actor=root_actor
|
||||
) is True
|
||||
|
||||
assert await ds_client.ds.allowed(
|
||||
action="create-table",
|
||||
resource=DatabaseResource("fixtures"),
|
||||
actor=root_actor
|
||||
) is True
|
||||
|
||||
assert await ds_client.ds.allowed(
|
||||
action="alter-table",
|
||||
resource=TableResource("fixtures", "facetable"),
|
||||
actor=root_actor
|
||||
) is True
|
||||
|
||||
assert await ds_client.ds.allowed(
|
||||
action="drop-table",
|
||||
resource=TableResource("fixtures", "facetable"),
|
||||
actor=root_actor
|
||||
) is True
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_root_without_root_enabled_no_special_permissions(ds_client):
|
||||
"""Root user without root_enabled doesn't get automatic permissions"""
|
||||
# Ensure catalog tables are populated
|
||||
await ds_client.ds.invoke_startup()
|
||||
await ds_client.ds._refresh_schemas()
|
||||
|
||||
# Ensure root_enabled is NOT set (or is False)
|
||||
ds_client.ds.root_enabled = False
|
||||
|
||||
root_actor = {"id": "root"}
|
||||
|
||||
# Test permissions that normally require special access
|
||||
# Without root_enabled, root should follow normal permission rules
|
||||
|
||||
# View permissions should still work (default=True)
|
||||
assert await ds_client.ds.allowed(
|
||||
action="view-instance",
|
||||
resource=InstanceResource(),
|
||||
actor=root_actor
|
||||
) is True # Default permission
|
||||
|
||||
assert await ds_client.ds.allowed(
|
||||
action="view-database",
|
||||
resource=DatabaseResource("fixtures"),
|
||||
actor=root_actor
|
||||
) is True # Default permission
|
||||
|
||||
# But restricted permissions should NOT automatically be granted
|
||||
# Test with instance-level permission (no resource class)
|
||||
result = await ds_client.ds.permission_allowed(root_actor, "permissions-debug", None)
|
||||
assert result is not True, "Root without root_enabled should not automatically get permissions-debug"
|
||||
|
||||
# Test with resource-based permissions using ds.allowed()
|
||||
assert await ds_client.ds.allowed(
|
||||
action="create-table",
|
||||
resource=DatabaseResource("fixtures"),
|
||||
actor=root_actor
|
||||
) is not True, "Root without root_enabled should not automatically get create-table"
|
||||
|
||||
assert await ds_client.ds.allowed(
|
||||
action="drop-table",
|
||||
resource=TableResource("fixtures", "facetable"),
|
||||
actor=root_actor
|
||||
) is not True, "Root without root_enabled should not automatically get drop-table"
|
||||
|
|
|
|||
|
|
@ -375,7 +375,8 @@ def test_permissions_checked(app_client, path, permissions):
|
|||
async def test_permissions_debug(ds_client, filter_):
|
||||
ds_client.ds._permission_checks.clear()
|
||||
assert (await ds_client.get("/-/permissions")).status_code == 403
|
||||
# With the cookie it should work
|
||||
# With the cookie it should work (need to set root_enabled for root user)
|
||||
ds_client.ds.root_enabled = True
|
||||
cookie = ds_client.actor_cookie({"id": "root"})
|
||||
response = await ds_client.get(
|
||||
f"/-/permissions?filter={filter_}", cookies={"ds_actor": cookie}
|
||||
|
|
@ -418,8 +419,8 @@ async def test_permissions_debug(ds_client, filter_):
|
|||
},
|
||||
{
|
||||
"action": "view-instance",
|
||||
"result": None,
|
||||
"used_default": True,
|
||||
"result": True,
|
||||
"used_default": False,
|
||||
"actor": {"id": "root"},
|
||||
},
|
||||
{"action": "debug-menu", "result": False, "used_default": True, "actor": None},
|
||||
|
|
@ -691,6 +692,7 @@ async def test_actor_restricted_permissions(
|
|||
perms_ds, actor, permission, resource_1, resource_2, expected_result
|
||||
):
|
||||
perms_ds.pdb = True
|
||||
perms_ds.root_enabled = True # Allow root actor to access /-/permissions
|
||||
cookies = {"ds_actor": perms_ds.sign({"a": {"id": "root"}}, "actor")}
|
||||
csrftoken = (await perms_ds.client.get("/-/permissions", cookies=cookies)).cookies[
|
||||
"ds_csrftoken"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue