Use longest possible matching URL for auth, refs #3

This commit is contained in:
Simon Willison 2023-07-17 16:03:05 -07:00
commit 98d714c5e1
3 changed files with 41 additions and 10 deletions

View file

@ -2,7 +2,7 @@ import click
import httpx
import json
import pathlib
from .utils import url_matches_prefix
from .utils import token_for_url
def get_config_dir():
@ -33,7 +33,7 @@ def query(url, sql, token):
url += ".json"
if token is None:
# Maybe there's a token in auth.json?
token = _token_for_url_from_auth(url, get_config_dir() / "auth.json")
token = token_for_url(url, _load_auths(get_config_dir() / "auth.json"))
headers = {}
if token:
headers["Authorization"] = f"Bearer {token}"
@ -77,13 +77,6 @@ def query(url, sql, token):
click.echo(json.dumps(response.json()["rows"], indent=2))
def _token_for_url_from_auth(url, auth_file):
auths = _load_auths(auth_file)
for auth_url, token in auths.items():
if url_matches_prefix(url, auth_url):
return token
@cli.group()
def alias():
"Manage aliases for different instances"

View file

@ -28,3 +28,15 @@ def url_matches_prefix(url: str, prefix: str) -> bool:
prefix_path += "/"
return url_path.startswith(prefix_path)
def token_for_url(url: str, tokens: dict) -> str:
matches = []
for prefix_url, token in tokens.items():
if url_matches_prefix(url, prefix_url):
matches.append((prefix_url, token))
# Sort by length of prefix_url, so that the longest match is first
matches.sort(key=lambda x: len(x[0]), reverse=True)
if matches:
return matches[0][1]
return None

View file

@ -1,4 +1,4 @@
from dclient.utils import url_matches_prefix
from dclient.utils import token_for_url, url_matches_prefix
import pytest
@ -39,3 +39,29 @@ import pytest
)
def test_url_matches_prefix(url, prefix_url, expected):
assert url_matches_prefix(url, prefix_url) == expected
@pytest.mark.parametrize(
"url,tokens,expected",
(
("https://foo.com/bar", {"https://foo.com": "foo"}, "foo"),
("https://foo.com/bar", {"https://foo.com/baz": "baz"}, None),
(
"https://foo.com/bar",
{"https://foo.com": "foo", "https://foo.com/bar": "bar"},
"bar",
),
(
"https://foo.com/bar/baz",
{
"https://foo.com": "foo",
"https://foo.com/bar/baz": "baz",
"https://foo.com/bar": "bar",
},
"baz",
),
),
)
def test_token_for_url(url, tokens, expected):
# Should always return longest matching of the available options
assert token_for_url(url, tokens) == expected