{"ok": true, "next": null, "next_url": null, "rows": [{"id": "authentication:allowdebugview", "page": "authentication", "ref": "allowdebugview", "title": "The /-/allow-debug tool", "content": "The  /-/allow-debug  tool lets you try out different   \"action\"  blocks against different  \"actor\"  JSON objects. You can try that out here:  https://latest.datasette.io/-/allow-debug", "breadcrumbs": "[\"Authentication and permissions\", \"Permissions\"]", "references": "[{\"href\": \"https://latest.datasette.io/-/allow-debug\", \"label\": \"https://latest.datasette.io/-/allow-debug\"}]"}, {"id": "authentication:authentication-default-deny", "page": "authentication", "ref": "authentication-default-deny", "title": "Denying all permissions by default", "content": "By default, Datasette allows unauthenticated access to view databases, tables, and execute SQL queries. \n                 You may want to run Datasette in a mode where  all  access is denied by default, and you explicitly grant permissions only to authenticated users, either using the  --root mechanism  or through  configuration file rules  or plugins. \n                 Use the  --default-deny  command-line option to run Datasette in this mode: \n                 datasette --default-deny data.db --root \n                 With  --default-deny  enabled: \n                 \n                     \n                         Anonymous users are denied access to view the instance, databases, tables, and queries \n                     \n                     \n                         Authenticated users are also denied access unless they're explicitly granted permissions \n                     \n                     \n                         The root user (when using  --root ) still has access to everything \n                     \n                     \n                         You can grant permissions using  configuration file rules  or plugins \n                     \n                 \n                 For example, to allow only a specific user to access your instance: \n                 datasette --default-deny data.db --config datasette.yaml \n                 Where  datasette.yaml  contains: \n                 allow:\n  id: alice \n                 This configuration will deny access to everyone except the user with  id  of  alice .", "breadcrumbs": "[\"Authentication and permissions\", \"Permissions\"]", "references": "[]"}, {"id": "authentication:authentication-permissions-allow", "page": "authentication", "ref": "authentication-permissions-allow", "title": "Defining permissions with \"allow\" blocks", "content": "One way to define permissions in Datasette is to use an  \"allow\"  block  in the datasette.yaml file . This is a JSON document describing which actors are allowed to perform an action against a specific resource. \n                 Each  allow  block is compiled into SQL and combined with any\n                     plugin-provided rules  to produce\n                    the cascading allow/deny decisions that power  await .allowed(*, action, resource, actor=None) . \n                 The most basic form of allow block is this ( allow demo ,  deny demo ): \n                 [[[cog\nfrom metadata_doc import config_example\nimport textwrap\nconfig_example(cog, textwrap.dedent(\n  \"\"\"\n    allow:\n      id: root\n    \"\"\").strip(),\n    \"YAML\", \"JSON\"\n  ) \n                 ]]] \n                 [[[end]]] \n                 This will match any actors with an  \"id\"  property of  \"root\"  - for example, an actor that looks like this: \n                 {\n    \"id\": \"root\",\n    \"name\": \"Root User\"\n} \n                 An allow block can specify \"deny all\" using  false  ( demo ): \n                 [[[cog\nfrom metadata_doc import config_example\nimport textwrap\nconfig_example(cog, textwrap.dedent(\n  \"\"\"\n    allow: false\n    \"\"\").strip(),\n    \"YAML\", \"JSON\"\n  ) \n                 ]]] \n                 [[[end]]] \n                 An  \"allow\"  of  true  allows all access ( demo ): \n                 [[[cog\nfrom metadata_doc import config_example\nimport textwrap\nconfig_example(cog, textwrap.dedent(\n  \"\"\"\n    allow: true\n    \"\"\").strip(),\n    \"YAML\", \"JSON\"\n  ) \n                 ]]] \n                 [[[end]]] \n                 Allow keys can provide a list of values. These will match any actor that has any of those values ( allow demo ,  deny demo ): \n                 [[[cog\nfrom metadata_doc import config_example\nimport textwrap\nconfig_example(cog, textwrap.dedent(\n  \"\"\"\n    allow:\n      id:\n      - simon\n      - cleopaws\n    \"\"\").strip(),\n    \"YAML\", \"JSON\"\n  ) \n                 ]]] \n                 [[[end]]] \n                 This will match any actor with an  \"id\"  of either  \"simon\"  or  \"cleopaws\" . \n                 Actors can have properties that feature a list of values. These will be matched against the list of values in an allow block. Consider the following actor: \n                 {\n    \"id\": \"simon\",\n    \"roles\": [\"staff\", \"developer\"]\n} \n                 This allow block will provide access to any actor that has  \"developer\"  as one of their roles ( allow demo ,  deny demo ): \n                 [[[cog\nfrom metadata_doc import config_example\nimport textwrap\nconfig_example(cog, textwrap.dedent(\n  \"\"\"\n    allow:\n      roles:\n      - developer\n    \"\"\").strip(),\n    \"YAML\", \"JSON\"\n  ) \n                 ]]] \n                 [[[end]]] \n                 Note that \"roles\" is not a concept that is baked into Datasette - it's a convention that plugins can choose to implement and act on. \n                 If you want to provide access to any actor with a value for a specific key, use  \"*\" . For example, to match any logged-in user specify the following ( allow demo ,  deny demo ): \n                 [[[cog\nfrom metadata_doc import config_example\nimport textwrap\nconfig_example(cog, textwrap.dedent(\n  \"\"\"\n    allow:\n      id: \"*\"\n    \"\"\").strip(),\n    \"YAML\", \"JSON\"\n  ) \n                 ]]] \n                 [[[end]]] \n                 You can specify that only unauthenticated actors (from anonymous HTTP requests) should be allowed access using the special  \"unauthenticated\": true  key in an allow block ( allow demo ,  deny demo ): \n                 [[[cog\nfrom metadata_doc import config_example\nimport textwrap\nconfig_example(cog, textwrap.dedent(\n  \"\"\"\n    allow:\n      unauthenticated: true\n    \"\"\").strip(),\n    \"YAML\", \"JSON\"\n  ) \n                 ]]] \n                 [[[end]]] \n                 Allow keys act as an \"or\" mechanism. An actor will be able to execute the query if any of their JSON properties match any of the values in the corresponding lists in the  allow  block. The following block will allow users with either a  role  of  \"ops\"  OR users who have an  id  of  \"simon\"  or  \"cleopaws\" : \n                 [[[cog\nfrom metadata_doc import config_example\nimport textwrap\nconfig_example(cog, textwrap.dedent(\n  \"\"\"\n    allow:\n      id:\n      - simon\n      - cleopaws\n      role: ops\n    \"\"\").strip(),\n    \"YAML\", \"JSON\"\n  ) \n                 ]]] \n                 [[[end]]] \n                 Demo for cleopaws ,  demo for ops role ,  demo for an actor matching neither rule .", "breadcrumbs": "[\"Authentication and permissions\", \"Permissions\"]", "references": "[{\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%22id%22%3A+%22root%22%7D&allow=%7B%0D%0A++++++++%22id%22%3A+%22root%22%0D%0A++++%7D\", \"label\": \"allow demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%22id%22%3A+%22trevor%22%7D&allow=%7B%0D%0A++++++++%22id%22%3A+%22root%22%0D%0A++++%7D\", \"label\": \"deny demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22root%22%0D%0A%7D&allow=false\", \"label\": \"demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22root%22%0D%0A%7D&allow=true\", \"label\": \"demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22cleopaws%22%0D%0A%7D&allow=%7B%0D%0A++++%22id%22%3A+%5B%0D%0A++++++++%22simon%22%2C%0D%0A++++++++%22cleopaws%22%0D%0A++++%5D%0D%0A%7D\", \"label\": \"allow demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22pancakes%22%0D%0A%7D&allow=%7B%0D%0A++++%22id%22%3A+%5B%0D%0A++++++++%22simon%22%2C%0D%0A++++++++%22cleopaws%22%0D%0A++++%5D%0D%0A%7D\", \"label\": \"deny demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22simon%22%2C%0D%0A++++%22roles%22%3A+%5B%0D%0A++++++++%22staff%22%2C%0D%0A++++++++%22developer%22%0D%0A++++%5D%0D%0A%7D&allow=%7B%0D%0A++++%22roles%22%3A+%5B%0D%0A++++++++%22developer%22%0D%0A++++%5D%0D%0A%7D\", \"label\": \"allow demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22cleopaws%22%2C%0D%0A++++%22roles%22%3A+%5B%22dog%22%5D%0D%0A%7D&allow=%7B%0D%0A++++%22roles%22%3A+%5B%0D%0A++++++++%22developer%22%0D%0A++++%5D%0D%0A%7D\", \"label\": \"deny demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22simon%22%0D%0A%7D&allow=%7B%0D%0A++++%22id%22%3A+%22*%22%0D%0A%7D\", \"label\": \"allow demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22bot%22%3A+%22readme-bot%22%0D%0A%7D&allow=%7B%0D%0A++++%22id%22%3A+%22*%22%0D%0A%7D\", \"label\": \"deny demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=null&allow=%7B%0D%0A++++%22unauthenticated%22%3A+true%0D%0A%7D\", \"label\": \"allow demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22hello%22%0D%0A%7D&allow=%7B%0D%0A++++%22unauthenticated%22%3A+true%0D%0A%7D\", \"label\": \"deny demo\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22cleopaws%22%0D%0A%7D&allow=%7B%0D%0A++++%22id%22%3A+%5B%0D%0A++++++++%22simon%22%2C%0D%0A++++++++%22cleopaws%22%0D%0A++++%5D%2C%0D%0A++++%22role%22%3A+%22ops%22%0D%0A%7D\", \"label\": \"Demo for cleopaws\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22trevor%22%2C%0D%0A++++%22role%22%3A+%5B%0D%0A++++++++%22ops%22%2C%0D%0A++++++++%22staff%22%0D%0A++++%5D%0D%0A%7D&allow=%7B%0D%0A++++%22id%22%3A+%5B%0D%0A++++++++%22simon%22%2C%0D%0A++++++++%22cleopaws%22%0D%0A++++%5D%2C%0D%0A++++%22role%22%3A+%22ops%22%0D%0A%7D\", \"label\": \"demo for ops role\"}, {\"href\": \"https://latest.datasette.io/-/allow-debug?actor=%7B%0D%0A++++%22id%22%3A+%22percy%22%2C%0D%0A++++%22role%22%3A+%5B%0D%0A++++++++%22staff%22%0D%0A++++%5D%0D%0A%7D&allow=%7B%0D%0A++++%22id%22%3A+%5B%0D%0A++++++++%22simon%22%2C%0D%0A++++++++%22cleopaws%22%0D%0A++++%5D%2C%0D%0A++++%22role%22%3A+%22ops%22%0D%0A%7D\", \"label\": \"demo for an actor matching neither rule\"}]"}, {"id": "authentication:authentication-permissions-explained", "page": "authentication", "ref": "authentication-permissions-explained", "title": "How permissions are resolved", "content": "Permission rules describe an effect ( allow  or  deny ) at one of three levels: \n                 \n                     \n                         resource \n                         \n                             A specific child resource, such as the  analytics/sales  table. \n                         \n                     \n                     \n                         parent \n                         \n                             A parent resource, such as the  analytics  database. A parent rule also applies to its child resources. \n                         \n                     \n                     \n                         global \n                         \n                             Every resource for that action. \n                         \n                     \n                 \n                 Datasette resolves matching rules from most specific to least specific: \n                 \n                     \n                         Resource rules take precedence over parent and global rules. \n                     \n                     \n                         Parent rules take precedence over global rules. \n                     \n                     \n                         If both allow and deny rules match at the same level, deny takes precedence. \n                     \n                     \n                         If no rule matches, access is denied. \n                     \n                 \n                 This means a resource-level allow can provide an exception to a parent-level deny. It also means that two plugins which disagree at the same level resolve to deny. \n                 \n                     Permission rule examples \n                     \n                         \n                         \n                         \n                         \n                             \n                                 \n                                     Matching rules \n                                 \n                                 \n                                     Result \n                                 \n                                 \n                                     Explanation \n                                 \n                             \n                         \n                         \n                             \n                                 \n                                     Global allow \n                                 \n                                 \n                                     Allow \n                                 \n                                 \n                                     The global rule is the most specific matching rule. \n                                 \n                             \n                             \n                                 \n                                     Global allow, parent deny \n                                 \n                                 \n                                     Deny \n                                 \n                                 \n                                     The parent rule is more specific. \n                                 \n                             \n                             \n                                 \n                                     Parent deny, resource allow \n                                 \n                                 \n                                     Allow \n                                 \n                                 \n                                     The resource rule is more specific. \n                                 \n                             \n                             \n                                 \n                                     Resource allow and resource deny \n                                 \n                                 \n                                     Deny \n                                 \n                                 \n                                     Deny takes precedence at the same level. \n                                 \n                             \n                             \n                                 \n                                     No matching rules \n                                 \n                                 \n                                     Deny \n                                 \n                                 \n                                     Permissions default to deny when no rule applies. \n                                 \n                             \n                         \n                     \n                 \n                 The built-in public defaults are global allow rules for actions such as  view-instance ,  view-database  and  view-table . They follow the same precedence rules as configuration and plugin rules. The  --default-deny  option prevents Datasette from contributing those default allow rules. \n                 Datasette performs checks using  await .allowed(*, action, resource, actor=None) , which accepts keyword arguments for  action ,  resource  and an optional  actor . \n                 resource  should be an instance of the appropriate  Resource  subclass from  datasette.resources \u2014for example  InstanceResource() ,  DatabaseResource(database=\"... )`` or  TableResource(database=\"...\", table=\"...\") . This defaults to  InstanceResource()  if not specified. \n                 When a check runs Datasette gathers allow/deny rules from multiple sources and\n                    compiles them into a SQL query. The resulting query describes all of the\n                    resources an actor may access for that action, together with the reasons those\n                    resources were allowed or denied. The combined sources are: \n                 \n                     \n                         allow  blocks configured in  datasette.yaml . \n                     \n                     \n                         Actor restrictions  encoded into the actor dictionary or API token. \n                     \n                     \n                         The \"root\" user rule when  --root  (or  Datasette.root_enabled ) is active. This is a global allow rule, so a more specific configuration deny can override it. \n                     \n                     \n                         Any additional SQL provided by plugins implementing  permission_resources_sql(datasette, actor, action) . \n                     \n                 \n                 Actor restrictions are applied after the allow/deny rules. They act as an additional allowlist: a restriction can remove access but cannot grant access that the actor did not already have. See  Restricting the actions that a token can perform . \n                 Some actions have dependencies on other actions. These are evaluated as an  AND  condition. For example,  execute-sql  also requires  view-database : both decisions must be allowed for the final result to be allowed.", "breadcrumbs": "[\"Authentication and permissions\", \"Permissions\"]", "references": "[]"}], "truncated": false}