diff --git a/datasette/app.py b/datasette/app.py index ca2efa91..c684eabc 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -908,6 +908,7 @@ class DatasetteRouter(AsgiRouter): ): scope_modifications["scheme"] = "https" # Handle authentication + default_actor = scope.get("actor") or None actor = None for actor in pm.hook.actor_from_request( datasette=self.ds, request=Request(scope, receive) @@ -918,7 +919,7 @@ class DatasetteRouter(AsgiRouter): actor = await actor if actor: break - scope_modifications["actor"] = actor + scope_modifications["actor"] = actor or default_actor return await super().route_path( dict(scope, **scope_modifications), receive, send, path ) diff --git a/tests/fixtures.py b/tests/fixtures.py index a4a96919..612bee99 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -39,6 +39,7 @@ EXPECTED_PLUGINS = [ "version": None, "hooks": [ "actor_from_request", + "asgi_wrapper", "extra_body_script", "extra_css_urls", "extra_js_urls", diff --git a/tests/plugins/my_plugin.py b/tests/plugins/my_plugin.py index 72736e84..a86e3cbf 100644 --- a/tests/plugins/my_plugin.py +++ b/tests/plugins/my_plugin.py @@ -137,6 +137,20 @@ def actor_from_request(datasette, request): return None +@hookimpl +def asgi_wrapper(): + def wrap(app): + async def maybe_set_actor_in_scope(scope, recieve, send): + if b"_actor_in_scope" in scope["query_string"]: + scope = dict(scope, actor={"id": "from-scope"}) + print(scope) + await app(scope, recieve, send) + + return maybe_set_actor_in_scope + + return wrap + + @hookimpl def permission_allowed(actor, action): if action == "this_is_allowed": diff --git a/tests/test_plugins.py b/tests/test_plugins.py index e3a234f2..245c60f7 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -534,6 +534,11 @@ def test_actor_from_request_async(app_client): assert {"id": "bot2", "1+1": 2} == app_client.ds._last_request.scope["actor"] +def test_existing_scope_actor_respected(app_client): + app_client.get("/?_actor_in_scope=1") + assert {"id": "from-scope"} == app_client.ds._last_request.scope["actor"] + + @pytest.mark.asyncio @pytest.mark.parametrize( "action,expected",