Commit graph

1,032 commits

Author SHA1 Message Date
Simon Willison
7d04211559 Fix test_tables_endpoint_config_database_allow by using unique database names 2025-10-24 10:32:18 -07:00
Simon Willison
d73b6f169f Add register_actions hook to test plugin and improve test 2025-10-24 10:32:18 -07:00
Simon Willison
130dad268d Fix test_navigation_menu_links by enabling root_enabled for root actor 2025-10-24 10:32:18 -07:00
Simon Willison
06af34240f Fix permission endpoint tests by resolving method signature conflicts
- Renamed internal allowed_resources_sql() to _build_permission_rules_sql()
  to avoid conflict with public method
- Made public allowed_resources_sql() keyword-only to prevent argument order bugs
- Fixed PermissionRulesView to use _build_permission_rules_sql() which returns
  full permission rules (with allow/deny) instead of filtered resources
- Fixed _build_permission_rules_sql() to pass actor dict to build_rules_union()
- Added actor_id extraction in AllowedResourcesView
- Added root_enabled=True to test fixture to grant permissions-debug to root user

All 51 tests in test_permission_endpoints.py now pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 10:32:18 -07:00
Simon Willison
7423c1a999 Fixed some more tests 2025-10-24 10:32:18 -07:00
Simon Willison
98493b7587 Fix permission_allowed_sql_bridge to not apply defaults, closes #2526
The bridge was incorrectly using the new allowed() method which applies
default allow rules. This caused actors without restrictions to get True
instead of USE_DEFAULT, breaking backward compatibility.

Fixed by:
- Removing the code that converted to resource objects and called allowed()
- Bridge now ONLY checks config-based rules via _config_permission_rules()
- Returns None when no config rules exist, allowing Permission.default to apply
- This maintains backward compatibility with the permission_allowed() API

All 177 permission tests now pass, including test_actor_restricted_permissions
and test_permissions_checked which were previously failing.
2025-10-24 10:32:18 -07:00
Simon Willison
8b5bf3e487 Mark test_permissions_checked database download test as xfail, refs #2526
The test expects ensure_permissions() to check all three permissions
(view-database-download, view-database, view-instance) but the current
implementation short-circuits after the first successful check.

