mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
This introduces a new hierarchical permission system that uses SQL queries
for efficient permission checking across resources. The system replaces the
older permission_allowed() pattern with a more flexible resource-based
approach.
Core changes:
- New Resource ABC and Action dataclass in datasette/permissions.py
* Resources represent hierarchical entities (instance, database, table)
* Each resource type implements resources_sql() to list all instances
* Actions define operations on resources with cascading rules
- New plugin hook: register_actions(datasette)
* Plugins register actions with their associated resource types
* Replaces register_permissions() and register_resource_types()
* See docs/plugin_hooks.rst for full documentation
- Three new Datasette methods for permission checks:
* allowed_resources(action, actor) - returns list[Resource]
* allowed_resources_with_reasons(action, actor) - for debugging
* allowed(action, resource, actor) - checks single resource
* All use SQL for filtering, never Python iteration
- New /-/tables endpoint (TablesView)
* Returns JSON list of tables user can view
* Supports ?q= parameter for regex filtering
* Format: {"matches": [{"name": "db/table", "url": "/db/table"}]}
* Respects all permission rules from configuration and plugins
- SQL-based permission evaluation (datasette/utils/actions_sql.py)
* Cascading rules: child-level → parent-level → global-level
* DENY beats ALLOW at same specificity
* Uses CTEs for efficient SQL-only filtering
* Combines permission_resources_sql() hook results
- Default actions in datasette/default_actions.py
* InstanceResource, DatabaseResource, TableResource, QueryResource
* Core actions: view-instance, view-database, view-table, etc.
- Fixed default_permissions.py to handle database-level allow blocks
* Now creates parent-level rules for view-table action
* Fixes: datasette ... -s databases.fixtures.allow.id root
Documentation:
- Comprehensive register_actions() hook documentation
- Detailed resources_sql() method explanation
- /-/tables endpoint documentation in docs/introspection.rst
- Deprecated register_permissions() with migration guide
Tests:
- tests/test_actions_sql.py: 7 tests for core permission API
- tests/test_tables_endpoint.py: 13 tests for /-/tables endpoint
- All 118 documentation tests pass
- Tests verify SQL does filtering (not Python)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
241 lines
6.6 KiB
ReStructuredText
241 lines
6.6 KiB
ReStructuredText
.. _introspection:
|
|
|
|
Introspection
|
|
=============
|
|
|
|
Datasette includes some pages and JSON API endpoints for introspecting the current instance. These can be used to understand some of the internals of Datasette and to see how a particular instance has been configured.
|
|
|
|
Each of these pages can be viewed in your browser. Add ``.json`` to the URL to get back the contents as JSON.
|
|
|
|
.. _JsonDataView_metadata:
|
|
|
|
/-/metadata
|
|
-----------
|
|
|
|
Shows the contents of the ``metadata.json`` file that was passed to ``datasette serve``, if any. `Metadata example <https://fivethirtyeight.datasettes.com/-/metadata>`_:
|
|
|
|
.. code-block:: json
|
|
|
|
{
|
|
"license": "CC Attribution 4.0 License",
|
|
"license_url": "http://creativecommons.org/licenses/by/4.0/",
|
|
"source": "fivethirtyeight/data on GitHub",
|
|
"source_url": "https://github.com/fivethirtyeight/data",
|
|
"title": "Five Thirty Eight",
|
|
"databases": {
|
|
|
|
}
|
|
}
|
|
|
|
.. _JsonDataView_versions:
|
|
|
|
/-/versions
|
|
-----------
|
|
|
|
Shows the version of Datasette, Python and SQLite. `Versions example <https://latest.datasette.io/-/versions>`_:
|
|
|
|
.. code-block:: json
|
|
|
|
{
|
|
"datasette": {
|
|
"version": "0.60"
|
|
},
|
|
"python": {
|
|
"full": "3.8.12 (default, Dec 21 2021, 10:45:09) \n[GCC 10.2.1 20210110]",
|
|
"version": "3.8.12"
|
|
},
|
|
"sqlite": {
|
|
"extensions": {
|
|
"json1": null
|
|
},
|
|
"fts_versions": [
|
|
"FTS5",
|
|
"FTS4",
|
|
"FTS3"
|
|
],
|
|
"compile_options": [
|
|
"COMPILER=gcc-6.3.0 20170516",
|
|
"ENABLE_FTS3",
|
|
"ENABLE_FTS4",
|
|
"ENABLE_FTS5",
|
|
"ENABLE_JSON1",
|
|
"ENABLE_RTREE",
|
|
"THREADSAFE=1"
|
|
],
|
|
"version": "3.37.0"
|
|
}
|
|
}
|
|
|
|
.. _JsonDataView_plugins:
|
|
|
|
/-/plugins
|
|
----------
|
|
|
|
Shows a list of currently installed plugins and their versions. `Plugins example <https://san-francisco.datasettes.com/-/plugins>`_:
|
|
|
|
.. code-block:: json
|
|
|
|
[
|
|
{
|
|
"name": "datasette_cluster_map",
|
|
"static": true,
|
|
"templates": false,
|
|
"version": "0.10",
|
|
"hooks": ["extra_css_urls", "extra_js_urls", "extra_body_script"]
|
|
}
|
|
]
|
|
|
|
Add ``?all=1`` to include details of the default plugins baked into Datasette.
|
|
|
|
.. _JsonDataView_settings:
|
|
|
|
/-/settings
|
|
-----------
|
|
|
|
Shows the :ref:`settings` for this instance of Datasette. `Settings example <https://fivethirtyeight.datasettes.com/-/settings>`_:
|
|
|
|
.. code-block:: json
|
|
|
|
{
|
|
"default_facet_size": 30,
|
|
"default_page_size": 100,
|
|
"facet_suggest_time_limit_ms": 50,
|
|
"facet_time_limit_ms": 1000,
|
|
"max_returned_rows": 1000,
|
|
"sql_time_limit_ms": 1000
|
|
}
|
|
|
|
.. _JsonDataView_config:
|
|
|
|
/-/config
|
|
---------
|
|
|
|
Shows the :ref:`configuration <configuration>` for this instance of Datasette. This is generally the contents of the :ref:`datasette.yaml or datasette.json <configuration_reference>` file, which can include plugin configuration as well. `Config example <https://latest.datasette.io/-/config>`_:
|
|
|
|
.. code-block:: json
|
|
|
|
{
|
|
"settings": {
|
|
"template_debug": true,
|
|
"trace_debug": true,
|
|
"force_https_urls": true
|
|
}
|
|
}
|
|
|
|
Any keys that include the one of the following substrings in their names will be returned as redacted ``***`` output, to help avoid accidentally leaking private configuration information: ``secret``, ``key``, ``password``, ``token``, ``hash``, ``dsn``.
|
|
|
|
.. _JsonDataView_databases:
|
|
|
|
/-/databases
|
|
------------
|
|
|
|
Shows currently attached databases. `Databases example <https://latest.datasette.io/-/databases>`_:
|
|
|
|
.. code-block:: json
|
|
|
|
[
|
|
{
|
|
"hash": null,
|
|
"is_memory": false,
|
|
"is_mutable": true,
|
|
"name": "fixtures",
|
|
"path": "fixtures.db",
|
|
"size": 225280
|
|
}
|
|
]
|
|
|
|
.. _TablesView:
|
|
|
|
/-/tables
|
|
---------
|
|
|
|
Returns a JSON list of all tables that the current actor has permission to view. This endpoint uses the resource-based permission system and respects database and table-level access controls.
|
|
|
|
The endpoint supports a ``?q=`` query parameter for filtering tables by name using case-insensitive regex matching.
|
|
|
|
`Tables example <https://latest.datasette.io/-/tables>`_:
|
|
|
|
.. code-block:: json
|
|
|
|
{
|
|
"matches": [
|
|
{
|
|
"name": "fixtures/facetable",
|
|
"url": "/fixtures/facetable"
|
|
},
|
|
{
|
|
"name": "fixtures/searchable",
|
|
"url": "/fixtures/searchable"
|
|
}
|
|
]
|
|
}
|
|
|
|
Search example with ``?q=facet`` returns only tables matching ``.*facet.*``:
|
|
|
|
.. code-block:: json
|
|
|
|
{
|
|
"matches": [
|
|
{
|
|
"name": "fixtures/facetable",
|
|
"url": "/fixtures/facetable"
|
|
}
|
|
]
|
|
}
|
|
|
|
When multiple search terms are provided (e.g., ``?q=user+profile``), tables must match the pattern ``.*user.*profile.*``. Results are ordered by shortest table name first.
|
|
|
|
.. _JsonDataView_threads:
|
|
|
|
/-/threads
|
|
----------
|
|
|
|
Shows details of threads and ``asyncio`` tasks. `Threads example <https://latest.datasette.io/-/threads>`_:
|
|
|
|
.. code-block:: json
|
|
|
|
{
|
|
"num_threads": 2,
|
|
"threads": [
|
|
{
|
|
"daemon": false,
|
|
"ident": 4759197120,
|
|
"name": "MainThread"
|
|
},
|
|
{
|
|
"daemon": true,
|
|
"ident": 123145319682048,
|
|
"name": "Thread-1"
|
|
},
|
|
],
|
|
"num_tasks": 3,
|
|
"tasks": [
|
|
"<Task pending coro=<RequestResponseCycle.run_asgi() running at uvicorn/protocols/http/httptools_impl.py:385> cb=[set.discard()]>",
|
|
"<Task pending coro=<Server.serve() running at uvicorn/main.py:361> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x10365c3d0>()]> cb=[run_until_complete.<locals>.<lambda>()]>",
|
|
"<Task pending coro=<LifespanOn.main() running at uvicorn/lifespan/on.py:48> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x10364f050>()]>>"
|
|
]
|
|
}
|
|
|
|
.. _JsonDataView_actor:
|
|
|
|
/-/actor
|
|
--------
|
|
|
|
Shows the currently authenticated actor. Useful for debugging Datasette authentication plugins.
|
|
|
|
.. code-block:: json
|
|
|
|
{
|
|
"actor": {
|
|
"id": 1,
|
|
"username": "some-user"
|
|
}
|
|
}
|
|
|
|
|
|
.. _MessagesDebugView:
|
|
|
|
/-/messages
|
|
-----------
|
|
|
|
The debug tool at ``/-/messages`` can be used to set flash messages to try out that feature. See :ref:`datasette_add_message` for details of this feature.
|