dclient auth prototype, refs #3

This commit is contained in:
Simon Willison 2023-01-22 13:07:52 -08:00
commit 7b900eb3bf

View file

@ -18,7 +18,8 @@ def cli():
@cli.command()
@click.argument("url")
@click.argument("sql")
def query(url, sql):
@click.option("--token", "-t", help="API token")
def query(url, sql, token):
"""
Run a SQL query against a Datasette database URL
@ -30,7 +31,13 @@ def query(url, sql):
url = aliases[url]
if not url.endswith(".json"):
url += ".json"
response = httpx.get(url, params={"sql": sql, "_shape": "objects"})
if token is None:
# Maybe there's a token in auth.json?
token = _token_for_url_from_auth(url, get_config_dir() / "auth.json")
headers = {}
if token:
headers["Authorization"] = f"Bearer {token}"
response = httpx.get(url, params={"sql": sql, "_shape": "objects"}, headers=headers)
if response.status_code != 200 or not response.json()["ok"]:
data = response.json()
bits = []
@ -43,6 +50,13 @@ def query(url, sql):
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.startswith(auth_url):
return token
@cli.group()
def alias():
"Manage aliases for different instances"
@ -88,9 +102,49 @@ def remove(name):
raise click.ClickException("No such alias")
@cli.group()
def auth():
"Manage authentication for different instances"
@auth.command()
@click.argument("alias_or_url")
@click.option("--token", prompt=True, hide_input=True)
def add(alias_or_url, token):
"Add an authentication token"
aliases_file = get_config_dir() / "aliases.json"
aliases = _load_aliases(aliases_file)
url = alias_or_url
if alias_or_url in aliases:
url = aliases[alias_or_url]
config_dir = get_config_dir()
config_dir.mkdir(parents=True, exist_ok=True)
auth_file = config_dir / "auth.json"
auths = _load_auths(auth_file)
auths[url] = token
auth_file.write_text(json.dumps(auths, indent=4))
@auth.command(name="list")
def list_():
"List auths"
auths_file = get_config_dir() / "auth.json"
print(auths_file)
auths = _load_auths(auths_file)
click.echo(json.dumps(auths, indent=2))
def _load_aliases(aliases_file):
if aliases_file.exists():
aliases = json.loads(aliases_file.read_text())
else:
aliases = {}
return aliases
def _load_auths(auth_file):
if auth_file.exists():
auths = json.loads(auth_file.read_text())
else:
auths = {}
return auths