Handle non-initials in permission_allowed_actor_restrictions, closes #1956

pull/1961/head
Simon Willison 2022-12-14 12:04:23 -08:00
rodzic 1a3dcf4943
commit e238df3959
2 zmienionych plików z 27 dodań i 5 usunięć

Wyświetl plik

@ -173,14 +173,20 @@ async def _resolve_metadata_view_permissions(datasette, actor, action, resource)
@hookimpl(specname="permission_allowed")
def permission_allowed_actor_restrictions(actor, action, resource):
def permission_allowed_actor_restrictions(datasette, actor, action, resource):
if actor is None:
return None
if "_r" not in actor:
# No restrictions, so we have no opinion
return None
_r = actor.get("_r")
action_initials = "".join([word[0] for word in action.split("-")])
# Does this action have an abbreviation?
to_check = {action}
permission = datasette.permissions.get(action)
if permission and permission.abbr:
to_check.add(permission.abbr)
# If _r is defined then we use those to further restrict the actor
# Crucially, we only use this to say NO (return False) - we never
# use it to return YES (True) because that might over-ride other
@ -188,14 +194,14 @@ def permission_allowed_actor_restrictions(actor, action, resource):
all_allowed = _r.get("a")
if all_allowed is not None:
assert isinstance(all_allowed, list)
if action_initials in all_allowed:
if to_check.intersection(all_allowed):
return None
# How about for the current database?
if isinstance(resource, str):
database_allowed = _r.get("d", {}).get(resource)
if database_allowed is not None:
assert isinstance(database_allowed, list)
if action_initials in database_allowed:
if to_check.intersection(database_allowed):
return None
# Or the current table? That's any time the resource is (database, table)
if resource is not None and not isinstance(resource, str) and len(resource) == 2:
@ -204,7 +210,7 @@ def permission_allowed_actor_restrictions(actor, action, resource):
# TODO: What should this do for canned queries?
if table_allowed is not None:
assert isinstance(table_allowed, list)
if action_initials in table_allowed:
if to_check.intersection(table_allowed):
return None
# This action is not specifically allowed, so reject it
return False

Wyświetl plik

@ -609,6 +609,22 @@ DEF = "USE_DEFAULT"
"t2",
False,
),
# non-abbreviations should work too
({"id": "t", "_r": {"a": ["view-instance"]}}, "view-instance", None, None, DEF),
(
{"id": "t", "_r": {"d": {"one": ["view-database"]}}},
"view-database",
"one",
None,
DEF,
),
(
{"id": "t", "_r": {"r": {"one": {"t1": ["view-table"]}}}},
"view-table",
"one",
"t1",
DEF,
),
),
)
async def test_actor_restricted_permissions(