issue_comments: 1278300241
This data as json
html_url | issue_url | id | node_id | user | created_at | updated_at | author_association | body | reactions | issue | performed_via_github_app |
---|---|---|---|---|---|---|---|---|---|---|---|
https://github.com/simonw/datasette/issues/1829#issuecomment-1278300241 | https://api.github.com/repos/simonw/datasette/issues/1829 | 1278300241 | IC_kwDOBm6k_c5MMVBR | 9599 | 2022-10-14T00:03:52Z | 2022-10-14T00:04:28Z | OWNER | Here's what I've got so far: ```diff diff --git a/datasette/app.py b/datasette/app.py index 5fa4955c..df9eae49 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -1,5 +1,5 @@ import asyncio -from typing import Sequence, Union, Tuple +from typing import Sequence, Union, Tuple, Optional import asgi_csrf import collections import datetime @@ -707,7 +707,7 @@ class Datasette: Raises datasette.Forbidden() if any of the checks fail """ - assert actor is None or isinstance(actor, dict) + assert actor is None or isinstance(actor, dict), "actor must be None or a dict" for permission in permissions: if isinstance(permission, str): action = permission @@ -732,23 +732,34 @@ class Datasette: else: raise Forbidden(action) - async def check_visibility(self, actor, action, resource): + async def check_visibility( + self, + actor: dict, + action: Optional[str] = None, + resource: Optional[str] = None, + permissions: Optional[ + Sequence[Union[Tuple[str, Union[str, Tuple[str, str]]], str]] + ] = None, + ): """Returns (visible, private) - visible = can you see it, private = can others see it too""" - visible = await self.permission_allowed( - actor, - action, - resource=resource, - default=True, - ) - if not visible: + if permissions: + assert ( + not action and not resource + ), "Can't use action= or resource= with permissions=" + else: + permissions = [(action, resource)] + try: + await self.ensure_permissions(actor, permissions) + except Forbidden: return False, False - private = not await self.permission_allowed( - None, - action, - resource=resource, - default=True, - ) - return visible, private + # User can see it, but can the anonymous user see it? + try: + await self.ensure_permissions(None, permissions) + except Forbidden: + # It's visible but private + return True, True + # It's visible to everyone + return True, False async def execute( self, diff --git a/datasette/views/table.py b/datasette/views/table.py index 60c092f9..f73b0957 100644 --- a/datasette/views/table.py +++ b/datasette/views/table.py @@ -28,7 +28,7 @@ from datasette.utils import ( urlsafe_components, value_as_boolean, ) -from datasette.utils.asgi import BadRequest, NotFound +from datasette.utils.asgi import BadRequest, Forbidden, NotFound from datasette.filters import Filters from .base import DataView, DatasetteError, ureg from .database import QueryView @@ -213,18 +213,16 @@ class TableView(DataView): raise NotFound(f"Table not found: {table_name}") # Ensure user has permission to view this table - await self.ds.ensure_permissions( + visible, private = await self.ds.check_visibility( request.actor, - [ + permissions=[ ("view-table", (database_name, table_name)), ("view-database", database_name), "view-instance", ], ) - - private = not await self.ds.permission_allowed( - None, "view-table", (database_name, table_name), default=True - ) + if not visible: + raise Forbidden("You do not have permission to view this table") # Handle ?_filter_column and redirect, if present redirect_params = filters_should_redirect(request.args) ``` Still needs tests and a documentation update. Also this fix is currently only applied on the table page - needs to be applied on database, row and query pages too. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | 1396948693 |