New check_visibility() utility function, refs #811

This commit is contained in:
Simon Willison 2020-06-08 06:49:55 -07:00
commit e18f8c3f87
3 changed files with 43 additions and 34 deletions

View file

@ -874,3 +874,26 @@ def actor_matches_allow(actor, allow):
if actor_values.intersection(values): if actor_values.intersection(values):
return True return True
return False 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

View file

@ -3,6 +3,7 @@ import jinja2
from datasette.utils import ( from datasette.utils import (
actor_matches_allow, actor_matches_allow,
check_visibility,
to_css_class, to_css_class,
validate_sql_select, validate_sql_select,
is_url, is_url,
@ -42,21 +43,15 @@ class DatabaseView(DataView):
tables = [] tables = []
for table in table_counts: for table in table_counts:
allowed = await self.ds.permission_allowed( visible, private = await check_visibility(
self.ds,
request.scope.get("actor"), request.scope.get("actor"),
"view-table", "view-table",
resource_type="table", "table",
resource_identifier=(database, table), (database, table),
default=True,
) )
if not allowed: if not visible:
continue 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) table_columns = await db.table_columns(table)
tables.append( tables.append(
{ {
@ -72,15 +67,17 @@ class DatabaseView(DataView):
) )
tables.sort(key=lambda t: (t["hidden"], t["name"])) tables.sort(key=lambda t: (t["hidden"], t["name"]))
canned_queries = [ canned_queries = []
dict( for query in self.ds.get_canned_queries(database):
query, private=not actor_matches_allow(None, query.get("allow", None)), 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 visible:
if actor_matches_allow( canned_queries.append(dict(query, private=private))
request.scope.get("actor", None), query.get("allow", None)
)
]
return ( return (
{ {
"database": database, "database": database,

View file

@ -1,7 +1,7 @@
import hashlib import hashlib
import json import json
from datasette.utils import CustomJSONEncoder from datasette.utils import check_visibility, CustomJSONEncoder
from datasette.utils.asgi import Response, Forbidden from datasette.utils.asgi import Response, Forbidden
from datasette.version import __version__ from datasette.version import __version__
@ -25,22 +25,11 @@ class IndexView(BaseView):
await self.check_permission(request, "view-instance") await self.check_permission(request, "view-instance")
databases = [] databases = []
for name, db in self.ds.databases.items(): for name, db in self.ds.databases.items():
# Check permission visible, private = await check_visibility(
allowed = await self.ds.permission_allowed( self.ds, request.scope.get("actor"), "view-database", "database", name,
request.scope.get("actor"),
"view-database",
resource_type="database",
resource_identifier=name,
default=True,
) )
if not allowed: if not visible:
continue continue
private = not await self.ds.permission_allowed(
None,
"view-database",
resource_type="database",
resource_identifier=name,
)
table_names = await db.table_names() table_names = await db.table_names()
hidden_table_names = set(await db.hidden_table_names()) hidden_table_names = set(await db.hidden_table_names())
views = await db.view_names() views = await db.view_names()