mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
Move takes_child/takes_parent information from Action to Resource (#2567)
Simplified Action by moving takes_child/takes_parent logic to Resource - Removed InstanceResource - global actions are now simply those with resource_class=None - Resource.parent_class - Replaced parent_name: str with parent_class: type[Resource] | None for direct class references - Simplified Action dataclass - No more redundant fields, everything is derived from the Resource class structure - Validation - The __init_subclass__ method now checks parent_class.parent_class to enforce the 2-level hierarchy Closes #2563
This commit is contained in:
parent
1f8995e776
commit
5705ce0d95
10 changed files with 417 additions and 186 deletions
|
|
@ -883,24 +883,18 @@ Actions define what operations can be performed on resources (like viewing a tab
|
|||
name="list-documents",
|
||||
abbr="ld",
|
||||
description="List documents in a collection",
|
||||
takes_parent=True,
|
||||
takes_child=False,
|
||||
resource_class=DocumentCollectionResource,
|
||||
),
|
||||
Action(
|
||||
name="view-document",
|
||||
abbr="vdoc",
|
||||
description="View document",
|
||||
takes_parent=True,
|
||||
takes_child=True,
|
||||
resource_class=DocumentResource,
|
||||
),
|
||||
Action(
|
||||
name="edit-document",
|
||||
abbr="edoc",
|
||||
description="Edit document",
|
||||
takes_parent=True,
|
||||
takes_child=True,
|
||||
resource_class=DocumentResource,
|
||||
),
|
||||
]
|
||||
|
|
@ -916,26 +910,20 @@ The fields of the ``Action`` dataclass are as follows:
|
|||
``description`` - string or None
|
||||
A human-readable description of what the action allows you to do.
|
||||
|
||||
``takes_parent`` - boolean
|
||||
``True`` if this action requires a parent identifier (like a database name).
|
||||
|
||||
``takes_child`` - boolean
|
||||
``True`` if this action requires a child identifier (like a table or document name).
|
||||
|
||||
``resource_class`` - type[Resource]
|
||||
The Resource subclass that defines what kind of resource this action applies to. Your Resource subclass must:
|
||||
``resource_class`` - type[Resource] or None
|
||||
The Resource subclass that defines what kind of resource this action applies to. Omit this (or set to ``None``) for global actions that apply only at the instance level with no associated resources (like ``debug-menu`` or ``permissions-debug``). Your Resource subclass must:
|
||||
|
||||
- Define a ``name`` class attribute (e.g., ``"document"``)
|
||||
- Optionally define a ``parent_name`` class attribute (e.g., ``"collection"``)
|
||||
- Define a ``parent_class`` class attribute (``None`` for top-level resources like databases, or the parent ``Resource`` subclass for child resources)
|
||||
- Implement a ``resources_sql()`` classmethod that returns SQL returning all resources as ``(parent, child)`` columns
|
||||
- Have an ``__init__`` method that accepts appropriate parameters and calls ``super().__init__(parent=..., child=...)``
|
||||
|
||||
The ``resources_sql()`` method
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``resources_sql()`` classmethod is crucial to Datasette's permission system. It returns a SQL query that lists all resources of that type that exist in the system.
|
||||
The ``resources_sql()`` classmethod returns a SQL query that lists all resources of that type that exist in the system.
|
||||
|
||||
This SQL query is used by Datasette to efficiently check permissions across multiple resources at once. When a user requests a list of resources (like tables, documents, or other entities), Datasette uses this SQL to:
|
||||
This query is used by Datasette to efficiently check permissions across multiple resources at once. When a user requests a list of resources (like tables, documents, or other entities), Datasette uses this SQL to:
|
||||
|
||||
1. Get all resources of this type from your data catalog
|
||||
2. Combine it with permission rules from the ``permission_resources_sql`` hook
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ def register_permissions(datasette):
|
|||
),
|
||||
]
|
||||
```
|
||||
The new `Action` does not have a `default=` parameter, and `takes_database` and `takes_resource` have been renamed to `takes_parent` and `takes_child. The new code would look like this:
|
||||
The new `Action` does not have a `default=` parameter. For global actions (those that don't apply to specific resources), omit `resource_class`:
|
||||
|
||||
```python
|
||||
from datasette.permissions import Action
|
||||
|
|
@ -53,21 +53,41 @@ def register_actions(datasette):
|
|||
name="datasette-pins-write",
|
||||
abbr=None,
|
||||
description="Can pin, unpin, and re-order pins for datasette-pins",
|
||||
takes_parent=False,
|
||||
takes_child=False,
|
||||
default=False,
|
||||
),
|
||||
Action(
|
||||
name="datasette-pins-read",
|
||||
abbr=None,
|
||||
description="Can read pinned items.",
|
||||
takes_parent=False,
|
||||
takes_child=False,
|
||||
default=False,
|
||||
),
|
||||
]
|
||||
```
|
||||
|
||||
For actions that apply to specific resources (like databases or tables), specify the `resource_class` instead of `takes_parent` and `takes_child`:
|
||||
|
||||
```python
|
||||
from datasette.permissions import Action
|
||||
from datasette.resources import DatabaseResource, TableResource
|
||||
|
||||
@hookimpl
|
||||
def register_actions(datasette):
|
||||
return [
|
||||
Action(
|
||||
name="execute-sql",
|
||||
abbr="es",
|
||||
description="Execute SQL queries",
|
||||
resource_class=DatabaseResource, # Parent-level resource
|
||||
),
|
||||
Action(
|
||||
name="insert-row",
|
||||
abbr="ir",
|
||||
description="Insert rows",
|
||||
resource_class=TableResource, # Child-level resource
|
||||
),
|
||||
]
|
||||
```
|
||||
|
||||
The hierarchy information (whether an action takes parent/child parameters) is now derived from the `Resource` class hierarchy. `Action` has `takes_parent` and `takes_child` properties that are computed based on the `resource_class` and its `parent_class` attribute.
|
||||
|
||||
## permission_allowed() hook is replaced by permission_resources_sql()
|
||||
|
||||
The following old code:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue