mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
Permissions SQL API improvements (#2558)
* Neater design for PermissionSQL class, refs #2556 - source is now automatically set to the source plugin - params is optional * PermissionSQL.allow() and PermissionSQL.deny() shortcuts Closes #2556 * Filter out temp database from attached_databases() Refs https://github.com/simonw/datasette/issues/2557#issuecomment-3470510837
This commit is contained in:
parent
5247856bd4
commit
6a71bde37f
14 changed files with 241 additions and 227 deletions
|
|
@ -1457,17 +1457,28 @@ permission_resources_sql(datasette, actor, action)
|
|||
The permission action being evaluated. Examples include ``"view-table"`` or ``"insert-row"``.
|
||||
|
||||
Return value
|
||||
A :class:`datasette.utils.permissions.PluginSQL` object, ``None`` or an iterable of ``PluginSQL`` objects.
|
||||
A :class:`datasette.permissions.PermissionSQL` object, ``None`` or an iterable of ``PermissionSQL`` objects.
|
||||
|
||||
Datasette's action-based permission resolver calls this hook to gather SQL rows describing which
|
||||
resources an actor may access (``allow = 1``) or should be denied (``allow = 0``) for a specific action.
|
||||
Each SQL snippet should return ``parent``, ``child``, ``allow`` and ``reason`` columns.
|
||||
|
||||
**Parameter naming convention:** Plugin parameters in ``PluginSQL.params`` should use unique names
|
||||
**Parameter naming convention:** Plugin parameters in ``PermissionSQL.params`` should use unique names
|
||||
to avoid conflicts with other plugins. The recommended convention is to prefix parameters with your
|
||||
plugin's source name (e.g., ``myplugin_user_id``). The system reserves these parameter names:
|
||||
``:actor``, ``:actor_id``, ``:action``, and ``:filter_parent``.
|
||||
|
||||
You can also use return ``PermissionSQL.allow(reason="reason goes here")`` or ``PermissionSQL.deny(reason="reason goes here")`` as shortcuts for simple root-level allow or deny rules. These will create SQL snippets that look like this:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
SELECT
|
||||
NULL AS parent,
|
||||
NULL AS child,
|
||||
1 AS allow,
|
||||
'reason goes here' AS reason
|
||||
|
||||
Or ``0 AS allow`` for denies.
|
||||
|
||||
Permission plugin examples
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
@ -1475,7 +1486,7 @@ Permission plugin examples
|
|||
These snippets show how to use the new ``permission_resources_sql`` hook to
|
||||
contribute rows to the action-based permission resolver. Each hook receives the
|
||||
current actor dictionary (or ``None``) and must return ``None`` or an instance or list of
|
||||
``datasette.utils.permissions.PluginSQL`` (or a coroutine that resolves to that).
|
||||
``datasette.permissions.PermissionSQL`` (or a coroutine that resolves to that).
|
||||
|
||||
Allow Alice to view a specific table
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -1486,7 +1497,7 @@ This plugin grants the actor with ``id == "alice"`` permission to perform the
|
|||
.. code-block:: python
|
||||
|
||||
from datasette import hookimpl
|
||||
from datasette.utils.permissions import PluginSQL
|
||||
from datasette.permissions import PermissionSQL
|
||||
|
||||
|
||||
@hookimpl
|
||||
|
|
@ -1496,8 +1507,7 @@ This plugin grants the actor with ``id == "alice"`` permission to perform the
|
|||
if not actor or actor.get("id") != "alice":
|
||||
return None
|
||||
|
||||
return PluginSQL(
|
||||
source="alice_sales_allow",
|
||||
return PermissionSQL(
|
||||
sql="""
|
||||
SELECT
|
||||
'accounting' AS parent,
|
||||
|
|
@ -1505,7 +1515,6 @@ This plugin grants the actor with ``id == "alice"`` permission to perform the
|
|||
1 AS allow,
|
||||
'alice can view accounting/sales' AS reason
|
||||
""",
|
||||
params={},
|
||||
)
|
||||
|
||||
Restrict execute-sql to a database prefix
|
||||
|
|
@ -1518,7 +1527,7 @@ will pass through to the SQL snippet.
|
|||
.. code-block:: python
|
||||
|
||||
from datasette import hookimpl
|
||||
from datasette.utils.permissions import PluginSQL
|
||||
from datasette.permissions import PermissionSQL
|
||||
|
||||
|
||||
@hookimpl
|
||||
|
|
@ -1526,8 +1535,7 @@ will pass through to the SQL snippet.
|
|||
if action != "execute-sql":
|
||||
return None
|
||||
|
||||
return PluginSQL(
|
||||
source="analytics_execute_sql",
|
||||
return PermissionSQL(
|
||||
sql="""
|
||||
SELECT
|
||||
parent,
|
||||
|
|
@ -1551,7 +1559,7 @@ with columns ``(actor_id, action, parent, child, allow, reason)``.
|
|||
.. code-block:: python
|
||||
|
||||
from datasette import hookimpl
|
||||
from datasette.utils.permissions import PluginSQL
|
||||
from datasette.permissions import PermissionSQL
|
||||
|
||||
|
||||
@hookimpl
|
||||
|
|
@ -1559,8 +1567,7 @@ with columns ``(actor_id, action, parent, child, allow, reason)``.
|
|||
if not actor:
|
||||
return None
|
||||
|
||||
return PluginSQL(
|
||||
source="permission_grants_table",
|
||||
return PermissionSQL(
|
||||
sql="""
|
||||
SELECT
|
||||
parent,
|
||||
|
|
@ -1586,7 +1593,7 @@ The resolver will automatically apply the most specific rule.
|
|||
.. code-block:: python
|
||||
|
||||
from datasette import hookimpl
|
||||
from datasette.utils.permissions import PluginSQL
|
||||
from datasette.permissions import PermissionSQL
|
||||
|
||||
|
||||
TRUSTED = {"alice", "bob"}
|
||||
|
|
@ -1600,17 +1607,14 @@ The resolver will automatically apply the most specific rule.
|
|||
actor_id = (actor or {}).get("id")
|
||||
|
||||
if actor_id not in TRUSTED:
|
||||
return PluginSQL(
|
||||
source="view_table_root_deny",
|
||||
return PermissionSQL(
|
||||
sql="""
|
||||
SELECT NULL AS parent, NULL AS child, 0 AS allow,
|
||||
'default deny view-table' AS reason
|
||||
""",
|
||||
params={},
|
||||
)
|
||||
|
||||
return PluginSQL(
|
||||
source="trusted_allow",
|
||||
return PermissionSQL(
|
||||
sql="""
|
||||
SELECT NULL AS parent, NULL AS child, 0 AS allow,
|
||||
'default deny view-table' AS reason
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue