Skip to content

Commit

Permalink
Error for drop against immutable database, closes #1874
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Nov 14, 2022
1 parent 612da8e commit 65521f0
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 12 deletions.
5 changes: 4 additions & 1 deletion datasette/views/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -1236,7 +1236,8 @@ async def post(self, request):
request.actor, "drop-table", resource=(database_name, table_name)
):
return _error(["Permission denied"], 403)

if not db.is_mutable:
return _error(["Database is immutable"], 403)
confirm = False
try:
data = json.loads(await request.post_body())
Expand All @@ -1248,6 +1249,8 @@ async def post(self, request):
return Response.json(
{
"ok": True,
"database": database_name,
"table": table_name,
"row_count": (
await db.execute("select count(*) from [{}]".format(table_name))
).single_value(),
Expand Down
2 changes: 2 additions & 0 deletions docs/json_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,8 @@ Without a POST body this will return a status ``200`` with a note about how many
{
"ok": true,
"database": "<database>",
"table": "<table>",
"row_count": 5,
"message": "Pass \"confirm\": true to confirm"
}
Expand Down
35 changes: 24 additions & 11 deletions tests/test_api_write.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@
def ds_write(tmp_path_factory):
db_directory = tmp_path_factory.mktemp("dbs")
db_path = str(db_directory / "data.db")
db = sqlite3.connect(str(db_path))
db.execute("vacuum")
db.execute("create table docs (id integer primary key, title text, score float)")
ds = Datasette([db_path])
db_path_immutable = str(db_directory / "immutable.db")
db1 = sqlite3.connect(str(db_path))
db2 = sqlite3.connect(str(db_path_immutable))
for db in (db1, db2):
db.execute("vacuum")
db.execute(
"create table docs (id integer primary key, title text, score float)"
)
ds = Datasette([db_path], immutables=[db_path_immutable])
yield ds
db.close()

Expand Down Expand Up @@ -339,7 +344,9 @@ async def test_delete_row(ds_write, scenario):


@pytest.mark.asyncio
@pytest.mark.parametrize("scenario", ("no_token", "no_perm", "bad_table", "has_perm"))
@pytest.mark.parametrize(
"scenario", ("no_token", "no_perm", "bad_table", "has_perm", "immutable")
)
async def test_drop_table(ds_write, scenario):
if scenario == "no_token":
token = "bad_token"
Expand All @@ -351,7 +358,10 @@ async def test_drop_table(ds_write, scenario):
await ds_write.get_database("data").execute_write(
"insert into docs (id, title) values (1, 'Row 1')"
)
path = "/data/{}/-/drop".format("docs" if scenario != "bad_table" else "bad_table")
path = "/{database}/{table}/-/drop".format(
database="immutable" if scenario == "immutable" else "data",
table="docs" if scenario != "bad_table" else "bad_table",
)
response = await ds_write.client.post(
path,
headers={
Expand All @@ -366,17 +376,20 @@ async def test_drop_table(ds_write, scenario):
else 404
)
assert response.json()["ok"] is False
assert (
response.json()["errors"] == ["Permission denied"]
if scenario == "no_token"
else ["Table not found: bad_table"]
)
expected_error = "Permission denied"
if scenario == "bad_table":
expected_error = "Table not found: bad_table"
elif scenario == "immutable":
expected_error = "Database is immutable"
assert response.json()["errors"] == [expected_error]
assert (await ds_write.client.get("/data/docs")).status_code == 200
else:
# It should show a confirmation page
assert response.status_code == 200
assert response.json() == {
"ok": True,
"database": "data",
"table": "docs",
"row_count": 1,
"message": 'Pass "confirm": true to confirm',
}
Expand Down

0 comments on commit 65521f0

Please sign in to comment.