mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
confirm: true mechanism for drop table API, closes #1887
This commit is contained in:
parent
db796771e2
commit
612da8eae6
4 changed files with 64 additions and 8 deletions
|
|
@ -336,7 +336,7 @@ class ApiExplorerView(BaseView):
|
||||||
{
|
{
|
||||||
"path": self.ds.urls.table(name, table) + "/-/drop",
|
"path": self.ds.urls.table(name, table) + "/-/drop",
|
||||||
"label": "Drop table {}".format(table),
|
"label": "Drop table {}".format(table),
|
||||||
"json": {},
|
"json": {"confirm": False},
|
||||||
"method": "POST",
|
"method": "POST",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1236,6 +1236,26 @@ class TableDropView(BaseView):
|
||||||
request.actor, "drop-table", resource=(database_name, table_name)
|
request.actor, "drop-table", resource=(database_name, table_name)
|
||||||
):
|
):
|
||||||
return _error(["Permission denied"], 403)
|
return _error(["Permission denied"], 403)
|
||||||
|
|
||||||
|
confirm = False
|
||||||
|
try:
|
||||||
|
data = json.loads(await request.post_body())
|
||||||
|
confirm = data.get("confirm")
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not confirm:
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
"ok": True,
|
||||||
|
"row_count": (
|
||||||
|
await db.execute("select count(*) from [{}]".format(table_name))
|
||||||
|
).single_value(),
|
||||||
|
"message": 'Pass "confirm": true to confirm',
|
||||||
|
},
|
||||||
|
status=200,
|
||||||
|
)
|
||||||
|
|
||||||
# Drop table
|
# Drop table
|
||||||
def drop_table(conn):
|
def drop_table(conn):
|
||||||
sqlite_utils.Database(conn)[table_name].drop()
|
sqlite_utils.Database(conn)[table_name].drop()
|
||||||
|
|
|
||||||
|
|
@ -572,6 +572,24 @@ To drop a table, make a ``POST`` to ``/<database>/<table>/-/drop``. This require
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
Authorization: Bearer dstok_<rest-of-token>
|
Authorization: Bearer dstok_<rest-of-token>
|
||||||
|
|
||||||
If successful, this will return a ``200`` status code and a ``{"ok": true}`` response body.
|
Without a POST body this will return a status ``200`` with a note about how many rows will be deleted:
|
||||||
|
|
||||||
|
.. code-block:: json
|
||||||
|
|
||||||
|
{
|
||||||
|
"ok": true,
|
||||||
|
"row_count": 5,
|
||||||
|
"message": "Pass \"confirm\": true to confirm"
|
||||||
|
}
|
||||||
|
|
||||||
|
If you pass the following POST body:
|
||||||
|
|
||||||
|
.. code-block:: json
|
||||||
|
|
||||||
|
{
|
||||||
|
"confirm": true
|
||||||
|
}
|
||||||
|
|
||||||
|
Then the table will be dropped and a status ``200`` response of ``{"ok": true}`` will be returned.
|
||||||
|
|
||||||
Any errors will return ``{"errors": ["... descriptive message ..."], "ok": false}``, and a ``400`` status code for a bad input or a ``403`` status code for an authentication or permission error.
|
Any errors will return ``{"errors": ["... descriptive message ..."], "ok": false}``, and a ``400`` status code for a bad input or a ``403`` status code for an authentication or permission error.
|
||||||
|
|
|
||||||
|
|
@ -348,7 +348,9 @@ async def test_drop_table(ds_write, scenario):
|
||||||
else:
|
else:
|
||||||
token = write_token(ds_write)
|
token = write_token(ds_write)
|
||||||
should_work = scenario == "has_perm"
|
should_work = scenario == "has_perm"
|
||||||
|
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 = "/data/{}/-/drop".format("docs" if scenario != "bad_table" else "bad_table")
|
||||||
response = await ds_write.client.post(
|
response = await ds_write.client.post(
|
||||||
path,
|
path,
|
||||||
|
|
@ -357,11 +359,7 @@ async def test_drop_table(ds_write, scenario):
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if should_work:
|
if not should_work:
|
||||||
assert response.status_code == 200
|
|
||||||
assert response.json() == {"ok": True}
|
|
||||||
assert (await ds_write.client.get("/data/docs")).status_code == 404
|
|
||||||
else:
|
|
||||||
assert (
|
assert (
|
||||||
response.status_code == 403
|
response.status_code == 403
|
||||||
if scenario in ("no_token", "bad_token")
|
if scenario in ("no_token", "bad_token")
|
||||||
|
|
@ -374,3 +372,23 @@ async def test_drop_table(ds_write, scenario):
|
||||||
else ["Table not found: bad_table"]
|
else ["Table not found: bad_table"]
|
||||||
)
|
)
|
||||||
assert (await ds_write.client.get("/data/docs")).status_code == 200
|
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,
|
||||||
|
"row_count": 1,
|
||||||
|
"message": 'Pass "confirm": true to confirm',
|
||||||
|
}
|
||||||
|
assert (await ds_write.client.get("/data/docs")).status_code == 200
|
||||||
|
# Now send confirm: true
|
||||||
|
response2 = await ds_write.client.post(
|
||||||
|
path,
|
||||||
|
json={"confirm": True},
|
||||||
|
headers={
|
||||||
|
"Authorization": "Bearer {}".format(token),
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert response2.json() == {"ok": True}
|
||||||
|
assert (await ds_write.client.get("/data/docs")).status_code == 404
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue