kopia lustrzana https://github.com/simonw/datasette
Extra permission rules for /-/create, closes #1937
rodzic
e238df3959
commit
c094dde3ff
|
@ -613,6 +613,13 @@ class TableCreateView(BaseView):
|
|||
ignore = data.get("ignore")
|
||||
replace = data.get("replace")
|
||||
|
||||
if replace:
|
||||
# Must have update-row permission
|
||||
if not await self.ds.permission_allowed(
|
||||
request.actor, "update-row", resource=database_name
|
||||
):
|
||||
return _error(["Permission denied - need update-row"], 403)
|
||||
|
||||
table_name = data.get("table")
|
||||
if not table_name:
|
||||
return _error(["Table is required"])
|
||||
|
@ -630,6 +637,13 @@ class TableCreateView(BaseView):
|
|||
if rows and row:
|
||||
return _error(["Cannot specify both rows and row"])
|
||||
|
||||
if rows or row:
|
||||
# Must have insert-row permission
|
||||
if not await self.ds.permission_allowed(
|
||||
request.actor, "insert-row", resource=database_name
|
||||
):
|
||||
return _error(["Permission denied - need insert-row"], 403)
|
||||
|
||||
if columns:
|
||||
if rows or row:
|
||||
return _error(["Cannot specify columns with rows or row"])
|
||||
|
|
|
@ -830,7 +830,8 @@ If the table is successfully created this will return a ``201`` status code and
|
|||
Creating a table from example data
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Instead of specifying ``columns`` directly you can instead pass a single example ``row`` or a list of ``rows``. Datasette will create a table with a schema that matches those rows and insert them for you:
|
||||
Instead of specifying ``columns`` directly you can instead pass a single example ``row`` or a list of ``rows``.
|
||||
Datasette will create a table with a schema that matches those rows and insert them for you:
|
||||
|
||||
::
|
||||
|
||||
|
@ -855,6 +856,8 @@ Instead of specifying ``columns`` directly you can instead pass a single example
|
|||
"pk": "id"
|
||||
}
|
||||
|
||||
Doing this requires both the :ref:`permissions_create_table` and :ref:`permissions_insert_row` permissions.
|
||||
|
||||
The ``201`` response here will be similar to the ``columns`` form, but will also include the number of rows that were inserted as ``row_count``:
|
||||
|
||||
.. code-block:: json
|
||||
|
@ -884,6 +887,8 @@ If you pass a row to the create endpoint with a primary key that already exists
|
|||
|
||||
You can avoid this error by passing the same ``"ignore": true`` or ``"replace": true`` options to the create endpoint as you can to the :ref:`insert endpoint <TableInsertView>`.
|
||||
|
||||
To use the ``"replace": true`` option you will also need the :ref:`permissions_update_row` permission.
|
||||
|
||||
.. _TableDropView:
|
||||
|
||||
Dropping tables
|
||||
|
|
|
@ -1096,6 +1096,50 @@ async def test_create_table(ds_write, input, expected_status, expected_response)
|
|||
assert data == expected_response
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
"permissions,body,expected_status,expected_errors",
|
||||
(
|
||||
(["create-table"], {"table": "t", "columns": [{"name": "c"}]}, 201, None),
|
||||
# Need insert-row too if you use "rows":
|
||||
(
|
||||
["create-table"],
|
||||
{"table": "t", "rows": [{"name": "c"}]},
|
||||
403,
|
||||
["Permission denied - need insert-row"],
|
||||
),
|
||||
# This should work:
|
||||
(
|
||||
["create-table", "insert-row"],
|
||||
{"table": "t", "rows": [{"name": "c"}]},
|
||||
201,
|
||||
None,
|
||||
),
|
||||
# If you use replace: true you need update-row too:
|
||||
(
|
||||
["create-table", "insert-row"],
|
||||
{"table": "t", "rows": [{"id": 1}], "pk": "id", "replace": True},
|
||||
403,
|
||||
["Permission denied - need update-row"],
|
||||
),
|
||||
),
|
||||
)
|
||||
async def test_create_table_permissions(
|
||||
ds_write, permissions, body, expected_status, expected_errors
|
||||
):
|
||||
token = ds_write.create_token("root", restrict_all=["view-instance"] + permissions)
|
||||
response = await ds_write.client.post(
|
||||
"/data/-/create",
|
||||
json=body,
|
||||
headers=_headers(token),
|
||||
)
|
||||
assert response.status_code == expected_status
|
||||
if expected_errors:
|
||||
data = response.json()
|
||||
assert data["ok"] is False
|
||||
assert data["errors"] == expected_errors
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
"input,expected_rows_after",
|
||||
|
|
Ładowanie…
Reference in New Issue