Add datasette.ensure_permission() method, refs #2525, refs #2528

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.
This commit is contained in:
Simon Willison 2025-10-25 09:28:33 -07:00
commit fabcfd68ad
5 changed files with 74 additions and 45 deletions

View file

@ -1310,6 +1310,39 @@ class Datasette:
return result
async def ensure_permission(
self,
*,
action: str,
resource: "Resource" = None,
actor: dict | None = None,
):
"""
Check if actor can perform action on resource, raising Forbidden if not.
This is a convenience wrapper around allowed() that raises Forbidden
instead of returning False. Use this when you want to enforce a permission
check and halt execution if it fails.
Example:
from datasette.resources import TableResource
# Will raise Forbidden if actor cannot view the table
await datasette.ensure_permission(
action="view-table",
resource=TableResource(database="analytics", table="users"),
actor=request.actor
)
# For instance-level actions, resource can be omitted:
await datasette.ensure_permission(
action="permissions-debug",
actor=request.actor
)
"""
if not await self.allowed(action=action, resource=resource, actor=actor):
raise Forbidden(action)
async def execute(
self,
db_name,