diff --git a/datasette/utils/__init__.py b/datasette/utils/__init__.py index 077728f4..3d964049 100644 --- a/datasette/utils/__init__.py +++ b/datasette/utils/__init__.py @@ -874,3 +874,26 @@ def actor_matches_allow(actor, allow): if actor_values.intersection(values): return True return False + + +async def check_visibility( + datasette, actor, action, resource_type, resource_identifier, default=True +): + "Returns (visible, private) - visible = can you see it, private = can others see it too" + visible = await datasette.permission_allowed( + actor, + action, + resource_type=resource_type, + resource_identifier=resource_identifier, + default=default, + ) + if not visible: + return (False, False) + private = not await datasette.permission_allowed( + None, + action, + resource_type=resource_type, + resource_identifier=resource_identifier, + default=default, + ) + return visible, private diff --git a/datasette/views/database.py b/datasette/views/database.py index ba3d22d9..afbb6b05 100644 --- a/datasette/views/database.py +++ b/datasette/views/database.py @@ -3,6 +3,7 @@ import jinja2 from datasette.utils import ( actor_matches_allow, + check_visibility, to_css_class, validate_sql_select, is_url, @@ -42,21 +43,15 @@ class DatabaseView(DataView): tables = [] for table in table_counts: - allowed = await self.ds.permission_allowed( + visible, private = await check_visibility( + self.ds, request.scope.get("actor"), "view-table", - resource_type="table", - resource_identifier=(database, table), - default=True, + "table", + (database, table), ) - if not allowed: + if not visible: continue - private = not await self.ds.permission_allowed( - None, - "view-table", - resource_type="table", - resource_identifier=(database, table), - ) table_columns = await db.table_columns(table) tables.append( { @@ -72,15 +67,17 @@ class DatabaseView(DataView): ) tables.sort(key=lambda t: (t["hidden"], t["name"])) - canned_queries = [ - dict( - query, private=not actor_matches_allow(None, query.get("allow", None)), + canned_queries = [] + for query in self.ds.get_canned_queries(database): + visible, private = await check_visibility( + self.ds, + request.scope.get("actor"), + "view-query", + "query", + (database, query["name"]), ) - for query in self.ds.get_canned_queries(database) - if actor_matches_allow( - request.scope.get("actor", None), query.get("allow", None) - ) - ] + if visible: + canned_queries.append(dict(query, private=private)) return ( { "database": database, diff --git a/datasette/views/index.py b/datasette/views/index.py index 7b88028b..0f7fb613 100644 --- a/datasette/views/index.py +++ b/datasette/views/index.py @@ -1,7 +1,7 @@ import hashlib import json -from datasette.utils import CustomJSONEncoder +from datasette.utils import check_visibility, CustomJSONEncoder from datasette.utils.asgi import Response, Forbidden from datasette.version import __version__ @@ -25,22 +25,11 @@ class IndexView(BaseView): await self.check_permission(request, "view-instance") databases = [] for name, db in self.ds.databases.items(): - # Check permission - allowed = await self.ds.permission_allowed( - request.scope.get("actor"), - "view-database", - resource_type="database", - resource_identifier=name, - default=True, + visible, private = await check_visibility( + self.ds, request.scope.get("actor"), "view-database", "database", name, ) - if not allowed: + if not visible: continue - private = not await self.ds.permission_allowed( - None, - "view-database", - resource_type="database", - resource_identifier=name, - ) table_names = await db.table_names() hidden_table_names = set(await db.hidden_table_names()) views = await db.view_names()