Created issue #2526 to track the investigation of the expected behavior.
2025-10-24 10:32:18 -07:00
Simon Willison
c06e05b7db New --root mechanism with datasette.root_enabled, closes #2521 2025-10-24 10:32:18 -07:00
Simon Willison
65c427e4ee Ensure :actor, :actor_id and :action are all available to permissions SQL, closes #2520
- Updated build_rules_union() to accept actor as dict and provide :actor (JSON) and :actor_id
- Updated resolve_permissions_from_catalog() and resolve_permissions_with_candidates() to accept actor dict
- :actor is now the full actor dict as JSON (use json_extract() to access fields)
- :actor_id is the actor's id field for simple comparisons
- :action continues to be available as before
- Updated all call sites and tests to use new parameter format
- Added test demonstrating all three parameters working together
2025-10-24 10:32:18 -07:00
Simon Willison
b9c6e7a0f6 PluginSQL renamed to PermissionSQL, closes #2524 2025-10-24 10:32:18 -07:00
Simon Willison
159b9f3fec ds.allowed() is now keyword-argument only, closes #2519 2025-10-24 10:32:18 -07:00
Simon Willison
b1080e7d30 Moved Resource defaults to datasette/resources.py 2025-10-24 10:32:18 -07:00
Simon Willison
2b879e462f 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-24 10:32:18 -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
5d09ab3ff1 Remove legacy event_loop fixture usage 2025-10-01 12:51:23 -07:00
Simon Willison
571ce651c1 Use venv Python to launch datasette fixtures 2025-10-01 12:49:09 -07:00
Simon Willison
d87bd12dbc Remove obsolete mix_stderr=False 2025-09-30 14:33:24 -07:00
Simon Willison
7a602140df catalog_views table, closes #2495
Refs https://github.com/datasette/datasette-queries/issues/1#issuecomment-3074491003
2025-07-15 10:22:56 -07:00
Jack Stratton
d5c6e502fb
fix: tilde encode database name in expanded foreign key links (#2476)
* Tilde encode database for expanded foreign key links
* Test for foreign key fix in #2476

---------

Co-authored-by: Simon Willison <swillison@gmail.com>
2025-04-16 22:15:11 -07:00
Simon Willison
f2485dce9c
Hide FTS tables that have content=
* Hide FTS tables that have content=, closes #2477
2025-04-16 21:44:09 -07:00
Simon Willison
333f786cb0 Correct syntax for link headers, closes #2470 2025-03-09 20:05:43 -05:00
Simon Willison
209bdee0e8 Don't run prepare_connection() on internal database, closes #2468 2025-02-18 10:23:23 -08:00
Simon Willison
e59fd01757 Fix for incorrect REFERENCES in internal DB
Refs #2466
2025-02-12 19:40:43 -08:00
Simon Willison
f95ac19e71 Fix to support replacing a database, closes #2465 2025-02-06 10:32:47 -08:00
Simon Willison
53a3b3c80e
Test improvements and fixed deprecation warnings (#2464)
* `asyncio_default_fixture_loop_scope = function`
* Fix a bunch of BeautifulSoup deprecation warnings
* Fix for PytestUnraisableExceptionWarning: Exception ignored in: <_io.FileIO [closed]>
* xfail for sql_time_limit tests (these can be flaky in CI)

Refs #2461
2025-02-04 14:49:52 -08:00
Simon Willison
962da77d61
Try the event_loop fixture (#2463)
Refs https://github.com/simonw/datasette/issues/2461#issuecomment-2634920351
2025-02-04 11:56:19 -08:00
Simon Willison
9e41d19f73 pytest.mark.serial on CLI tests, refs #2461 2025-02-04 11:28:16 -08:00
Simon Willison
f57977a08f /-/permissions?filter=exclude-yours/only-yours - closes #2460 2025-02-04 11:09:44 -08:00
Simon Willison
4dff846271 simple_primary_key now uses integer id, helps close #2458 2025-02-01 21:44:53 -08:00
Simon Willison
b190b87ec6 Detect single unique text column in label_column_for_table, closes #2458
Also added new tests for label_column_for_table()
2025-02-01 17:02:49 -08:00
Simon Willison
308c243cfd datasette.set_actor_cookie() and datasette.delete_actor_cookie(), closes #1690 2025-01-15 17:37:25 -08:00
Simon Willison
37873e02b0 Better breadcrumbs on database and table page, closes #2454 2025-01-09 10:07:03 -08:00
Simon Willison
dce718961c Async support for magic parameters
Closes #2441
2024-11-15 13:17:45 -08:00
Simon Willison
2170269258
New .core CSS class for inputs and buttons
* Initial .core input/button classes, refs #2415
* Docs for the new .core CSS class, refs #2415
* Applied .core class everywhere that needs it, closes #2415
2024-09-03 08:37:26 -07:00
Simon Willison
92c4d41ca6 results.dicts() method, closes #2414 2024-09-01 17:20:41 -07:00
Simon Willison
f28ff8e4f0 Consider just 1000 rows for suggest facet, closes #2406 2024-08-21 13:36:42 -07:00
Simon Willison
8a63cdccc7 Tracer now catches errors, closes #2405 2024-08-21 12:19:18 -07:00
Simon Willison
34a6b2ac84 Fixed bug with ?_trace=1 and large responses, closes #2404 2024-08-21 10:58:17 -07:00
Simon Willison
9028d7f805 Support nested JSON in metadata.json, closes #2403 2024-08-21 09:53:52 -07:00
Simon Willison
39dfc7d7d7
Removed units functionality and Pint dependency
Closes #2400, unblocks #2320
2024-08-20 19:03:33 -07:00
Alex Garcia
0dd41efce6
skip over "queries" blocks when processing database-level metadata items (#2386) 2024-08-15 21:48:07 -07:00
Simon Willison
53a8ae1871 Applied Black, refs #2327, #2326 2024-08-15 17:16:47 -07:00
Seb Bacon
9cb5700d60
bugfix: correctly detect json1 in versions.json (#2327)
Fixes #2326
2024-08-15 13:20:26 -07:00
Alex Garcia
6d91d082e0
Hide shadow tables, don't hide virtual tables
Closes #2296
2024-08-15 13:19:22 -07:00
Simon Willison
05dfd34fd0 Use text/html for CSRF error page, refs #2390 2024-08-15 08:48:47 -07:00
Simon Willison
492378c2a0 Test for application/json; charset=utf-8
Refs #2384, #2392
2024-08-14 21:37:40 -07:00
Simon Willison
06d4ffb92e Custom error on CSRF failures, closes #2390
Uses https://github.com/simonw/asgi-csrf/issues/28
2024-08-14 21:29:16 -07:00
Simon Willison
93067668fe /-/ alternative URL for homepage, closes #2393 2024-08-14 17:57:13 -07:00
Simon Willison
bf953628bb Fix bug where -s could reset settings to defaults, closes #2389 2024-08-14 14:28:48 -07:00
Simon Willison
81b68a143a /-/auth-token as root redirects to /, closes #2375 2024-07-26 14:09:20 -07:00