Skip to content

Commit

Permalink
Get working on both Datasette versions, refs #15
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Apr 26, 2024
1 parent c04d23e commit 11c7a83
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 29 deletions.
31 changes: 20 additions & 11 deletions datasette_secrets/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import click
from cryptography.fernet import Fernet
import dataclasses
from datasette import hookimpl, Forbidden, Permission, Response
from datasette import hookimpl, Forbidden, Response
from datasette.plugins import pm
from datasette.utils import await_me_maybe, sqlite3
import os
Expand Down Expand Up @@ -89,7 +89,7 @@ class Secret:
def get_database(datasette):
plugin_config = datasette.plugin_config("datasette-secrets") or {}
database = plugin_config.get("database") or "_internal"
if database == "_internal":
if database == "_internal" and hasattr(datasette, "get_internal_database"):
return datasette.get_internal_database()
return datasette.get_database(database)

Expand All @@ -108,6 +108,8 @@ def get_config(datasette):

@hookimpl
def register_permissions(datasette):
from datasette import Permission

return [
Permission(
name="manage-secrets",
Expand Down Expand Up @@ -187,15 +189,22 @@ async def secrets_index(datasette, request):
)
existing_secrets = {row["name"]: dict(row) for row in existing_secrets_result.rows}
# Try to turn updated_by into actors
actors = await datasette.actors_from_ids(
{row["updated_by"] for row in existing_secrets.values() if row["updated_by"]}
)
for secret in existing_secrets.values():
if secret["updated_by"]:
actor = actors.get(secret["updated_by"])
if actor:
display = actor.get("username") or actor.get("name") or actor.get("id")
secret["updated_by"] = display
if hasattr(datasette, "actors_from_ids"):
actors = await datasette.actors_from_ids(
{
row["updated_by"]
for row in existing_secrets.values()
if row["updated_by"]
}
)
for secret in existing_secrets.values():
if secret["updated_by"]:
actor = actors.get(secret["updated_by"])
if actor:
display = (
actor.get("username") or actor.get("name") or actor.get("id")
)
secret["updated_by"] = display
unset_secrets = [
secret
for secret in all_secrets
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ CI = "https://github.com/datasette/datasette-secrets/actions"
secrets = "datasette_secrets"

[project.optional-dependencies]
test = ["pytest", "pytest-asyncio"]
test = ["pytest", "pytest-asyncio", "datasette-test>=0.3"]

[tool.pytest.ini_options]
asyncio_mode = "strict"
Expand Down
44 changes: 27 additions & 17 deletions tests/test_secrets.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
from click.testing import CliRunner
from cryptography.fernet import Fernet
from datasette import hookimpl
from datasette.app import Datasette
from datasette.cli import cli
from datasette.plugins import pm
from datasette_test import Datasette, actor_cookie
from datasette_secrets import get_secret, Secret, startup, get_config
import pytest
from unittest.mock import ANY

TEST_ENCRYPTION_KEY = "-LujHtwFWGaBpznrV1zduoZBmCnMOW7J0H5hmeXgAVo="


def get_internal_database(ds):
if hasattr(ds, "get_internal_database"):
return ds.get_internal_database()
else:
return ds.get_database("_internal")


def test_generate_command():
runner = CliRunner()
result = runner.invoke(cli, ["secrets", "generate-encryption-key"])
Expand Down Expand Up @@ -89,15 +96,13 @@ def register_secrets(self):
@pytest.fixture
def ds():
return Datasette(
config={
"plugins": {
"datasette-secrets": {
"database": "_internal",
"encryption-key": TEST_ENCRYPTION_KEY,
}
},
"permissions": {"manage-secrets": {"id": "admin"}},
}
plugin_config={
"datasette-secrets": {
"database": "_internal",
"encryption-key": TEST_ENCRYPTION_KEY,
}
},
permissions={"manage-secrets": {"id": "admin"}},
)


Expand All @@ -115,7 +120,7 @@ async def test_permissions(ds, path, verb, data, user):
kwargs = {}
if user:
kwargs["cookies"] = {
"ds_actor": ds.client.actor_cookie({"id": user}),
"ds_actor": actor_cookie(ds, {"id": user}),
}
if data:
kwargs["data"] = data
Expand All @@ -131,7 +136,7 @@ async def test_permissions(ds, path, verb, data, user):

@pytest.mark.asyncio
async def test_set_secret(ds, use_actors_plugin):
cookies = {"ds_actor": ds.client.actor_cookie({"id": "admin"})}
cookies = {"ds_actor": actor_cookie(ds, {"id": "admin"})}
get_response = await ds.client.get("/-/secrets/EXAMPLE_SECRET", cookies=cookies)
csrftoken = get_response.cookies["ds_csrftoken"]
cookies["ds_csrftoken"] = csrftoken
Expand All @@ -142,7 +147,7 @@ async def test_set_secret(ds, use_actors_plugin):
)
assert post_response.status_code == 302
assert post_response.headers["Location"] == "/-/secrets"
internal_db = ds.get_internal_database()
internal_db = get_internal_database(ds)
secrets = await internal_db.execute("select * from datasette_secrets")
rows = [dict(r) for r in secrets.rows]
assert rows == [
Expand Down Expand Up @@ -174,7 +179,12 @@ async def test_set_secret(ds, use_actors_plugin):
assert response.status_code == 200
assert "EXAMPLE_SECRET" in response.text
assert "new-note" in response.text
assert "<td>ADMIN</td>" in response.text

if hasattr(ds, "actors_from_ids"):
assert "<td>ADMIN</td>" in response.text
else:
# Pre 1.0, so can't use that mechanism
assert "<td>admin</td>" in response.text

# Now let's edit it
post_response2 = await ds.client.post(
Expand Down Expand Up @@ -213,11 +223,11 @@ async def test_set_secret(ds, use_actors_plugin):
@pytest.mark.asyncio
async def test_get_secret(ds, monkeypatch):
# First set it manually
cookies = {"ds_actor": ds.client.actor_cookie({"id": "admin"})}
cookies = {"ds_actor": actor_cookie(ds, {"id": "admin"})}
get_response = await ds.client.get("/-/secrets/EXAMPLE_SECRET", cookies=cookies)
csrftoken = get_response.cookies["ds_csrftoken"]
cookies["ds_csrftoken"] = csrftoken
db = ds.get_internal_database()
db = get_internal_database(ds)
# Reset state
await db.execute_write(
"update datasette_secrets set last_used_at = null, last_used_by = null"
Expand Down Expand Up @@ -288,7 +298,7 @@ async def test_secret_index_page(ds, register_multiple_secrets):
response = await ds.client.get(
"/-/secrets",
cookies={
"ds_actor": ds.client.actor_cookie({"id": "admin"}),
"ds_actor": actor_cookie(ds, {"id": "admin"}),
},
)
assert response.status_code == 200
Expand Down

0 comments on commit 11c7a83

Please sign in to comment.