Commit graph

2,728 commits

Author SHA1 Message Date
Simon Willison
4b50cc7bc1 Use allowed_resources_sql() with CTE for table filtering 2025-10-23 15:34:36 -07:00
Simon Willison
c4f0365130 Rewrite tables endpoint to use SQL LIKE instead of Python regex 2025-10-23 15:29:51 -07:00
Simon Willison
19a37303c7 Fix /-/tables endpoint: add .json support and correct response format 2025-10-23 15:28:37 -07:00
Simon Willison
8de5b9431c Fix test_tables_endpoint_config_database_allow by using unique database names 2025-10-23 15:26:14 -07:00
Simon Willison
275c06fbe4 Add register_actions hook to test plugin and improve test 2025-10-23 15:24:10 -07:00
Simon Willison
d4dd08933e Fix test_navigation_menu_links by enabling root_enabled for root actor 2025-10-23 15:20:16 -07:00
Simon Willison
28a69d19a2 permission_allowed_default_allow_sql 2025-10-23 15:17:29 -07:00
Simon Willison
8bb07f80b1 Applied Black 2025-10-23 15:08:34 -07:00
Simon Willison
4d93149c2b 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-23 14:53:07 -07:00
Simon Willison
475f817c5a Fixed some more tests 2025-10-23 14:43:51 -07:00
Simon Willison
2039e238d9 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-23 14:34:48 -07:00
Simon Willison
e42b040055 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-23 14:23:46 -07:00
Simon Willison
f4245dce66 Eliminate duplicate config checking by removing old permission_allowed hooks
- Removed permission_allowed_default() hook (checked config twice)
- Removed _resolve_config_view_permissions() and _resolve_config_permissions_blocks() helpers
- Added permission_allowed_sql_bridge() to bridge old permission_allowed() API to new SQL system
- Moved default_allow_sql setting check into permission_resources_sql()
- Made root-level allow blocks apply to all view-* actions (view-database, view-table, view-query)
- Added add_row_allow_block() helper for allow blocks that should deny when no match

This resolves the duplicate checking issue where config blocks were evaluated twice:
once in permission_allowed hooks and once in permission_resources_sql hooks.

Note: One test still failing (test_permissions_checked for database download) - needs investigation
2025-10-23 13:53:01 -07:00
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
5fc58c8775 New --root mechanism with datasette.root_enabled, closes #2521 2025-10-23 12:40:50 -07:00
Simon Willison
1d37d30c2a 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-23 09:48:55 -07:00
Simon Willison
5ed57607e5 PluginSQL renamed to PermissionSQL, closes #2524 2025-10-23 09:34:19 -07:00
Simon Willison
cf887e0277 ds.allowed() is now keyword-argument only, closes #2519 2025-10-23 09:25:33 -07:00
Simon Willison
7dfd14bb07 Update allowed_resources_sql() and refactor allowed_resources() 2025-10-20 16:26:54 -07:00
Simon Willison
3663b9df2d Moved Resource defaults to datasette/resources.py 2025-10-20 16:23:14 -07:00
Simon Willison
9e5c64c3de Ran prettier 2025-10-20 16:03:22 -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
ec38ad3768
Add DatabaseContext dataclass for consistent template context documentation (#2513)
Refs:
- #1510
- #2333

Claude Code:

Created DatabaseContext as a documented dataclass following the same pattern
as the existing QueryContext. This change replaces the inline dictionary
context creation with an explicit dataclass that:

- Documents all 21 template context variables with help metadata
- Inherits from the Context base class for identification
- Provides better IDE support and type safety
- Makes template variables discoverable without reading code

Also updated QueryContext to inherit from Context for consistency.
2025-10-09 12:54:02 -07:00
Simon Willison
659673614a Refactor debug templates to use shared JavaScript functions
Extracted common JavaScript utilities from debug_allowed.html, debug_check.html, and debug_rules.html into a new _debug_common_functions.html include template. This eliminates code duplication and improves maintainability.

The shared functions include:
- populateFormFromURL(): Populates form fields from URL query parameters
- updateURL(formId, page): Updates browser URL with form values
- escapeHtml(text): HTML escaping utility

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-08 21:53:34 -07:00
Simon Willison
e2a739c496 Fix for asyncio.iscoroutinefunction deprecation warnings
Closes #2512

Refs https://github.com/simonw/asyncinject/issues/18
2025-10-08 20:32:16 -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
85da8474d4
Python 3.14, drop Python 3.9
Closes #2506
2025-10-08 13:11:32 -07:00
Simon Willison
909448fb7a Run CLI coroutines on explicit event loops
With the help of Codex CLI: https://gist.github.com/simonw/d2de93bfdf85a014a29093720c511093
2025-10-01 12:59:14 -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
9dc2a3ffe5 Removed broken refs to Glitch, closes #2503 2025-09-28 21:15:58 -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
Simon Willison
e2497fdb59 Replace Glitch with Codespaces, closes #2488 2025-05-28 19:17:22 -07:00
Simon Willison
1c77a7e33f Fix global-power-points references
Refs https://github.com/simonw/datasette.io/issues/167
2025-05-28 19:07:46 -07:00
Simon Willison
6f7f4c7d89 Release 1.0a19 1.0a19
Refs #2479
2025-04-21 22:38:53 -07:00
Simon Willison
f4274e7a2e CSS fix for table headings on mobile, closes #2479 2025-04-21 22:33:34 -07:00
Simon Willison
271aa09056 Release 1.0a18 1.0a18
Refs #2466, #2468, #2470, #2476, #2477
2025-04-16 22:16:25 -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
f6446b3095 Further wording tweaks 2025-04-16 08:25:03 -07:00
Simon Willison
d03273e205
Wording tweak 2025-04-16 08:19:22 -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
7945f4fbf2 Improved docs for db.get_all_foreign_keys() 2025-03-12 15:42:11 -07:00
dependabot[bot]
da209ed2ba
Drop 3.8 testing, add 3.13 testing, upgrade Black
Also bump some GitHub Actions versions.
2025-03-09 20:45:18 -07:00
Simon Willison
333f786cb0 Correct syntax for link headers, closes #2470 2025-03-09 20:05:43 -05:00
Simon Willison
6e512caa59 Upgrade to actions/cache@v4
v2 no longer works.
2025-02-28 22:57:22 -08: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
cd9182a551 Release 1.0a17 1.0a17
Refs #1690, #1943, #2422, #2424, #2441, #2454, #2455, #2458, #2460, #2465
2025-02-06 11:12:34 -08:00