--root option and /-/auth-token view, refs #784

This commit is contained in:
Simon Willison 2020-05-31 18:03:17 -07:00
commit 9f3d4aba31
9 changed files with 89 additions and 8 deletions

View file

@ -2,6 +2,7 @@ from datasette.app import Datasette
from datasette.utils import sqlite3
from asgiref.testing import ApplicationCommunicator
from asgiref.sync import async_to_sync
from http.cookies import SimpleCookie
import itertools
import json
import os
@ -44,10 +45,14 @@ class TestClient:
self.asgi_app = asgi_app
@async_to_sync
async def get(self, path, allow_redirects=True, redirect_count=0, method="GET"):
return await self._get(path, allow_redirects, redirect_count, method)
async def get(
self, path, allow_redirects=True, redirect_count=0, method="GET", cookies=None
):
return await self._get(path, allow_redirects, redirect_count, method, cookies)
async def _get(self, path, allow_redirects=True, redirect_count=0, method="GET"):
async def _get(
self, path, allow_redirects=True, redirect_count=0, method="GET", cookies=None
):
query_string = b""
if "?" in path:
path, _, query_string = path.partition("?")
@ -56,6 +61,12 @@ class TestClient:
raw_path = path.encode("latin-1")
else:
raw_path = quote(path, safe="/:,").encode("latin-1")
headers = [[b"host", b"localhost"]]
if cookies:
sc = SimpleCookie()
for key, value in cookies.items():
sc[key] = value
headers.append([b"cookie", sc.output(header="").encode("utf-8")])
scope = {
"type": "http",
"http_version": "1.0",
@ -63,7 +74,7 @@ class TestClient:
"path": unquote(path),
"raw_path": raw_path,
"query_string": query_string,
"headers": [[b"host", b"localhost"]],
"headers": headers,
}
instance = ApplicationCommunicator(self.asgi_app, scope)
await instance.send_input({"type": "http.request"})

25
tests/test_auth.py Normal file
View file

@ -0,0 +1,25 @@
from .fixtures import app_client
def test_auth_token(app_client):
"The /-/auth-token endpoint sets the correct cookie"
assert app_client.ds._root_token is not None
path = "/-/auth-token?token={}".format(app_client.ds._root_token)
response = app_client.get(path, allow_redirects=False,)
assert 302 == response.status
assert "/" == response.headers["Location"]
set_cookie = response.headers["set-cookie"]
assert set_cookie.endswith("; Path=/")
assert set_cookie.startswith("ds_actor=")
cookie_value = set_cookie.split("ds_actor=")[1].split("; Path=/")[0]
assert {"id": "root"} == app_client.ds.unsign(cookie_value, "actor")
# Check that a second with same token fails
assert app_client.ds._root_token is None
assert 403 == app_client.get(path, allow_redirects=False,).status
def test_actor_cookie(app_client):
"A valid actor cookie sets request.scope['actor']"
cookie = app_client.ds.sign({"id": "test"}, "actor")
response = app_client.get("/", cookies={"ds_actor": cookie})
assert {"id": "test"} == app_client.ds._last_request.scope["actor"]

View file

@ -76,6 +76,7 @@ def test_metadata_yaml():
memory=False,
config=[],
secret=None,
root=False,
version_note=None,
help_config=False,
return_instance=True,

View file

@ -65,8 +65,8 @@ def documented_views():
first_word = label.split("_")[0]
if first_word.endswith("View"):
view_labels.add(first_word)
# We deliberately don't document this one:
view_labels.add("PatternPortfolioView")
# We deliberately don't document these:
view_labels.update(("PatternPortfolioView", "AuthTokenView"))
return view_labels