Commit graph

126 commits

Author SHA1 Message Date
Simon Willison
faef51ad05 Document datasette.allowed(), PermissionSQL class, and SQL parameters
- Added documentation for datasette.allowed() method with keyword-only arguments
- Added comprehensive PermissionSQL class documentation with examples
- Documented the three SQL parameters available: :actor, :actor_id, :action
- Included examples of using json_extract() to access actor fields
- Explained permission resolution rules (specificity, deny over allow, implicit deny)
- Fixed RST formatting warnings (escaped asterisk, fixed underline length)
2025-10-23 12:42:10 -07:00
Simon Willison
7db754c284 Implement resource-based permission system with SQL-driven access control
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>
2025-10-20 16:00:36 -07:00
Simon Willison
27084caa04
New allowed_resources_sql plugin hook and debug tools (#2505)
* allowed_resources_sql plugin hook and infrastructure
* New methods for checking permissions with the new system
* New /-/allowed and /-/check and /-/rules special endpoints

Still needs to be integrated more deeply into Datasette, especially for listing visible tables.

Refs: #2502

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-08 14:27:51 -07:00
Simon Willison
d021ce97aa
Note that only first actor_from_request value is respected
https://github.com/datasette/datasette-profiles/issues/4#issuecomment-2758588167
2025-03-27 09:09:57 -07:00
Simon Willison
209bdee0e8 Don't run prepare_connection() on internal database, closes #2468 2025-02-18 10:23:23 -08:00
Simon Willison
cd9182a551 Release 1.0a17
Refs #1690, #1943, #2422, #2424, #2441, #2454, #2455, #2458, #2460, #2465
2025-02-06 11:12:34 -08:00
Simon Willison
e85517dab3 blacken-docs, refs #2441 2024-11-15 13:34:45 -08:00
Simon Willison
dce718961c Async support for magic parameters
Closes #2441
2024-11-15 13:17:45 -08:00
Simon Willison
8dc9bfa2ab Markup tweak for track_event docs 2024-08-05 12:58:10 -07:00
Simon Willison
bd7d3bb70f Tweaks and improvements to upgrade guide, refs ##2374
Also refs #2381
2024-08-05 12:11:17 -07:00
Alex Garcia
e1bfab3fca
Move Metadata to --internal database
Refs:
- https://github.com/simonw/datasette/pull/2343
- https://github.com/simonw/datasette/issues/2341
2024-06-11 09:33:23 -07:00
Simon Willison
7d6d471dc5 Include actor in track_event async example, refs #2319 2024-04-11 18:53:07 -07:00
Simon Willison
2a08ffed5c
Async example for track_event hook
Closes #2319
2024-04-11 18:47:01 -07:00
Simon Willison
63714cb2b7 Fixed some typos spotted by Gemini Pro 1.5, closes #2318 2024-04-10 17:05:15 -07:00
Simon Willison
da68662767
datasette-enrichments is example of row_actions
Refs:
- https://github.com/simonw/datasette/issues/2299
- https://github.com/datasette/datasette-enrichments/issues/41
2024-03-17 14:40:47 -07:00
Simon Willison
828ef9899f Ran blacken-docs, refs #2299 2024-03-12 16:25:25 -07:00
Simon Willison
8d456aae45 Fix spelling of displayed, refs #2299 2024-03-12 16:17:53 -07:00
Simon Willison
b8711988b9 row_actions() plugin hook, closes #2299 2024-03-12 16:16:05 -07:00
Simon Willison
7339cc51de Rearrange plugin hooks page with more sections, closes #2300 2024-03-12 15:44:10 -07:00
Simon Willison
909c85cd2b view_actions plugin hook, closes #2297 2024-03-12 14:25:28 -07:00
Simon Willison
daf5ca02ca homepage_actions() plugin hook, closes #2298 2024-03-12 13:46:06 -07:00
Simon Willison
7b32d5f7d8 datasette-create-view as example of query_actions hook 2024-03-07 00:11:14 -05:00
Simon Willison
090dff542b
Action menu descriptions
* Refactor tests to extract get_actions_links() helper
* Table, database and query action menu items now support optional descriptions

Closes #2294
2024-03-06 22:54:06 -05:00
Simon Willison
4d24bf6b34 Don't explain an explain even in the demo, refs #2293 2024-03-05 18:14:55 -08:00
Simon Willison
5de6797d4a Better demo plugin for query_actions, refs #2293 2024-03-05 18:06:38 -08:00
Simon Willison
6ec0081f5d
query_actions plugin hook
* New query_actions plugin hook, closes #2283
2024-02-27 21:55:16 -08:00
Simon Willison
5d79974186
Call them "notable events" 2024-02-10 07:19:47 -08:00
Simon Willison
dcd9ea3622
datasette-events-db as an example of track_events() 2024-02-08 14:14:58 -08:00
Simon Willison
6ccef35cc9 More links between events documentation 2024-02-01 15:42:45 -08:00
Simon Willison
b466749e88 Filled out docs/configuration.rst, closes #2246 2024-01-31 20:03:19 -08:00
Simon Willison
bcc4f6bf1f
track_event() mechanism for analytics and plugins
* Closes #2240
* Documentation for event plugin hooks, refs #2240
* Include example track_event plugin in docs, refs #2240
* Tests for track_event() and register_events() hooks, refs #2240
* Initial documentation for core events, refs #2240
* Internals documentation for datasette.track_event()
2024-01-31 15:21:40 -08:00
Simon Willison
959e020297 Ran blacken-docs 2024-01-30 20:40:18 -08:00
Simon Willison
c3caf36af7
Template slot family of plugin hooks - top_homepage() and others
New plugin hooks:

top_homepage
top_database
top_table
top_row
top_query
top_canned_query

New datasette.utils.make_slot_function()

Closes #1191
2024-01-30 19:54:03 -08:00
Simon Willison
48148e66a8 Link from actors_from_ids plugin hook docs to datasette.actors_from_ids() 2024-01-10 10:42:36 -08:00
Simon Willison
c7a4706bcc
jinja2_environment_from_request() plugin hook
Closes #2225
2024-01-05 14:33:23 -08:00
Simon Willison
85a41987c7 Fixed typo acepts -> accepts 2023-10-08 09:07:11 -07:00
Alex Garcia
b2ec8717c3
Plugin configuration now lives in datasette.yaml/json
* Checkpoint, moving top-level plugin config to datasette.json
* Support database-level and table-level plugin configuration in datasette.yaml

Refs #2093
2023-09-13 14:06:25 -07:00
Simon Willison
b645174271
actors_from_ids plugin hook and datasette.actors_from_ids() method (#2181)
* Prototype of actors_from_ids plugin hook, refs #2180
* datasette-remote-actors example plugin, refs #2180
2023-09-07 21:23:59 -07:00
Simon Willison
ab040470e2 Applied blacken-docs 2023-09-07 15:57:27 -07:00
Simon Willison
fbcb103c0c Added example code to database_actions hook documentation 2023-09-07 07:47:24 -07:00
Simon Willison
50da908213
Cascade for restricted token view-table/view-database/view-instance operations (#2154)
Closes #2102

* Permission is now a dataclass, not a namedtuple - refs https://github.com/simonw/datasette/pull/2154/#discussion_r1308087800
* datasette.get_permission() method
2023-08-29 09:32:34 -07:00
Simon Willison
943df09dcc Remove all remaining "$ " prefixes from docs, closes #2140
Also document sqlite-utils create-view
2023-08-11 10:44:34 -07:00
Simon Willison
1377a290cd
New JSON design for query views (#2118)
* Refs #2111, closes #2110
* New Context dataclass/subclass mechanism, refs #2127
* Define QueryContext and extract get_tables() method, refs #2127
* Fix OPTIONS bug by porting DaatbaseView to be a View subclass
* Expose async_view_for_class.view_class for test_routes test
* Error/truncated aruments for renderers, closes #2130
2023-08-07 18:47:39 -07:00
Simon Willison
d1d78ec0eb
Better docs for startup() hook 2023-06-23 13:06:35 -07:00
Simon Willison
0b4a286914 render_cell(..., request) argument, closes #2007 2023-01-27 19:34:14 -08:00
Simon Willison
6a352e99ab
Added missing import to example 2023-01-11 11:04:11 -08:00
Simon Willison
deb5fcbed4
Fixed table_action example in docs 2023-01-04 10:25:04 -08:00
Simon Willison
63fb750f39 Replace AsgiLifespan with AsgiRunOnFirstRequest, refs #1955 2022-12-17 14:14:34 -08:00
Simon Willison
0b68996cc5 Revert "Replace AsgiLifespan with AsgiRunOnFirstRequest, refs #1955"
This reverts commit dc18f62089.
2022-12-15 13:06:45 -08:00
Simon Willison
dc18f62089 Replace AsgiLifespan with AsgiRunOnFirstRequest, refs #1955 2022-12-15 09:34:07 -08:00