mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
Migrate all view files to use new allowed() method with Resource objects
- Converted all permission_allowed() calls to allowed() - Use proper Resource objects (InstanceResource, DatabaseResource, TableResource) - Removed explicit InstanceResource() parameters where default applies - Updated PermissionRulesView to use build_permission_rules_sql() helper
This commit is contained in:
parent
224084facc
commit
a0659075a3
6 changed files with 81 additions and 68 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
from datasette import hookimpl
|
from datasette import hookimpl
|
||||||
|
from datasette.resources import DatabaseResource
|
||||||
from datasette.views.base import DatasetteError
|
from datasette.views.base import DatasetteError
|
||||||
from datasette.utils.asgi import BadRequest
|
from datasette.utils.asgi import BadRequest
|
||||||
import json
|
import json
|
||||||
|
|
@ -13,10 +14,10 @@ def where_filters(request, database, datasette):
|
||||||
where_clauses = []
|
where_clauses = []
|
||||||
extra_wheres_for_ui = []
|
extra_wheres_for_ui = []
|
||||||
if "_where" in request.args:
|
if "_where" in request.args:
|
||||||
if not await datasette.permission_allowed(
|
if not await datasette.allowed(
|
||||||
request.actor,
|
action="execute-sql",
|
||||||
"execute-sql",
|
resource=DatabaseResource(database=database),
|
||||||
resource=database,
|
actor=request.actor,
|
||||||
default=True,
|
default=True,
|
||||||
):
|
):
|
||||||
raise DatasetteError("_where= is not allowed", status=403)
|
raise DatasetteError("_where= is not allowed", status=403)
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ from typing import List
|
||||||
|
|
||||||
from datasette.events import AlterTableEvent, CreateTableEvent, InsertRowsEvent
|
from datasette.events import AlterTableEvent, CreateTableEvent, InsertRowsEvent
|
||||||
from datasette.database import QueryInterrupted
|
from datasette.database import QueryInterrupted
|
||||||
|
from datasette.resources import DatabaseResource
|
||||||
from datasette.utils import (
|
from datasette.utils import (
|
||||||
add_cors_headers,
|
add_cors_headers,
|
||||||
await_me_maybe,
|
await_me_maybe,
|
||||||
|
|
@ -119,8 +120,8 @@ class DatabaseView(View):
|
||||||
|
|
||||||
attached_databases = [d.name for d in await db.attached_databases()]
|
attached_databases = [d.name for d in await db.attached_databases()]
|
||||||
|
|
||||||
allow_execute_sql = await datasette.permission_allowed(
|
allow_execute_sql = await datasette.allowed(
|
||||||
request.actor, "execute-sql", database
|
action="execute-sql", resource=DatabaseResource(database=database), actor=request.actor
|
||||||
)
|
)
|
||||||
json_data = {
|
json_data = {
|
||||||
"database": database,
|
"database": database,
|
||||||
|
|
@ -729,8 +730,8 @@ class QueryView(View):
|
||||||
path_with_format(request=request, format=key)
|
path_with_format(request=request, format=key)
|
||||||
)
|
)
|
||||||
|
|
||||||
allow_execute_sql = await datasette.permission_allowed(
|
allow_execute_sql = await datasette.allowed(
|
||||||
request.actor, "execute-sql", database
|
action="execute-sql", resource=DatabaseResource(database=database), actor=request.actor
|
||||||
)
|
)
|
||||||
|
|
||||||
show_hide_hidden = ""
|
show_hide_hidden = ""
|
||||||
|
|
@ -940,8 +941,8 @@ class TableCreateView(BaseView):
|
||||||
database_name = db.name
|
database_name = db.name
|
||||||
|
|
||||||
# Must have create-table permission
|
# Must have create-table permission
|
||||||
if not await self.ds.permission_allowed(
|
if not await self.ds.allowed(
|
||||||
request.actor, "create-table", resource=database_name
|
action="create-table", resource=DatabaseResource(database=database_name), actor=request.actor
|
||||||
):
|
):
|
||||||
return _error(["Permission denied"], 403)
|
return _error(["Permission denied"], 403)
|
||||||
|
|
||||||
|
|
@ -977,8 +978,8 @@ class TableCreateView(BaseView):
|
||||||
|
|
||||||
if replace:
|
if replace:
|
||||||
# Must have update-row permission
|
# Must have update-row permission
|
||||||
if not await self.ds.permission_allowed(
|
if not await self.ds.allowed(
|
||||||
request.actor, "update-row", resource=database_name
|
action="update-row", resource=DatabaseResource(database=database_name), actor=request.actor
|
||||||
):
|
):
|
||||||
return _error(["Permission denied: need update-row"], 403)
|
return _error(["Permission denied: need update-row"], 403)
|
||||||
|
|
||||||
|
|
@ -1001,8 +1002,8 @@ class TableCreateView(BaseView):
|
||||||
|
|
||||||
if rows or row:
|
if rows or row:
|
||||||
# Must have insert-row permission
|
# Must have insert-row permission
|
||||||
if not await self.ds.permission_allowed(
|
if not await self.ds.allowed(
|
||||||
request.actor, "insert-row", resource=database_name
|
action="insert-row", resource=DatabaseResource(database=database_name), actor=request.actor
|
||||||
):
|
):
|
||||||
return _error(["Permission denied: need insert-row"], 403)
|
return _error(["Permission denied: need insert-row"], 403)
|
||||||
|
|
||||||
|
|
@ -1014,8 +1015,8 @@ class TableCreateView(BaseView):
|
||||||
else:
|
else:
|
||||||
# alter=True only if they request it AND they have permission
|
# alter=True only if they request it AND they have permission
|
||||||
if data.get("alter"):
|
if data.get("alter"):
|
||||||
if not await self.ds.permission_allowed(
|
if not await self.ds.allowed(
|
||||||
request.actor, "alter-table", resource=database_name
|
action="alter-table", resource=DatabaseResource(database=database_name), actor=request.actor
|
||||||
):
|
):
|
||||||
return _error(["Permission denied: need alter-table"], 403)
|
return _error(["Permission denied: need alter-table"], 403)
|
||||||
alter = True
|
alter = True
|
||||||
|
|
|
||||||
|
|
@ -177,8 +177,8 @@ class IndexView(BaseView):
|
||||||
"databases": databases,
|
"databases": databases,
|
||||||
"metadata": await self.ds.get_instance_metadata(),
|
"metadata": await self.ds.get_instance_metadata(),
|
||||||
"datasette_version": __version__,
|
"datasette_version": __version__,
|
||||||
"private": not await self.ds.permission_allowed(
|
"private": not await self.ds.allowed(
|
||||||
None, "view-instance"
|
action="view-instance", actor=None
|
||||||
),
|
),
|
||||||
"top_homepage": make_slot_function(
|
"top_homepage": make_slot_function(
|
||||||
"top_homepage", self.ds, request
|
"top_homepage", self.ds, request
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
from datasette.utils.asgi import NotFound, Forbidden, Response
|
from datasette.utils.asgi import NotFound, Forbidden, Response
|
||||||
from datasette.database import QueryInterrupted
|
from datasette.database import QueryInterrupted
|
||||||
from datasette.events import UpdateRowEvent, DeleteRowEvent
|
from datasette.events import UpdateRowEvent, DeleteRowEvent
|
||||||
|
from datasette.resources import TableResource
|
||||||
from .base import DataView, BaseView, _error
|
from .base import DataView, BaseView, _error
|
||||||
from datasette.utils import (
|
from datasette.utils import (
|
||||||
await_me_maybe,
|
await_me_maybe,
|
||||||
|
|
@ -184,8 +185,8 @@ async def _resolve_row_and_check_permission(datasette, request, permission):
|
||||||
return False, _error(["Record not found: {}".format(e.pk_values)], 404)
|
return False, _error(["Record not found: {}".format(e.pk_values)], 404)
|
||||||
|
|
||||||
# Ensure user has permission to delete this row
|
# Ensure user has permission to delete this row
|
||||||
if not await datasette.permission_allowed(
|
if not await datasette.allowed(
|
||||||
request.actor, permission, resource=(resolved.db.name, resolved.table)
|
action=permission, resource=TableResource(database=resolved.db.name, table=resolved.table), actor=request.actor
|
||||||
):
|
):
|
||||||
return False, _error(["Permission denied"], 403)
|
return False, _error(["Permission denied"], 403)
|
||||||
|
|
||||||
|
|
@ -257,8 +258,8 @@ class RowUpdateView(BaseView):
|
||||||
update = data["update"]
|
update = data["update"]
|
||||||
|
|
||||||
alter = data.get("alter")
|
alter = data.get("alter")
|
||||||
if alter and not await self.ds.permission_allowed(
|
if alter and not await self.ds.allowed(
|
||||||
request.actor, "alter-table", resource=(resolved.db.name, resolved.table)
|
action="alter-table", resource=TableResource(database=resolved.db.name, table=resolved.table), actor=request.actor
|
||||||
):
|
):
|
||||||
return _error(["Permission denied for alter-table"], 403)
|
return _error(["Permission denied for alter-table"], 403)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from datasette.events import LogoutEvent, LoginEvent, CreateTokenEvent
|
from datasette.events import LogoutEvent, LoginEvent, CreateTokenEvent
|
||||||
|
from datasette.resources import DatabaseResource, TableResource, InstanceResource
|
||||||
from datasette.utils.asgi import Response, Forbidden
|
from datasette.utils.asgi import Response, Forbidden
|
||||||
from datasette.utils import (
|
from datasette.utils import (
|
||||||
actor_matches_allow,
|
actor_matches_allow,
|
||||||
|
|
@ -112,7 +113,7 @@ class PermissionsDebugView(BaseView):
|
||||||
|
|
||||||
async def get(self, request):
|
async def get(self, request):
|
||||||
await self.ds.ensure_permissions(request.actor, ["view-instance"])
|
await self.ds.ensure_permissions(request.actor, ["view-instance"])
|
||||||
if not await self.ds.permission_allowed(request.actor, "permissions-debug"):
|
if not await self.ds.allowed(action="permissions-debug", actor=request.actor):
|
||||||
raise Forbidden("Permission denied")
|
raise Forbidden("Permission denied")
|
||||||
filter_ = request.args.get("filter") or "all"
|
filter_ = request.args.get("filter") or "all"
|
||||||
permission_checks = list(reversed(self.ds._permission_checks))
|
permission_checks = list(reversed(self.ds._permission_checks))
|
||||||
|
|
@ -151,29 +152,31 @@ class PermissionsDebugView(BaseView):
|
||||||
|
|
||||||
async def post(self, request):
|
async def post(self, request):
|
||||||
await self.ds.ensure_permissions(request.actor, ["view-instance"])
|
await self.ds.ensure_permissions(request.actor, ["view-instance"])
|
||||||
if not await self.ds.permission_allowed(request.actor, "permissions-debug"):
|
if not await self.ds.allowed(action="permissions-debug", actor=request.actor):
|
||||||
raise Forbidden("Permission denied")
|
raise Forbidden("Permission denied")
|
||||||
vars = await request.post_vars()
|
vars = await request.post_vars()
|
||||||
actor = json.loads(vars["actor"])
|
actor = json.loads(vars["actor"])
|
||||||
permission = vars["permission"]
|
permission = vars["permission"]
|
||||||
resource_1 = vars["resource_1"]
|
resource_1 = vars["resource_1"]
|
||||||
resource_2 = vars["resource_2"]
|
resource_2 = vars["resource_2"]
|
||||||
resource = []
|
# Convert to Resource object
|
||||||
if resource_1:
|
if resource_1 and resource_2:
|
||||||
resource.append(resource_1)
|
resource_obj = TableResource(database=resource_1, table=resource_2)
|
||||||
if resource_2:
|
resource_for_response = (resource_1, resource_2)
|
||||||
resource.append(resource_2)
|
elif resource_1:
|
||||||
resource = tuple(resource)
|
resource_obj = DatabaseResource(database=resource_1)
|
||||||
if len(resource) == 1:
|
resource_for_response = resource_1
|
||||||
resource = resource[0]
|
else:
|
||||||
result = await self.ds.permission_allowed(
|
resource_obj = InstanceResource()
|
||||||
actor, permission, resource, default="USE_DEFAULT"
|
resource_for_response = None
|
||||||
|
result = await self.ds.allowed(
|
||||||
|
action=permission, resource=resource_obj, actor=actor
|
||||||
)
|
)
|
||||||
return Response.json(
|
return Response.json(
|
||||||
{
|
{
|
||||||
"actor": actor,
|
"actor": actor,
|
||||||
"permission": permission,
|
"permission": permission,
|
||||||
"resource": resource,
|
"resource": resource_for_response,
|
||||||
"result": result,
|
"result": result,
|
||||||
"default": self.ds.permissions[permission].default,
|
"default": self.ds.permissions[permission].default,
|
||||||
}
|
}
|
||||||
|
|
@ -204,8 +207,8 @@ class AllowedResourcesView(BaseView):
|
||||||
await self.ds.refresh_schemas()
|
await self.ds.refresh_schemas()
|
||||||
|
|
||||||
# Check if user has permissions-debug (to show sensitive fields)
|
# Check if user has permissions-debug (to show sensitive fields)
|
||||||
has_debug_permission = await self.ds.permission_allowed(
|
has_debug_permission = await self.ds.allowed(
|
||||||
request.actor, "permissions-debug"
|
action="permissions-debug", actor=request.actor
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check if this is a request for JSON (has .json extension)
|
# Check if this is a request for JSON (has .json extension)
|
||||||
|
|
@ -360,7 +363,7 @@ class PermissionRulesView(BaseView):
|
||||||
|
|
||||||
async def get(self, request):
|
async def get(self, request):
|
||||||
await self.ds.ensure_permissions(request.actor, ["view-instance"])
|
await self.ds.ensure_permissions(request.actor, ["view-instance"])
|
||||||
if not await self.ds.permission_allowed(request.actor, "permissions-debug"):
|
if not await self.ds.allowed(action="permissions-debug", actor=request.actor):
|
||||||
raise Forbidden("Permission denied")
|
raise Forbidden("Permission denied")
|
||||||
|
|
||||||
# Check if this is a request for JSON (has .json extension)
|
# Check if this is a request for JSON (has .json extension)
|
||||||
|
|
@ -401,8 +404,10 @@ class PermissionRulesView(BaseView):
|
||||||
page_size = max_page_size
|
page_size = max_page_size
|
||||||
offset = (page - 1) * page_size
|
offset = (page - 1) * page_size
|
||||||
|
|
||||||
union_sql, union_params = await self.ds._build_permission_rules_sql(
|
from datasette.utils.actions_sql import build_permission_rules_sql
|
||||||
actor, action
|
|
||||||
|
union_sql, union_params = await build_permission_rules_sql(
|
||||||
|
self.ds, actor, action
|
||||||
)
|
)
|
||||||
await self.ds.refresh_schemas()
|
await self.ds.refresh_schemas()
|
||||||
db = self.ds.get_internal_database()
|
db = self.ds.get_internal_database()
|
||||||
|
|
@ -482,8 +487,8 @@ class PermissionCheckView(BaseView):
|
||||||
|
|
||||||
async def get(self, request):
|
async def get(self, request):
|
||||||
# Check if user has permissions-debug (to show sensitive fields)
|
# Check if user has permissions-debug (to show sensitive fields)
|
||||||
has_debug_permission = await self.ds.permission_allowed(
|
has_debug_permission = await self.ds.allowed(
|
||||||
request.actor, "permissions-debug"
|
action="permissions-debug", actor=request.actor
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check if this is a request for JSON (has .json extension)
|
# Check if this is a request for JSON (has .json extension)
|
||||||
|
|
@ -513,15 +518,19 @@ class PermissionCheckView(BaseView):
|
||||||
{"error": "parent is required when child is provided"}, status=400
|
{"error": "parent is required when child is provided"}, status=400
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Convert to Resource object
|
||||||
if parent and child:
|
if parent and child:
|
||||||
|
resource_obj = TableResource(database=parent, table=child)
|
||||||
resource = (parent, child)
|
resource = (parent, child)
|
||||||
elif parent:
|
elif parent:
|
||||||
|
resource_obj = DatabaseResource(database=parent)
|
||||||
resource = parent
|
resource = parent
|
||||||
else:
|
else:
|
||||||
|
resource_obj = InstanceResource()
|
||||||
resource = None
|
resource = None
|
||||||
|
|
||||||
before_checks = len(self.ds._permission_checks)
|
before_checks = len(self.ds._permission_checks)
|
||||||
allowed = await self.ds.permission_allowed_2(request.actor, action, resource)
|
allowed = await self.ds.allowed(action=action, resource=resource_obj, actor=request.actor)
|
||||||
|
|
||||||
info = None
|
info = None
|
||||||
if len(self.ds._permission_checks) > before_checks:
|
if len(self.ds._permission_checks) > before_checks:
|
||||||
|
|
@ -642,8 +651,8 @@ class CreateTokenView(BaseView):
|
||||||
for database in self.ds.databases.values():
|
for database in self.ds.databases.values():
|
||||||
if database.name == "_memory":
|
if database.name == "_memory":
|
||||||
continue
|
continue
|
||||||
if not await self.ds.permission_allowed(
|
if not await self.ds.allowed(
|
||||||
request.actor, "view-database", database.name
|
action="view-database", resource=DatabaseResource(database=database.name), actor=request.actor
|
||||||
):
|
):
|
||||||
continue
|
continue
|
||||||
hidden_tables = await database.hidden_table_names()
|
hidden_tables = await database.hidden_table_names()
|
||||||
|
|
@ -651,10 +660,10 @@ class CreateTokenView(BaseView):
|
||||||
for table in await database.table_names():
|
for table in await database.table_names():
|
||||||
if table in hidden_tables:
|
if table in hidden_tables:
|
||||||
continue
|
continue
|
||||||
if not await self.ds.permission_allowed(
|
if not await self.ds.allowed(
|
||||||
request.actor,
|
action="view-table",
|
||||||
"view-table",
|
resource=TableResource(database=database.name, table=table),
|
||||||
resource=(database.name, table),
|
actor=request.actor
|
||||||
):
|
):
|
||||||
continue
|
continue
|
||||||
tables.append({"name": table, "encoded": tilde_encode(table)})
|
tables.append({"name": table, "encoded": tilde_encode(table)})
|
||||||
|
|
@ -795,8 +804,8 @@ class ApiExplorerView(BaseView):
|
||||||
if not db.is_mutable:
|
if not db.is_mutable:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if await self.ds.permission_allowed(
|
if await self.ds.allowed(
|
||||||
request.actor, "insert-row", (name, table)
|
action="insert-row", resource=TableResource(database=name, table=table), actor=request.actor
|
||||||
):
|
):
|
||||||
pks = await db.primary_keys(table)
|
pks = await db.primary_keys(table)
|
||||||
table_links.extend(
|
table_links.extend(
|
||||||
|
|
@ -831,8 +840,8 @@ class ApiExplorerView(BaseView):
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
if await self.ds.permission_allowed(
|
if await self.ds.allowed(
|
||||||
request.actor, "drop-table", (name, table)
|
action="drop-table", resource=TableResource(database=name, table=table), actor=request.actor
|
||||||
):
|
):
|
||||||
table_links.append(
|
table_links.append(
|
||||||
{
|
{
|
||||||
|
|
@ -844,7 +853,7 @@ class ApiExplorerView(BaseView):
|
||||||
)
|
)
|
||||||
database_links = []
|
database_links = []
|
||||||
if (
|
if (
|
||||||
await self.ds.permission_allowed(request.actor, "create-table", name)
|
await self.ds.allowed(action="create-table", resource=DatabaseResource(database=name), actor=request.actor)
|
||||||
and db.is_mutable
|
and db.is_mutable
|
||||||
):
|
):
|
||||||
database_links.append(
|
database_links.append(
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ from datasette.events import (
|
||||||
UpsertRowsEvent,
|
UpsertRowsEvent,
|
||||||
)
|
)
|
||||||
from datasette import tracer
|
from datasette import tracer
|
||||||
|
from datasette.resources import DatabaseResource, TableResource
|
||||||
from datasette.utils import (
|
from datasette.utils import (
|
||||||
add_cors_headers,
|
add_cors_headers,
|
||||||
await_me_maybe,
|
await_me_maybe,
|
||||||
|
|
@ -449,11 +450,11 @@ class TableInsertView(BaseView):
|
||||||
if upsert:
|
if upsert:
|
||||||
# Must have insert-row AND upsert-row permissions
|
# Must have insert-row AND upsert-row permissions
|
||||||
if not (
|
if not (
|
||||||
await self.ds.permission_allowed(
|
await self.ds.allowed(
|
||||||
request.actor, "insert-row", resource=(database_name, table_name)
|
action="insert-row", resource=TableResource(database=database_name, table=table_name), actor=request.actor
|
||||||
)
|
)
|
||||||
and await self.ds.permission_allowed(
|
and await self.ds.allowed(
|
||||||
request.actor, "update-row", resource=(database_name, table_name)
|
action="update-row", resource=TableResource(database=database_name, table=table_name), actor=request.actor
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
return _error(
|
return _error(
|
||||||
|
|
@ -461,8 +462,8 @@ class TableInsertView(BaseView):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# Must have insert-row permission
|
# Must have insert-row permission
|
||||||
if not await self.ds.permission_allowed(
|
if not await self.ds.allowed(
|
||||||
request.actor, "insert-row", resource=(database_name, table_name)
|
action="insert-row", resource=TableResource(database=database_name, table=table_name), actor=request.actor
|
||||||
):
|
):
|
||||||
return _error(["Permission denied"], 403)
|
return _error(["Permission denied"], 403)
|
||||||
|
|
||||||
|
|
@ -491,16 +492,16 @@ class TableInsertView(BaseView):
|
||||||
if upsert and (ignore or replace):
|
if upsert and (ignore or replace):
|
||||||
return _error(["Upsert does not support ignore or replace"], 400)
|
return _error(["Upsert does not support ignore or replace"], 400)
|
||||||
|
|
||||||
if replace and not await self.ds.permission_allowed(
|
if replace and not await self.ds.allowed(
|
||||||
request.actor, "update-row", resource=(database_name, table_name)
|
action="update-row", resource=TableResource(database=database_name, table=table_name), actor=request.actor
|
||||||
):
|
):
|
||||||
return _error(['Permission denied: need update-row to use "replace"'], 403)
|
return _error(['Permission denied: need update-row to use "replace"'], 403)
|
||||||
|
|
||||||
initial_schema = None
|
initial_schema = None
|
||||||
if alter:
|
if alter:
|
||||||
# Must have alter-table permission
|
# Must have alter-table permission
|
||||||
if not await self.ds.permission_allowed(
|
if not await self.ds.allowed(
|
||||||
request.actor, "alter-table", resource=(database_name, table_name)
|
action="alter-table", resource=TableResource(database=database_name, table=table_name), actor=request.actor
|
||||||
):
|
):
|
||||||
return _error(["Permission denied for alter-table"], 403)
|
return _error(["Permission denied for alter-table"], 403)
|
||||||
# Track initial schema to check if it changed later
|
# Track initial schema to check if it changed later
|
||||||
|
|
@ -627,8 +628,8 @@ class TableDropView(BaseView):
|
||||||
db = self.ds.get_database(database_name)
|
db = self.ds.get_database(database_name)
|
||||||
if not await db.table_exists(table_name):
|
if not await db.table_exists(table_name):
|
||||||
return _error(["Table not found: {}".format(table_name)], 404)
|
return _error(["Table not found: {}".format(table_name)], 404)
|
||||||
if not await self.ds.permission_allowed(
|
if not await self.ds.allowed(
|
||||||
request.actor, "drop-table", resource=(database_name, table_name)
|
action="drop-table", resource=TableResource(database=database_name, table=table_name), actor=request.actor
|
||||||
):
|
):
|
||||||
return _error(["Permission denied"], 403)
|
return _error(["Permission denied"], 403)
|
||||||
if not db.is_mutable:
|
if not db.is_mutable:
|
||||||
|
|
@ -914,8 +915,8 @@ async def table_view_traced(datasette, request):
|
||||||
"true" if datasette.setting("allow_facet") else "false"
|
"true" if datasette.setting("allow_facet") else "false"
|
||||||
),
|
),
|
||||||
is_sortable=any(c["sortable"] for c in data["display_columns"]),
|
is_sortable=any(c["sortable"] for c in data["display_columns"]),
|
||||||
allow_execute_sql=await datasette.permission_allowed(
|
allow_execute_sql=await datasette.allowed(
|
||||||
request.actor, "execute-sql", resolved.db.name
|
action="execute-sql", resource=DatabaseResource(database=resolved.db.name), actor=request.actor
|
||||||
),
|
),
|
||||||
query_ms=1.2,
|
query_ms=1.2,
|
||||||
select_templates=[
|
select_templates=[
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue