{"html_url": "https://github.com/simonw/datasette/issues/1947#issuecomment-1350037572", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1947", "id": 1350037572, "node_id": "IC_kwDOBm6k_c5Qd_BE", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T23:27:32Z", "updated_at": "2022-12-13T23:27:32Z", "author_association": "OWNER", "body": "I'm going to ignore the permissions issue for the moment - I'll allow people to select any permissions they like in any of the databases or tables that are visible to them (don't want to leak the existence of databases/tables to users who shouldn't be able to see them).\r\n\r\nI think the value of getting this working outweights any potential confusion from not using finely grained permission checks to decide if the user should be able to apply a permission or not.\r\n\r\nThe tokens themselves won't be able to perform `insert-row` or similar if the user doesn't have the ability to do that, even if they selected that checkbox.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1493390939, "label": "UI to create reduced scope tokens from the `/-/create-token` page"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1947#issuecomment-1350019528", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1947", "id": 1350019528, "node_id": "IC_kwDOBm6k_c5Qd6nI", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T23:19:16Z", "updated_at": "2022-12-13T23:19:16Z", "author_association": "OWNER", "body": "Here's the checkbox prototype:\r\n```diff\r\ndiff --git a/datasette/templates/create_token.html b/datasette/templates/create_token.html\r\nindex a94881ed..1795ebaf 100644\r\n--- a/datasette/templates/create_token.html\r\n+++ b/datasette/templates/create_token.html\r\n@@ -2,11 +2,20 @@\r\n \r\n {% block title %}Create an API token{% endblock %}\r\n \r\n+{% block extra_head %}\r\n+\r\n+{% endblock %}\r\n+\r\n {% block content %}\r\n \r\n

Create an API token

\r\n \r\n-

This token will allow API access with the same abilities as your current user.

\r\n+

This token will allow API access with the same abilities as your current user, {{ request.actor.id }}

\r\n \r\n {% if errors %}\r\n {% for error in errors %}\r\n@@ -27,8 +36,39 @@\r\n \r\n \r\n \r\n- \r\n+\r\n+
\r\n+ Restrict actions that can be performed using this token\r\n+

All databases and tables

\r\n+ \r\n+\r\n+ {% for database in databases %}\r\n+

All tables in database: {{ database }}

\r\n+ \r\n+ {% endfor %}\r\n+

Specific tables

\r\n+ {% for dbt in database_with_tables %}\r\n+ {% for table in dbt.tables %}\r\n+

{{ dbt.database }}: {{ table }}

\r\n+ \r\n+ {% endfor %}\r\n+ {% endfor %}\r\n+
\r\n+\r\n \r\n+\r\n \r\n {% if token %}\r\n
\r\ndiff --git a/datasette/views/special.py b/datasette/views/special.py\r\nindex 30345d14..48357f87 100644\r\n--- a/datasette/views/special.py\r\n+++ b/datasette/views/special.py\r\n@@ -231,12 +231,37 @@ class CreateTokenView(BaseView):\r\n return await self.render(\r\n [\"create_token.html\"],\r\n request,\r\n- {\"actor\": request.actor},\r\n+ {\r\n+ \"actor\": request.actor,\r\n+ \"all_permissions\": self.ds.permissions.keys(),\r\n+ \"database_permissions\": [\r\n+ key\r\n+ for key, value in self.ds.permissions.items()\r\n+ if value.takes_database\r\n+ ],\r\n+ \"table_permissions\": [\r\n+ key\r\n+ for key, value in self.ds.permissions.items()\r\n+ if value.takes_resource\r\n+ ],\r\n+ \"databases\": [k for k in self.ds.databases.keys() if k != \"_internal\"],\r\n+ \"database_with_tables\": [\r\n+ {\r\n+ \"database\": db.name,\r\n+ \"tables\": await db.table_names(),\r\n+ }\r\n+ for db in self.ds.databases.values()\r\n+ if db.name != \"_internal\"\r\n+ ],\r\n+ },\r\n )\r\n \r\n async def post(self, request):\r\n self.check_permission(request)\r\n post = await request.post_vars()\r\n+ from pprint import pprint\r\n+\r\n+ pprint(post)\r\n errors = []\r\n duration = None\r\n if post.get(\"expire_type\"):\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1493390939, "label": "UI to create reduced scope tokens from the `/-/create-token` page"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1947#issuecomment-1350013016", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1947", "id": 1350013016, "node_id": "IC_kwDOBm6k_c5Qd5BY", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T23:16:24Z", "updated_at": "2022-12-13T23:17:17Z", "author_association": "OWNER", "body": "Slightly tricky thing here is that it should only show permissions that the user themselves has - on databases and tables that they have permission to access.\r\n\r\nI have a nasty feeling this may require looping through _everything_ and running every permission check, which could get very expensive if there are plugins involved that do their own storage check to resolve a permission.\r\n\r\nIt's that classic permission system problem: how to efficiently iterate through everything the user has permission to do in one go?\r\n\r\nMight be that I have to punt on that, and show the user a list of permissions to select that they might not actually have ability for.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1493390939, "label": "UI to create reduced scope tokens from the `/-/create-token` page"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1947#issuecomment-1350008636", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1947", "id": 1350008636, "node_id": "IC_kwDOBm6k_c5Qd388", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T23:14:33Z", "updated_at": "2022-12-13T23:14:33Z", "author_association": "OWNER", "body": "Checkbox interface looks like this. It's not beautiful but it's good enough for the moment:\r\n\r\n\"image\"\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1493390939, "label": "UI to create reduced scope tokens from the `/-/create-token` page"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1947#issuecomment-1350002434", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1947", "id": 1350002434, "node_id": "IC_kwDOBm6k_c5Qd2cC", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T23:11:50Z", "updated_at": "2022-12-13T23:11:59Z", "author_association": "OWNER", "body": "I think checkboxes will work well.\r\n\r\nHere's the data I get back from them (as `post_vars()`):\r\n\r\n```\r\n{'all:debug-menu': 'on',\r\n 'all:insert-row': 'on',\r\n 'expire_duration': '',\r\n 'expire_type': '',\r\n 'table:fixtures:delete-row': 'on',\r\n 'table:fixtures:drop-table': 'on',\r\n 'table:fixtures:view-query': 'on'}\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1493390939, "label": "UI to create reduced scope tokens from the `/-/create-token` page"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1947#issuecomment-1349975255", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1947", "id": 1349975255, "node_id": "IC_kwDOBm6k_c5QdvzX", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T23:00:11Z", "updated_at": "2022-12-13T23:00:11Z", "author_association": "OWNER", "body": "My `\r\n \r\n
\r\n+\r\n+
\r\n+ Restrict actions that can be performed using this token\r\n+

Restrict actions that can be performed using this token:

\r\n+

All databases and tables:

\r\n+

\r\n+
\r\n+\r\n \r\n \r\n {% if token %}\r\ndiff --git a/datasette/views/special.py b/datasette/views/special.py\r\nindex 30345d14..9d0fcd31 100644\r\n--- a/datasette/views/special.py\r\n+++ b/datasette/views/special.py\r\n@@ -231,7 +231,17 @@ class CreateTokenView(BaseView):\r\n return await self.render(\r\n [\"create_token.html\"],\r\n request,\r\n- {\"actor\": request.actor},\r\n+ {\r\n+ \"actor\": request.actor,\r\n+ \"all_permissions\": self.ds.permissions.keys(),\r\n+ \"database_permissions\": [key for key, value in self.ds.permissions.items() if value.takes_database],\r\n+ \"table_permissions\": [key for key, value in self.ds.permissions.items() if value.takes_resource],\r\n+ \"databases\": self.ds.databases.keys(),\r\n+ \"database_with_tables\": [{\r\n+ \"database\": db.name,\r\n+ \"tables\": await db.table_names(),\r\n+ } for db in self.ds.databases.values()],\r\n+ },\r\n )\r\n \r\n async def post(self, request):\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1493390939, "label": "UI to create reduced scope tokens from the `/-/create-token` page"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1947#issuecomment-1349974287", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1947", "id": 1349974287, "node_id": "IC_kwDOBm6k_c5QdvkP", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T22:59:44Z", "updated_at": "2022-12-13T22:59:44Z", "author_association": "OWNER", "body": "Got an option group thing working:\r\n\r\n\"image\"\r\n\r\nBut... it strikes me that any time you're considering a `` for this.\r\n\r\nThe usability for keyboards is still pretty awful, but it's a niche enough feature that maybe that's OK for the moment?\r\n\r\n```javascript\r\nvar select = document.querySelector('select');\r\nvar selected = Array.from(temp0.options).filter(o => o.selected).map(o => o.value) \r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1493390939, "label": "UI to create reduced scope tokens from the `/-/create-token` page"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1947#issuecomment-1347768549", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1947", "id": 1347768549, "node_id": "IC_kwDOBm6k_c5QVVDl", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T05:25:56Z", "updated_at": "2022-12-13T22:29:12Z", "author_association": "OWNER", "body": "- [x] I should add a `--database` example to that help text.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1493390939, "label": "UI to create reduced scope tokens from the `/-/create-token` page"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1947#issuecomment-1347768328", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1947", "id": 1347768328, "node_id": "IC_kwDOBm6k_c5QVVAI", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T05:25:31Z", "updated_at": "2022-12-13T22:25:46Z", "author_association": "OWNER", "body": "https://latest.datasette.io/-/create-token currently looks like this:\n\n\n![Image](https://user-images.githubusercontent.com/9599/207458002-7c46940b-22c0-45d3-a668-ec7f1082588c.png)\n\n\nAs a reminder, the CLI options that this needs to provide an alternative to are:\n\nhttps://github.com/simonw/datasette/blob/d4b98d3924dec625a99236e65b1b169ff957381f/docs/cli-reference.rst#L619-L638", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1493390939, "label": "UI to create reduced scope tokens from the `/-/create-token` page"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1950#issuecomment-1349864950", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1950", "id": 1349864950, "node_id": "IC_kwDOBm6k_c5QdU32", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T22:11:15Z", "updated_at": "2022-12-13T22:11:15Z", "author_association": "OWNER", "body": "Most places I use that exception at the moment set their own non-500 status error:\n```\ndatasette % rg DatasetteError\ndatasette/handle_exception.py\n7:from .views.base import DatasetteError\n33: elif isinstance(exception, DatasetteError):\n\ndatasette/filters.py\n2:from datasette.views.base import DatasetteError\n22: raise DatasetteError(\"_where= is not allowed\", status=403)\n141: raise DatasetteError(\n\ndatasette/views/table.py\n34:from .base import BaseView, DataView, DatasetteError, ureg, _error\n178: raise DatasetteError(\n192: raise DatasetteError(\n390: raise DatasetteError(\"Cannot use _sort and _sort_desc at the same time\")\n394: raise DatasetteError(f\"Cannot sort table by {sort}\")\n400: raise DatasetteError(f\"Cannot sort table by {sort_desc}\")\n\ndatasette/views/base.py\n39:class DatasetteError(Exception):\n219: raise DatasetteError(str(e), title=\"Invalid SQL\", status=400)\n222: raise DatasetteError(str(e))\n224: except DatasetteError:\n382: raise DatasetteError(\n402: raise DatasetteError(str(e), title=\"Invalid SQL\", status=400)\n405: raise DatasetteError(str(e))\n407: except DatasetteError:\n\ndatasette/views/table2.py\n28:from .base import DataView, DatasetteError, ureg\n296: raise DatasetteError(\n310: raise DatasetteError(\n472: raise DatasetteError(\"Cannot use _sort and _sort_desc at the same time\")\n476: raise DatasetteError(f\"Cannot sort table by {sort}\")\n482: raise DatasetteError(f\"Cannot sort table by {sort_desc}\")\n\ndatasette/views/database.py\n31:from .base import BaseView, DatasetteError, DataView, _error\n188: raise DatasetteError(\"Invalid database\", status=404)\n190: raise DatasetteError(\"Cannot download in-memory databases\", status=404)\n194: raise DatasetteError(\"Cannot download database\", status=404)\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1495241162, "label": "Bad ?_sort returns a 500 error, should be a 400"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1950#issuecomment-1349855620", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1950", "id": 1349855620, "node_id": "IC_kwDOBm6k_c5QdSmE", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T22:08:50Z", "updated_at": "2022-12-13T22:08:50Z", "author_association": "OWNER", "body": "https://github.com/simonw/datasette/blob/d4b98d3924dec625a99236e65b1b169ff957381f/datasette/views/table.py#L392-L400", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1495241162, "label": "Bad ?_sort returns a 500 error, should be a 400"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1958#issuecomment-1352644267", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1958", "id": 1352644267, "node_id": "IC_kwDOBm6k_c5Qn7ar", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T18:33:32Z", "updated_at": "2022-12-13T18:33:32Z", "author_association": "OWNER", "body": "When you run `--root` you need to follow the special link that gets output to the console:\r\n\r\n```\r\n% datasette --root\r\nhttp://127.0.0.1:8001/-/auth-token?token=036d8055cc8000e9667f21c1dd08722a9358c066463873ad9566d23d88765c52\r\nINFO: Started server process [53934]\r\nINFO: Waiting for application startup.\r\nINFO: Application startup complete.\r\n```\r\nThat `/-/auth-token?...` link is the one that sets the cookie and lets you in.", "reactions": "{\"total_count\": 1, \"+1\": 1, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1497909798, "label": "datasette --root running in Docker doesn't reliably show the magic URL"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1958#issuecomment-1352644262", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1958", "id": 1352644262, "node_id": "IC_kwDOBm6k_c5Qn7am", "user": {"value": 11729897, "label": "davidhaley"}, "created_at": "2022-12-13T16:49:31Z", "updated_at": "2022-12-13T16:49:52Z", "author_association": "NONE", "body": "I may have found the reason. I don't think the `--root` option is taking effect.\r\n\r\nVisited: http://127.0.0.1:8001/-/permissions\r\n\r\n![image](https://user-images.githubusercontent.com/11729897/207394127-59f8320f-3410-4ff8-869d-b19ab955d67c.png)", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1497909798, "label": "datasette --root running in Docker doesn't reliably show the magic URL"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1914#issuecomment-1347801679", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1914", "id": 1347801679, "node_id": "IC_kwDOBm6k_c5QVdJP", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T06:15:54Z", "updated_at": "2022-12-13T06:15:54Z", "author_association": "OWNER", "body": "Should make sure that every API that returns an object as the top level (that's almost all of them) includes `\"ok\": true` to indicate no errors.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1468689139, "label": "Finalize design of JSON for Datasette 1.0"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1947#issuecomment-1347775760", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1947", "id": 1347775760, "node_id": "IC_kwDOBm6k_c5QVW0Q", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T05:38:47Z", "updated_at": "2022-12-13T05:38:47Z", "author_association": "OWNER", "body": "I'm going to hide the options for reducing the scope of the token inside a details/summary element.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1493390939, "label": "UI to create reduced scope tokens from the `/-/create-token` page"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1937#issuecomment-1347770871", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1937", "id": 1347770871, "node_id": "IC_kwDOBm6k_c5QVVn3", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T05:30:43Z", "updated_at": "2022-12-13T05:30:43Z", "author_association": "OWNER", "body": "Also you should need `update-row` permission to use the `\"replace\": true` option - I should add that rule to `/-/insert` add well.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1483320357, "label": "/db/-/create API should require insert-rows permission to use row: or rows: option"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1938#issuecomment-1347767048", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1938", "id": 1347767048, "node_id": "IC_kwDOBm6k_c5QVUsI", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T05:23:18Z", "updated_at": "2022-12-13T05:23:18Z", "author_association": "OWNER", "body": "I landed this already:\r\n- #1636 ", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1485488236, "label": "\"permissions\" blocks in metadata.json/yaml"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1948#issuecomment-1347766530", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1948", "id": 1347766530, "node_id": "IC_kwDOBm6k_c5QVUkC", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T05:22:19Z", "updated_at": "2022-12-13T05:22:19Z", "author_association": "OWNER", "body": "I tested:\r\n\r\n```\r\n{\"id\": \"root\", \"_r\": {\"a\": \"view-table\"}}\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1493404423, "label": "500 error on permission debug page when testing actors with _r"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1855#issuecomment-1347761892", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1855", "id": 1347761892, "node_id": "IC_kwDOBm6k_c5QVTbk", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T05:14:25Z", "updated_at": "2022-12-13T05:14:25Z", "author_association": "OWNER", "body": "New documentation: https://docs.datasette.io/en/latest/authentication.html#restricting-the-actions-that-a-token-can-perform", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1423336089, "label": "`datasette create-token` ability to create tokens with a reduced set of permissions"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1947#issuecomment-1347760109", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1947", "id": 1347760109, "node_id": "IC_kwDOBm6k_c5QVS_t", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T05:12:00Z", "updated_at": "2022-12-13T05:12:00Z", "author_association": "OWNER", "body": "For the UI: I think I'm going to dump a whole bunch of form elements on the page (so you can set up to 3 of each category of limit without any JavaScript), then add JavaScript that hides all but one of the options and gives you a \"add another\" widget that adds multiple more.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1493390939, "label": "UI to create reduced scope tokens from the `/-/create-token` page"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1855#issuecomment-1347759522", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1855", "id": 1347759522, "node_id": "IC_kwDOBm6k_c5QVS2i", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T05:11:43Z", "updated_at": "2022-12-13T05:11:43Z", "author_association": "OWNER", "body": "Decided to do the `/-/create-token` UI in a separate ticket:\r\n- #1947", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1423336089, "label": "`datasette create-token` ability to create tokens with a reduced set of permissions"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1946#issuecomment-1347733217", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1946", "id": 1347733217, "node_id": "IC_kwDOBm6k_c5QVMbh", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T04:28:45Z", "updated_at": "2022-12-13T04:28:45Z", "author_association": "OWNER", "body": "Demo of the new feature:\r\n```\r\n% datasette create-token --secret s root\r\ndstok_eyJhIjoicm9vdCIsInRva2VuIjoiZHN0b2siLCJ0IjoxNjcwOTA1NjgwfQ.pqSWOwCSNp678hEWl9l5o7m1GaM\r\n% datasette --get /-/actor.json\r\n{\"actor\": null}\r\n% DATASETTE_SECRET=s datasette --get /-/actor.json --token dstok_eyJhIjoicm9vdCIsInRva2VuIjoiZHN0b2siLCJ0IjoxNjcwOTA1NjgwfQ.pqSWOwCSNp678hEWl9l5o7m1GaM\r\n{\"actor\": {\"id\": \"root\", \"token\": \"dstok\"}}\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1493339206, "label": "`datasette --get` mechanism for sending tokens"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1946#issuecomment-1347732039", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1946", "id": 1347732039, "node_id": "IC_kwDOBm6k_c5QVMJH", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T04:26:20Z", "updated_at": "2022-12-13T04:26:20Z", "author_association": "OWNER", "body": "Two options:\r\n\r\n- `--header \"Authorization: Bearer XXX\"` which can be used to send any headers\r\n- `--token XXX` to specify the token, which is then sent using that header\r\n\r\nI like the second option more, simply because there are currently no other headers that affect how Datasette works. `--token` feels obvious and easy to use.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1493339206, "label": "`datasette --get` mechanism for sending tokens"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1855#issuecomment-1347731288", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1855", "id": 1347731288, "node_id": "IC_kwDOBm6k_c5QVL9Y", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T04:24:50Z", "updated_at": "2022-12-13T04:24:50Z", "author_association": "OWNER", "body": "For the tests for `datasette create-token` it would be useful if `datasette --get` had a mechanism for sending an `Authorization: Bearer X` header.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1423336089, "label": "`datasette create-token` ability to create tokens with a reduced set of permissions"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1855#issuecomment-1347726302", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1855", "id": 1347726302, "node_id": "IC_kwDOBm6k_c5QVKve", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T04:16:26Z", "updated_at": "2022-12-13T04:16:26Z", "author_association": "OWNER", "body": "I'm going to move this code into `datasette/cli.py` - it's a bit unexpected having it live in `default_permissions.py` like this (I couldn't find the code when I went looking for it earlier).", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1423336089, "label": "`datasette create-token` ability to create tokens with a reduced set of permissions"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1855#issuecomment-1347707683", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1855", "id": 1347707683, "node_id": "IC_kwDOBm6k_c5QVGMj", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T03:55:35Z", "updated_at": "2022-12-13T04:15:27Z", "author_association": "OWNER", "body": "Help looks like this:\r\n\r\n```\r\nUsage: datasette create-token [OPTIONS] ID\r\n\r\n Create a signed API token for the specified actor ID\r\n\r\n Example:\r\n\r\n datasette create-token root --secret mysecret\r\n\r\n To only allow create-table:\r\n\r\n datasette create-token root --secret mysecret \\\r\n --all create-table\r\n\r\n Or to only allow insert-row against a specific table:\r\n\r\n datasette create-token root --secret myscret \\\r\n --resource mydb mytable insert-row\r\n\r\n Restricted actions can be specified multiple times using multiple --all,\r\n --database, and --resource options.\r\n\r\n Add --debug to see a decoded version of the token.\r\n\r\nOptions:\r\n --secret TEXT Secret used for signing the API tokens\r\n [required]\r\n -e, --expires-after INTEGER Token should expire after this many seconds\r\n -a, --all ACTION Restrict token to this action\r\n -d, --database DB ACTION Restrict token to this action on this\r\n database\r\n -r, --resource DB RESOURCE ACTION\r\n Restrict token to this action on this\r\n database resource (a table, SQL view or\r\n named query)\r\n --debug Show decoded token\r\n --plugins-dir DIRECTORY Path to directory containing custom plugins\r\n --help Show this message and exit.\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1423336089, "label": "`datasette create-token` ability to create tokens with a reduced set of permissions"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1855#issuecomment-1347695728", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1855", "id": 1347695728, "node_id": "IC_kwDOBm6k_c5QVDRw", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T03:30:09Z", "updated_at": "2022-12-13T03:30:09Z", "author_association": "OWNER", "body": "I just noticed this in the existing code:\r\n\r\nhttps://github.com/simonw/datasette/blob/c5d30b58a1cd1c66bbddcf3561db005543ecaf25/datasette/default_permissions.py#L195-L203\r\n\r\nHard-coding those action names should not be necessary any more, especially now we have `datasette.permissions` for looking up metadata about the permissions.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1423336089, "label": "`datasette create-token` ability to create tokens with a reduced set of permissions"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1855#issuecomment-1347694871", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1855", "id": 1347694871, "node_id": "IC_kwDOBm6k_c5QVDEX", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T03:28:15Z", "updated_at": "2022-12-13T03:28:15Z", "author_association": "OWNER", "body": "Initial prototype of the `create-token` command changes:\r\n\r\n```diff\r\ndiff --git a/datasette/default_permissions.py b/datasette/default_permissions.py\r\nindex 406dae40..bbe1247e 100644\r\n--- a/datasette/default_permissions.py\r\n+++ b/datasette/default_permissions.py\r\n@@ -278,17 +278,55 @@ def register_commands(cli):\r\n help=\"Token should expire after this many seconds\",\r\n type=int,\r\n )\r\n+ @click.option(\r\n+ \"alls\",\r\n+ \"-a\",\r\n+ \"--all\",\r\n+ type=str,\r\n+ multiple=True,\r\n+ help=\"Restrict token to this permission\",\r\n+ )\r\n+ @click.option(\r\n+ \"databases\",\r\n+ \"-d\",\r\n+ \"--database\",\r\n+ type=(str, str),\r\n+ multiple=True,\r\n+ help=\"Restrict token to this permission on this database\",\r\n+ )\r\n+ @click.option(\r\n+ \"resources\",\r\n+ \"-r\",\r\n+ \"--resource\",\r\n+ type=(str, str, str),\r\n+ multiple=True,\r\n+ help=\"Restrict token to this permission on this database resource (a table, SQL view or named query)\",\r\n+ )\r\n @click.option(\r\n \"--debug\",\r\n help=\"Show decoded token\",\r\n is_flag=True,\r\n )\r\n- def create_token(id, secret, expires_after, debug):\r\n+ def create_token(id, secret, expires_after, alls, databases, resources, debug):\r\n \"Create a signed API token for the specified actor ID\"\r\n ds = Datasette(secret=secret)\r\n bits = {\"a\": id, \"token\": \"dstok\", \"t\": int(time.time())}\r\n if expires_after:\r\n bits[\"d\"] = expires_after\r\n+ if alls or databases or resources:\r\n+ bits[\"_r\"] = {}\r\n+ if alls:\r\n+ bits[\"_r\"][\"a\"] = list(alls)\r\n+ if databases:\r\n+ bits[\"_r\"][\"d\"] = {}\r\n+ for database, action in databases:\r\n+ bits[\"_r\"][\"d\"].setdefault(database, []).append(action)\r\n+ if resources:\r\n+ bits[\"_r\"][\"r\"] = {}\r\n+ for database, table, action in resources:\r\n+ bits[\"_r\"][\"r\"].setdefault(database, {}).setdefault(\r\n+ table, []\r\n+ ).append(action)\r\n token = ds.sign(bits, namespace=\"token\")\r\n click.echo(\"dstok_{}\".format(token))\r\n if debug:\r\n```\r\nStill needs tests, plus I'd like it to use abbreviations if available to keep the token length shorter.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1423336089, "label": "`datasette create-token` ability to create tokens with a reduced set of permissions"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1855#issuecomment-1347693620", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1855", "id": 1347693620, "node_id": "IC_kwDOBm6k_c5QVCw0", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T03:25:41Z", "updated_at": "2022-12-13T03:25:41Z", "author_association": "OWNER", "body": "I'm going to rename \"t\" in the magic format to \"r\" for resource.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1423336089, "label": "`datasette create-token` ability to create tokens with a reduced set of permissions"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1855#issuecomment-1347675456", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1855", "id": 1347675456, "node_id": "IC_kwDOBm6k_c5QU-VA", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T02:57:46Z", "updated_at": "2022-12-13T02:57:46Z", "author_association": "OWNER", "body": "I was going to have the CLI command throw an error if you attempt to use a permission that isn't registered with Datasette, but then I remembered that one of the uses for the CLI tool is to create signed tokens that will work against other Datasette instances (via the `--secret` option) that might have different plugins installed that register different permission names.\r\n\r\nSo I might have it output warnings instead.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1423336089, "label": "`datasette create-token` ability to create tokens with a reduced set of permissions"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1855#issuecomment-1313148519", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1855", "id": 1313148519, "node_id": "IC_kwDOBm6k_c5ORQ5n", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-11-14T06:13:43Z", "updated_at": "2022-12-13T02:46:51Z", "author_association": "OWNER", "body": "The `datasette create-token` command will need to be able to do this too.\r\n\r\nRight now that command looks like this:\r\n```\r\n% datasette create-token --help\r\nUsage: datasette create-token [OPTIONS] ID\r\n\r\n Create a signed API token for the specified actor ID\r\n\r\nOptions:\r\n --secret TEXT Secret used for signing the API tokens\r\n [required]\r\n -e, --expires-after INTEGER Token should expire after this many seconds\r\n --debug Show decoded token\r\n --help Show this message and exit.\r\n```\r\n```\r\n% datasette create-token root --secret sec --debug -e 445\r\ndstok_eyJhIjoicm9vdCIsInRva2VuIjoiZHN0b2siLCJ0IjoxNjY4NDA2MjEzLCJkIjo0NDV9.Hd6qRli6xRKkOIRQgZkPO5iN1wM\r\n\r\nDecoded:\r\n\r\n{\r\n \"a\": \"root\",\r\n \"token\": \"dstok\",\r\n \"t\": 1668406213,\r\n \"d\": 445\r\n}\r\n```\r\n(The `--debug` bit adds the decoded token.)\r\n\r\nSyntax for adding \"insert row\" for everything, \"update row\" for all in the \"data\" database and \"delete row\" just for the docs / titles table:\r\n```\r\ndatasette create-token root --secret sec \\\r\n --all insert-row \\\r\n --database data update-row \\\r\n --table docs titles delete-row\r\n```\r\nThe `ir` / `ur` / `dr` options would work too. To add multiple permissions use these options multiple times:\r\n```\r\ndatasette create-token root --secret sec \\\r\n --all insert-row \\\r\n --all delete-row\r\n```\r\nShort versions: `-a` and `-d` and `-t`.\r\n\r\nUPDATE: I have decided to use the term `resource` in the user-facing elements of this feature instead of `table`, since that can refer to a SQL view and a canned query as well.\r\n\r\nSo `--resource` and `-r`, not `-t`.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1423336089, "label": "`datasette create-token` ability to create tokens with a reduced set of permissions"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1855#issuecomment-1347669087", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1855", "id": 1347669087, "node_id": "IC_kwDOBm6k_c5QU8xf", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T02:45:15Z", "updated_at": "2022-12-13T02:45:15Z", "author_association": "OWNER", "body": "The hardest piece here is the UI. I'm going to implement the CLI command first.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1423336089, "label": "`datasette create-token` ability to create tokens with a reduced set of permissions"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1636#issuecomment-1347655074", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1636", "id": 1347655074, "node_id": "IC_kwDOBm6k_c5QU5Wi", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T02:21:04Z", "updated_at": "2022-12-13T02:21:23Z", "author_association": "OWNER", "body": "The thing I'm stuck on at the moment is how to implement it such that an `allow` block for `create-table` at the root of the metadata will be checked correctly.\r\n\r\nMaybe the algorithm when `_resolve_metadata_permissions_blocks(datasette, actor, action, resource)` is called should do this:\r\n\r\n1. If a root permission block matching that action exists, test with that\r\n2. Next, if resource has been passed, check at the database level\r\n3. If the resource included a table/query, check at that level too\r\n\r\nSo everything is keyed off the incoming `action` name.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1138008042, "label": "\"permissions\" propery in metadata for configuring arbitrary permissions"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1636#issuecomment-1347648326", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1636", "id": 1347648326, "node_id": "IC_kwDOBm6k_c5QU3tG", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T02:10:02Z", "updated_at": "2022-12-13T02:10:02Z", "author_association": "OWNER", "body": "The implementation for this will go here: https://github.com/simonw/datasette/blob/8bf06a76b51bc9ace7cf72cf0cca8f1da7704ea7/datasette/default_permissions.py#L81-L83\r\n\r\nHere's the start of the tests (currently marked as `xfail`):\r\n\r\nhttps://github.com/simonw/datasette/blob/8bf06a76b51bc9ace7cf72cf0cca8f1da7704ea7/tests/test_permissions.py#L652-L689", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1138008042, "label": "\"permissions\" propery in metadata for configuring arbitrary permissions"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1636#issuecomment-1347647298", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1636", "id": 1347647298, "node_id": "IC_kwDOBm6k_c5QU3dC", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T02:08:46Z", "updated_at": "2022-12-13T02:08:46Z", "author_association": "OWNER", "body": "A bunch of the work for this just landed - in particular the new scheme is now documented (even though it doesn't work yet):\r\n\r\nhttps://docs.datasette.io/en/latest/authentication.html#other-permissions-in-metadata", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1138008042, "label": "\"permissions\" propery in metadata for configuring arbitrary permissions"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1939#issuecomment-1347646516", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1939", "id": 1347646516, "node_id": "IC_kwDOBm6k_c5QU3Q0", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T02:07:50Z", "updated_at": "2022-12-13T02:07:50Z", "author_association": "OWNER", "body": "Documentation for the new hook: https://docs.datasette.io/en/latest/plugin_hooks.html#register-permissions-datasette", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1485757511, "label": "register_permissions(datasette) plugin hook"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1943#issuecomment-1347645615", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1943", "id": 1347645615, "node_id": "IC_kwDOBm6k_c5QU3Cv", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T02:06:47Z", "updated_at": "2022-12-13T02:06:47Z", "author_association": "OWNER", "body": "This URL is already used for the https://latest.datasette.io/-/permissions tool - but it could include a block on that page that tells you what permissions are available.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1490576818, "label": "`/-/permissions` should list available permissions"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1940#issuecomment-1347640542", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1940", "id": 1347640542, "node_id": "IC_kwDOBm6k_c5QU1ze", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T02:02:10Z", "updated_at": "2022-12-13T02:02:10Z", "author_association": "OWNER", "body": "This PR ended up bundling part of the implementation of:\r\n- #1636\r\n\r\nI'm going to be bad an NOT untangle that from this before I merge it.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1486011362, "label": "register_permissions() plugin hook"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1940#issuecomment-1347632350", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1940", "id": 1347632350, "node_id": "IC_kwDOBm6k_c5QUzze", "user": {"value": 22429695, "label": "codecov[bot]"}, "created_at": "2022-12-13T01:48:40Z", "updated_at": "2022-12-13T02:00:52Z", "author_association": "NONE", "body": "# [Codecov](https://codecov.io/gh/simonw/datasette/pull/1940?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison) Report\nBase: **92.00**% // Head: **92.03**% // Increases project coverage by **`+0.02%`** :tada:\n> Coverage data is based on head [(`a1317ab`)](https://codecov.io/gh/simonw/datasette/pull/1940?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison) compared to base [(`e539c1c`)](https://codecov.io/gh/simonw/datasette/commit/e539c1c024bc62d88df91d9107cbe37e7f0fe55f?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison).\n> Patch coverage: 100.00% of modified lines in pull request are covered.\n\n> :exclamation: Current head a1317ab differs from pull request most recent head 94e5c75. Consider uploading reports for the commit 94e5c75 to get more accurate results\n\n
Additional details and impacted files\n\n\n```diff\n@@ Coverage Diff @@\n## main #1940 +/- ##\n==========================================\n+ Coverage 92.00% 92.03% +0.02% \n==========================================\n Files 38 38 \n Lines 5378 5396 +18 \n==========================================\n+ Hits 4948 4966 +18 \n Misses 430 430 \n```\n\n\n| [Impacted Files](https://codecov.io/gh/simonw/datasette/pull/1940?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison) | Coverage \u0394 | |\n|---|---|---|\n| [datasette/permissions.py](https://codecov.io/gh/simonw/datasette/pull/1940/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison#diff-ZGF0YXNldHRlL3Blcm1pc3Npb25zLnB5) | `100.00% <\u00f8> (\u00f8)` | |\n| [datasette/views/database.py](https://codecov.io/gh/simonw/datasette/pull/1940/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison#diff-ZGF0YXNldHRlL3ZpZXdzL2RhdGFiYXNlLnB5) | `96.26% <\u00f8> (\u00f8)` | |\n| [datasette/views/index.py](https://codecov.io/gh/simonw/datasette/pull/1940/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison#diff-ZGF0YXNldHRlL3ZpZXdzL2luZGV4LnB5) | `96.49% <\u00f8> (\u00f8)` | |\n| [datasette/views/special.py](https://codecov.io/gh/simonw/datasette/pull/1940/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison#diff-ZGF0YXNldHRlL3ZpZXdzL3NwZWNpYWwucHk=) | `79.20% <\u00f8> (-0.21%)` | :arrow_down: |\n| [datasette/views/table.py](https://codecov.io/gh/simonw/datasette/pull/1940/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison#diff-ZGF0YXNldHRlL3ZpZXdzL3RhYmxlLnB5) | `92.57% <\u00f8> (\u00f8)` | |\n| [datasette/\\_\\_init\\_\\_.py](https://codecov.io/gh/simonw/datasette/pull/1940/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison#diff-ZGF0YXNldHRlL19faW5pdF9fLnB5) | `100.00% <100.00%> (\u00f8)` | |\n| [datasette/app.py](https://codecov.io/gh/simonw/datasette/pull/1940/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison#diff-ZGF0YXNldHRlL2FwcC5weQ==) | `94.47% <100.00%> (+0.04%)` | :arrow_up: |\n| [datasette/default\\_permissions.py](https://codecov.io/gh/simonw/datasette/pull/1940/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison#diff-ZGF0YXNldHRlL2RlZmF1bHRfcGVybWlzc2lvbnMucHk=) | `95.20% <100.00%> (+0.39%)` | :arrow_up: |\n| [datasette/hookspecs.py](https://codecov.io/gh/simonw/datasette/pull/1940/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison#diff-ZGF0YXNldHRlL2hvb2tzcGVjcy5weQ==) | `100.00% <100.00%> (\u00f8)` | |\n\nHelp us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison)\n\n
\n\n[:umbrella: View full report at Codecov](https://codecov.io/gh/simonw/datasette/pull/1940?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison). \n:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison).\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1486011362, "label": "register_permissions() plugin hook"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1940#issuecomment-1347634128", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1940", "id": 1347634128, "node_id": "IC_kwDOBm6k_c5QU0PQ", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T01:51:56Z", "updated_at": "2022-12-13T01:51:56Z", "author_association": "OWNER", "body": "Actually one last thing: I said that the error would only occur if the permissions differed in some way.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1486011362, "label": "register_permissions() plugin hook"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1940#issuecomment-1347620733", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1940", "id": 1347620733, "node_id": "IC_kwDOBm6k_c5QUw99", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T01:33:06Z", "updated_at": "2022-12-13T01:33:06Z", "author_association": "OWNER", "body": "It's this change which triggers the failures:\r\n```diff\r\ndiff --git a/datasette/app.py b/datasette/app.py\r\nindex 760063d5..defa9688 100644\r\n--- a/datasette/app.py\r\n+++ b/datasette/app.py\r\n@@ -707,9 +707,12 @@ class Datasette:\r\n )\r\n return crumbs\r\n \r\n- async def permission_allowed(self, actor, action, resource=None, default=False):\r\n+ async def permission_allowed(self, actor, action, resource=None, default=None):\r\n \"\"\"Check permissions using the permissions_allowed plugin hook\"\"\"\r\n result = None\r\n+ # Use default from registered permission, if available\r\n+ if default is None and action in self.permissions:\r\n+ default = self.permissions[action].default\r\n for check in pm.hook.permission_allowed(\r\n datasette=self,\r\n actor=actor,\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1486011362, "label": "register_permissions() plugin hook"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1940#issuecomment-1347616055", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1940", "id": 1347616055, "node_id": "IC_kwDOBm6k_c5QUv03", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-12-13T01:27:03Z", "updated_at": "2022-12-13T01:27:03Z", "author_association": "OWNER", "body": "I'm going to revert that last commit, see if I can get the tests running again and then apply the changes a line at a time to figure out which ones broke things.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1486011362, "label": "register_permissions() plugin hook"}, "performed_via_github_app": null}