mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
Add PermissionCheck dataclass with parent/child fields, refs #2528
Instead of logging permission checks as dicts with a 'resource' key, use a typed dataclass with separate parent and child fields. Changes: - Created PermissionCheck dataclass in app.py - Updated permission check logging to use dataclass - Updated PermissionsDebugView to use dataclass attributes - Updated PermissionCheckView to check parent/child instead of resource - Updated permissions_debug.html template to display parent/child - Updated test expectations to use dataclass attributes This provides better type safety and cleaner separation between parent and child resource identifiers.
This commit is contained in:
parent
4760cb9e06
commit
10ea23a59c
4 changed files with 37 additions and 34 deletions
|
|
@ -120,6 +120,17 @@ from .resources import InstanceResource, DatabaseResource, TableResource
|
||||||
|
|
||||||
app_root = Path(__file__).parent.parent
|
app_root = Path(__file__).parent.parent
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
|
class PermissionCheck:
|
||||||
|
"""Represents a logged permission check for debugging purposes."""
|
||||||
|
when: str
|
||||||
|
actor: Optional[Dict[str, Any]]
|
||||||
|
action: str
|
||||||
|
parent: Optional[str]
|
||||||
|
child: Optional[str]
|
||||||
|
result: bool
|
||||||
|
|
||||||
# https://github.com/simonw/datasette/issues/283#issuecomment-781591015
|
# https://github.com/simonw/datasette/issues/283#issuecomment-781591015
|
||||||
SQLITE_LIMIT_ATTACHED = 10
|
SQLITE_LIMIT_ATTACHED = 10
|
||||||
|
|
||||||
|
|
@ -1287,25 +1298,15 @@ class Datasette:
|
||||||
result = False
|
result = False
|
||||||
|
|
||||||
# Log the permission check for debugging
|
# Log the permission check for debugging
|
||||||
# Convert Resource to old-style format for backward compatibility with debug tools
|
|
||||||
if resource.parent and resource.child:
|
|
||||||
old_style_resource = (resource.parent, resource.child)
|
|
||||||
elif resource.parent:
|
|
||||||
old_style_resource = resource.parent
|
|
||||||
else:
|
|
||||||
old_style_resource = None
|
|
||||||
|
|
||||||
self._permission_checks.append(
|
self._permission_checks.append(
|
||||||
{
|
PermissionCheck(
|
||||||
"when": datetime.datetime.now(datetime.timezone.utc).isoformat(),
|
when=datetime.datetime.now(datetime.timezone.utc).isoformat(),
|
||||||
"actor": actor,
|
actor=actor,
|
||||||
"action": action,
|
action=action,
|
||||||
"resource": old_style_resource,
|
parent=resource.parent,
|
||||||
"result": result,
|
child=resource.child,
|
||||||
"reason": None, # Not tracked in new system
|
result=result,
|
||||||
"source_plugin": None, # Not tracked in new system
|
)
|
||||||
"depth": None, # Not tracked in new system
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
|
||||||
|
|
@ -133,8 +133,14 @@ debugPost.addEventListener('submit', function(ev) {
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</h2>
|
</h2>
|
||||||
<p><strong>Actor:</strong> {{ check.actor|tojson }}</p>
|
<p><strong>Actor:</strong> {{ check.actor|tojson }}</p>
|
||||||
{% if check.resource %}
|
{% if check.parent %}
|
||||||
<p><strong>Resource:</strong> {{ check.resource }}</p>
|
<p><strong>Resource:</strong>
|
||||||
|
{% if check.child %}
|
||||||
|
{{ check.parent }} / {{ check.child }}
|
||||||
|
{% else %}
|
||||||
|
{{ check.parent }}
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
||||||
|
|
@ -120,13 +120,13 @@ class PermissionsDebugView(BaseView):
|
||||||
permission_checks = [
|
permission_checks = [
|
||||||
check
|
check
|
||||||
for check in permission_checks
|
for check in permission_checks
|
||||||
if (check["actor"] or {}).get("id") != request.actor["id"]
|
if (check.actor or {}).get("id") != request.actor["id"]
|
||||||
]
|
]
|
||||||
elif filter_ == "only-yours":
|
elif filter_ == "only-yours":
|
||||||
permission_checks = [
|
permission_checks = [
|
||||||
check
|
check
|
||||||
for check in permission_checks
|
for check in permission_checks
|
||||||
if (check["actor"] or {}).get("id") == request.actor["id"]
|
if (check.actor or {}).get("id") == request.actor["id"]
|
||||||
]
|
]
|
||||||
return await self.render(
|
return await self.render(
|
||||||
["permissions_debug.html"],
|
["permissions_debug.html"],
|
||||||
|
|
@ -540,9 +540,10 @@ class PermissionCheckView(BaseView):
|
||||||
if len(self.ds._permission_checks) > before_checks:
|
if len(self.ds._permission_checks) > before_checks:
|
||||||
for check in reversed(self.ds._permission_checks):
|
for check in reversed(self.ds._permission_checks):
|
||||||
if (
|
if (
|
||||||
check.get("actor") == request.actor
|
check.actor == request.actor
|
||||||
and check.get("action") == action
|
and check.action == action
|
||||||
and check.get("resource") == resource
|
and check.parent == parent
|
||||||
|
and check.child == child
|
||||||
):
|
):
|
||||||
info = check
|
info = check
|
||||||
break
|
break
|
||||||
|
|
@ -560,12 +561,6 @@ class PermissionCheckView(BaseView):
|
||||||
if request.actor and "id" in request.actor:
|
if request.actor and "id" in request.actor:
|
||||||
response["actor_id"] = request.actor["id"]
|
response["actor_id"] = request.actor["id"]
|
||||||
|
|
||||||
if info is not None:
|
|
||||||
response["depth"] = info.get("depth")
|
|
||||||
# Only include sensitive fields if user has permissions-debug
|
|
||||||
if has_debug_permission:
|
|
||||||
response["reason"] = info.get("reason")
|
|
||||||
|
|
||||||
return Response.json(response)
|
return Response.json(response)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1259,9 +1259,10 @@ async def test_actor_restrictions(
|
||||||
"response_status": response.status_code,
|
"response_status": response.status_code,
|
||||||
"checks": [
|
"checks": [
|
||||||
{
|
{
|
||||||
"action": check["action"],
|
"action": check.action,
|
||||||
"resource": check["resource"],
|
"parent": check.parent,
|
||||||
"result": check["result"],
|
"child": check.child,
|
||||||
|
"result": check.result,
|
||||||
}
|
}
|
||||||
for check in perms_ds._permission_checks
|
for check in perms_ds._permission_checks
|
||||||
],
|
],
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue