id,page,ref,title,content,breadcrumbs,references plugin_hooks:allow-alice-to-view-a-specific-table,plugin_hooks,allow-alice-to-view-a-specific-table,Allow Alice to view a specific table,"This plugin grants the actor with id == ""alice"" permission to perform the view-table action against the sales table inside the accounting database. from datasette import hookimpl from datasette.permissions import PermissionSQL @hookimpl def permission_resources_sql(datasette, actor, action): if action != ""view-table"": return None if not actor or actor.get(""id"") != ""alice"": return None return PermissionSQL( sql="""""" SELECT 'accounting' AS parent, 'sales' AS child, 1 AS allow, 'alice can view accounting/sales' AS reason """""", )","[""Plugin hooks"", ""permission_resources_sql(datasette, actor, action)"", ""Permission plugin examples""]",[] plugin_hooks:default-deny-with-an-exception,plugin_hooks,default-deny-with-an-exception,Default deny with an exception,"Combine a root-level deny with a specific table allow for trusted users. The resolver will automatically apply the most specific rule. from datasette import hookimpl from datasette.permissions import PermissionSQL TRUSTED = {""alice"", ""bob""} @hookimpl def permission_resources_sql(datasette, actor, action): if action != ""view-table"": return None actor_id = (actor or {}).get(""id"") if actor_id not in TRUSTED: return PermissionSQL( sql="""""" SELECT NULL AS parent, NULL AS child, 0 AS allow, 'default deny view-table' AS reason """""", ) return PermissionSQL( sql="""""" SELECT NULL AS parent, NULL AS child, 0 AS allow, 'default deny view-table' AS reason UNION ALL SELECT 'reports' AS parent, 'daily_metrics' AS child, 1 AS allow, 'trusted user access' AS reason """""", params={""actor_id"": actor_id}, ) The UNION ALL ensures the deny rule is always present, while the second row adds the exception for trusted users.","[""Plugin hooks"", ""permission_resources_sql(datasette, actor, action)"", ""Permission plugin examples""]",[] plugin_hooks:id1,plugin_hooks,id1,Plugin hooks,"Datasette plugins use plugin hooks to customize Datasette's behavior. These hooks are powered by the pluggy plugin system. Each plugin can implement one or more hooks using the @hookimpl decorator against a function named that matches one of the hooks documented on this page. When you implement a plugin hook you can accept any or all of the parameters that are documented as being passed to that hook. For example, you can implement the render_cell plugin hook like this even though the full documented hook signature is render_cell(row, value, column, table, pks, database, datasette, request) : @hookimpl def render_cell(value, column): if column == ""stars"": return ""*"" * int(value) List of plugin hooks prepare_connection(conn, database, datasette) write_wrapper(datasette, database, request, transaction) prepare_jinja2_environment(env, datasette) Page extras extra_template_vars(template, database, table, columns, view_name, request, datasette) extra_css_urls(template, database, table, columns, view_name, request, datasette) extra_js_urls(template, database, table, columns, view_name, request, datasette) extra_body_script(template, database, table, columns, view_name, request, datasette) publish_subcommand(publish) render_cell(row, value, column, table, pks, database, datasette, request, column_type) register_output_renderer(datasette) register_routes(datasette) register_commands(cli) register_facet_classes() register_actions(datasette) The resources_sql(datasette, actor) method register_column_types(datasette) asgi_wrapper(datasette) startup(datasette) actor_from_request(datasette, request) actors_from_ids(datasette, actor_ids) jinja2_environment_from_request(datasette, request, env) filters_from_request(request, database, table, datasette) permission_resources_sql(datasette, actor, action) Permission plugin examples Allow Alice to view a specific table Restrict execute-sql to a database prefix Read permissions from a custom table Default deny with an exception register_magic_parameters(datasette) forbidden(datasette, request, message) handle_exception(datasette, request, exception) menu_links(datasette, actor, request) jump_items_sql(datasette, actor, request) Action hooks table_actions(datasette, actor, database, table, request) view_actions(datasette, actor, database, view, request) query_actions(datasette, actor, database, query_name, request, sql, params) row_actions(datasette, actor, request, database, table, row) database_actions(datasette, actor, database, request) homepage_actions(datasette, actor, request) Template slots top_homepage(datasette, request) top_database(datasette, request, database) top_table(datasette, request, database, table) top_row(datasette, request, database, table, row) top_query(datasette, request, database, sql) top_stored_query(datasette, request, database, query_name) Event tracking track_event(datasette, event) register_events(datasette) register_token_handler(datasette)",[],"[{""href"": ""https://pluggy.readthedocs.io/"", ""label"": ""pluggy""}]" plugin_hooks:permission-plugin-examples,plugin_hooks,permission-plugin-examples,Permission plugin examples,"These snippets show how to use the new permission_resources_sql hook to contribute rows to the action-based permission resolver. Each hook receives the current actor dictionary (or None ) and must return None or an instance or list of datasette.permissions.PermissionSQL (or a coroutine that resolves to that).","[""Plugin hooks"", ""permission_resources_sql(datasette, actor, action)""]",[] plugin_hooks:plugin-actions,plugin_hooks,plugin-actions,Action hooks,"Action hooks can be used to add items to the action menus that appear at the top of different pages within Datasette. Unlike menu_links() , actions which are displayed on every page, actions should only be relevant to the page the user is currently viewing. Each of these hooks should return a list of menu items, with optional ""description"": ""..."" keys describing each action in more detail. The most common action item is a link to another page: { ""href"": datasette.urls.path(""/-/custom-action""), ""label"": ""Custom action"", ""description"": ""Run this action on a separate page."", } Plugins can also return button actions for JavaScript-backed interactions: { ""type"": ""button"", ""label"": ""Open custom dialog"", ""description"": ""Show a dialog without leaving this page."", ""attrs"": { ""aria-label"": ""Open custom dialog"", ""data-plugin-action"": ""open-custom-dialog"", }, } These are rendered as