async def get(self, request): errors = [] actor_input = request.args.get("actor") or '{"id": "root"}' try: actor = json.loads(actor_input) actor_input = json.dumps(actor, indent=4) except json.decoder.JSONDecodeError as ex: errors.append("Actor JSON error: {}".format(ex)) allow_input = request.args.get("allow") or '{"id": "*"}' try: allow = json.loads(allow_input) allow_input = json.dumps(allow, indent=4) except json.decoder.JSONDecodeError as ex: errors.append("Allow JSON error: {}".format(ex)) result = None if not errors: result = str(actor_matches_allow(actor, allow)) return await self.render( ["allow_debug.html"], request, { "result": result, "error": "\n\n".join(errors) if errors else "", "actor_input": actor_input, "allow_input": allow_input, }, )
async def inner(): if action in ("permissions-debug", "debug-menu"): if actor and actor.get("id") == "root": return True elif action == "view-instance": allow = datasette.metadata("allow") if allow is not None: return actor_matches_allow(actor, allow) elif action == "view-database": if resource == "_internal" and (actor is None or actor.get("id") != "root"): return False database_allow = datasette.metadata("allow", database=resource) if database_allow is None: return None return actor_matches_allow(actor, database_allow) elif action == "view-table": database, table = resource tables = datasette.metadata("tables", database=database) or {} table_allow = (tables.get(table) or {}).get("allow") if table_allow is None: return None return actor_matches_allow(actor, table_allow) elif action == "view-query": # Check if this query has a "allow" block in metadata database, query_name = resource query = await datasette.get_canned_query(database, query_name, actor) assert query is not None allow = query.get("allow") if allow is None: return None return actor_matches_allow(actor, allow) elif action == "execute-sql": # Use allow_sql block from database block, or from top-level database_allow_sql = datasette.metadata("allow_sql", database=resource) if database_allow_sql is None: database_allow_sql = datasette.metadata("allow_sql") if database_allow_sql is None: return None return actor_matches_allow(actor, database_allow_sql)
def permission_allowed(datasette, actor, action, resource): if action == "permissions-debug": if actor and actor.get("id") == "root": return True elif action == "view-instance": allow = datasette.metadata("allow") if allow is not None: return actor_matches_allow(actor, allow) elif action == "view-database": database_allow = datasette.metadata("allow", database=resource) if database_allow is None: return True return actor_matches_allow(actor, database_allow) elif action == "view-table": database, table = resource tables = datasette.metadata("tables", database=database) or {} table_allow = (tables.get(table) or {}).get("allow") if table_allow is None: return True return actor_matches_allow(actor, table_allow) elif action == "view-query": # Check if this query has a "allow" block in metadata database, query_name = resource queries_metadata = datasette.metadata("queries", database=database) assert query_name in queries_metadata if isinstance(queries_metadata[query_name], str): return True allow = queries_metadata[query_name].get("allow") if allow is None: return True return actor_matches_allow(actor, allow) elif action == "execute-sql": # Use allow_sql block from database block, or from top-level database_allow_sql = datasette.metadata("allow_sql", database=resource) if database_allow_sql is None: database_allow_sql = datasette.metadata("allow_sql") if database_allow_sql is None: return True return actor_matches_allow(actor, database_allow_sql)
def test_actor_matches_allow(actor, allow, expected): assert expected == utils.actor_matches_allow(actor, allow)