From c6a811237c00684c9f1e3a28a717425046cab3da Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Mon, 12 Dec 2022 20:11:51 -0800 Subject: [PATCH] /-/actor.json no longer requires view-instance, closes #1945 --- datasette/app.py | 4 +++- datasette/views/special.py | 13 +++++++++++-- tests/test_permissions.py | 24 ++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/datasette/app.py b/datasette/app.py index 52b70c3e..878e484f 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -1262,7 +1262,9 @@ class Datasette: r"/-/databases(\.(?Pjson))?$", ) add_route( - JsonDataView.as_view(self, "actor.json", self._actor, needs_request=True), + JsonDataView.as_view( + self, "actor.json", self._actor, needs_request=True, permission=None + ), r"/-/actor(\.(?Pjson))?$", ) add_route( diff --git a/datasette/views/special.py b/datasette/views/special.py index bae94ebc..30345d14 100644 --- a/datasette/views/special.py +++ b/datasette/views/special.py @@ -10,15 +10,24 @@ import urllib class JsonDataView(BaseView): name = "json_data" - def __init__(self, datasette, filename, data_callback, needs_request=False): + def __init__( + self, + datasette, + filename, + data_callback, + needs_request=False, + permission="view-instance", + ): self.ds = datasette self.filename = filename self.data_callback = data_callback self.needs_request = needs_request + self.permission = permission async def get(self, request): as_format = request.url_vars["format"] - await self.ds.ensure_permissions(request.actor, ["view-instance"]) + if self.permission: + await self.ds.ensure_permissions(request.actor, [self.permission]) if self.needs_request: data = self.data_callback(request) else: diff --git a/tests/test_permissions.py b/tests/test_permissions.py index 9f83ef29..0679e9b5 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -8,6 +8,7 @@ from pprint import pprint import pytest_asyncio import pytest import re +import time import urllib @@ -818,3 +819,26 @@ async def test_permissions_in_metadata( assert result == expected_result finally: perms_ds._metadata_local = previous_metadata + + +@pytest.mark.asyncio +async def test_actor_endpoint_allows_any_token(): + ds = Datasette() + token = ds.sign( + { + "a": "root", + "token": "dstok", + "t": int(time.time()), + "_r": {"a": ["debug-menu"]}, + }, + namespace="token", + ) + response = await ds.client.get( + "/-/actor.json", headers={"Authorization": f"Bearer dstok_{token}"} + ) + assert response.status_code == 200 + assert response.json()["actor"] == { + "id": "root", + "token": "dstok", + "_r": {"a": ["debug-menu"]}, + }