mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
Implemented datasette.permission_allowed(), refs #699
This commit is contained in:
parent
461c82838d
commit
9315bacf6f
5 changed files with 75 additions and 4 deletions
|
|
@ -406,6 +406,25 @@ class Datasette:
|
|||
# pylint: disable=no-member
|
||||
pm.hook.prepare_connection(conn=conn, database=database, datasette=self)
|
||||
|
||||
async def permission_allowed(
|
||||
self, actor, action, resource_type=None, resource_identifier=None, default=False
|
||||
):
|
||||
"Check permissions using the permissions_allowed plugin hook"
|
||||
for check in pm.hook.permission_allowed(
|
||||
datasette=self,
|
||||
actor=actor,
|
||||
action=action,
|
||||
resource_type=resource_type,
|
||||
resource_identifier=resource_identifier,
|
||||
):
|
||||
if callable(check):
|
||||
check = check()
|
||||
if asyncio.iscoroutine(check):
|
||||
check = await check
|
||||
if check is not None:
|
||||
return check
|
||||
return default
|
||||
|
||||
async def execute(
|
||||
self,
|
||||
db_name,
|
||||
|
|
|
|||
|
|
@ -111,6 +111,25 @@ This method lets you read plugin configuration values that were set in ``metadat
|
|||
|
||||
Renders a `Jinja template <https://jinja.palletsprojects.com/en/2.11.x/>`__ using Datasette's preconfigured instance of Jinja and returns the resulting string. The template will have access to Datasette's default template functions and any functions that have been made available by other plugins.
|
||||
|
||||
await .permission_allowed(actor, action, resource_type=None, resource_identifier=None, default=False)
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
|
||||
``actor`` - dictionary
|
||||
The authenticated actor. This is usually ``request.scope.get("actor")``.
|
||||
|
||||
``action`` - string
|
||||
The name of the action that is being permission checked.
|
||||
|
||||
``resource_type`` - string, optional
|
||||
The type of resource being checked, e.g. ``"table"``.
|
||||
|
||||
``resource_identifier`` - string, optional
|
||||
The resource identifier, e.g. the name of the table.
|
||||
|
||||
Check if the given actor has permission to perform the given action on the given resource. This uses plugins that implement the :ref:`plugin_permission_allowed` plugin hook to decide if the action is allowed or not.
|
||||
|
||||
If none of the plugins express an opinion, the return value will be the ``default`` argument. This is deny, but you can pass ``default=True`` to default allow instead.
|
||||
|
||||
.. _datasette_get_database:
|
||||
|
||||
.get_database(name)
|
||||
|
|
|
|||
|
|
@ -134,3 +134,11 @@ def actor_from_request(datasette, request):
|
|||
return {"id": "bot"}
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
@hookimpl
|
||||
def permission_allowed(actor, action):
|
||||
if action == "this_is_allowed":
|
||||
return True
|
||||
elif action == "this_is_denied":
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -107,3 +107,16 @@ def actor_from_request(datasette, request):
|
|||
return None
|
||||
|
||||
return inner
|
||||
|
||||
|
||||
@hookimpl
|
||||
def permission_allowed(datasette, actor, action):
|
||||
# Testing asyncio version of permission_allowed
|
||||
async def inner():
|
||||
assert 2 == (await datasette.get_database().execute("select 1 + 1")).first()[0]
|
||||
if action == "this_is_allowed_async":
|
||||
return True
|
||||
elif action == "this_is_denied_async":
|
||||
return False
|
||||
|
||||
return inner
|
||||
|
|
|
|||
|
|
@ -523,7 +523,19 @@ def test_actor_from_request_async(app_client):
|
|||
assert {"id": "bot2", "1+1": 2} == app_client.ds._last_request.scope["actor"]
|
||||
|
||||
|
||||
@pytest.mark.xfail
|
||||
def test_permission_allowed(app_client):
|
||||
# TODO
|
||||
assert False
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
"action,expected",
|
||||
[
|
||||
("this_is_allowed", True),
|
||||
("this_is_denied", False),
|
||||
("this_is_allowed_async", True),
|
||||
("this_is_denied_async", False),
|
||||
("no_match", None),
|
||||
],
|
||||
)
|
||||
async def test_permission_allowed(app_client, action, expected):
|
||||
actual = await app_client.ds.permission_allowed(
|
||||
{"id": "actor"}, action, default=None
|
||||
)
|
||||
assert expected == actual
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue