Added test_rst_heading_underlines_match_title_length() to verify that RST
heading underlines match their title lengths. The test properly handles:
- Overline+underline style headings (skips validation for those)
- Empty lines before underlines (ignores them)
- Minimum 5-character underline length (avoids false positives)
Running this test identified 14 heading underline mismatches which have
been fixed across 5 documentation files:
- docs/authentication.rst (3 headings)
- docs/plugin_hooks.rst (4 headings)
- docs/internals.rst (5 headings)
- docs/deploying.rst (1 heading)
- docs/changelog.rst (1 heading)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated check_visibility() method signature to accept Resource objects
(DatabaseResource, TableResource, QueryResource) instead of plain strings
and tuples.
Changes:
- Updated check_visibility() signature to only accept Resource objects
- Added validation with helpful error message for incorrect types
- Updated all check_visibility() calls throughout the codebase:
- datasette/views/database.py: Use DatabaseResource and QueryResource
- datasette/views/special.py: Use DatabaseResource and TableResource
- datasette/views/row.py: Use TableResource
- datasette/views/table.py: Use TableResource
- datasette/app.py: Use TableResource in expand_foreign_keys
- Updated tests to use Resource objects
- Updated documentation in docs/internals.rst:
- Removed outdated permissions parameter
- Updated examples to use Resource objects
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements a new ensure_permission() method that is a convenience wrapper
around allowed() that raises Forbidden instead of returning False.
Changes:
- Added ensure_permission() method to datasette/app.py
- Updated all views to use ensure_permission() instead of the pattern:
if not await self.ds.allowed(...): raise Forbidden(...)
- Updated docs/internals.rst to document the new method
- Removed old ensure_permissions() documentation (that method was already removed)
The new method simplifies permission enforcement in views and makes the
code more concise and consistent.
- 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)
* Checkpoint, moving top-level plugin config to datasette.json
* Support database-level and table-level plugin configuration in datasette.yaml
Refs #2093
* Docs for permissions: in metadata, refs #1636
* Refactor default_permissions.py to help with implementation of #1636
* register_permissions() plugin hook, closes#1939 - also refs #1938
* Tests for register_permissions() hook, refs #1939
* Documentation for datasette.permissions, refs #1939
* permission_allowed() falls back on Permission.default, refs #1939
* Raise StartupError on duplicate permissions
* Allow dupe permisisons if exact matches