html_url,issue_url,id,node_id,user,created_at,updated_at,author_association,body,reactions,issue,performed_via_github_app https://github.com/simonw/datasette/issues/1947#issuecomment-1350037572,https://api.github.com/repos/simonw/datasette/issues/1947,1350037572,IC_kwDOBm6k_c5Qd_BE,9599,2022-12-13T23:27:32Z,2022-12-13T23:27:32Z,OWNER,"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). I 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. The 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.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1493390939, https://github.com/simonw/datasette/issues/1947#issuecomment-1350019528,https://api.github.com/repos/simonw/datasette/issues/1947,1350019528,IC_kwDOBm6k_c5Qd6nI,9599,2022-12-13T23:19:16Z,2022-12-13T23:19:16Z,OWNER,"Here's the checkbox prototype: ```diff diff --git a/datasette/templates/create_token.html b/datasette/templates/create_token.html index a94881ed..1795ebaf 100644 --- a/datasette/templates/create_token.html +++ b/datasette/templates/create_token.html @@ -2,11 +2,20 @@ {% block title %}Create an API token{% endblock %} +{% block extra_head %} + +{% endblock %} + {% block content %}

Create an API token

-

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

+

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

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

All databases and tables

+ + + {% for database in databases %} +

All tables in database: {{ database }}

+ + {% endfor %} +

Specific tables

+ {% for dbt in database_with_tables %} + {% for table in dbt.tables %} +

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

+ + {% endfor %} + {% endfor %} +
+ + {% if token %}
diff --git a/datasette/views/special.py b/datasette/views/special.py index 30345d14..48357f87 100644 --- a/datasette/views/special.py +++ b/datasette/views/special.py @@ -231,12 +231,37 @@ class CreateTokenView(BaseView): return await self.render( [""create_token.html""], request, - {""actor"": request.actor}, + { + ""actor"": request.actor, + ""all_permissions"": self.ds.permissions.keys(), + ""database_permissions"": [ + key + for key, value in self.ds.permissions.items() + if value.takes_database + ], + ""table_permissions"": [ + key + for key, value in self.ds.permissions.items() + if value.takes_resource + ], + ""databases"": [k for k in self.ds.databases.keys() if k != ""_internal""], + ""database_with_tables"": [ + { + ""database"": db.name, + ""tables"": await db.table_names(), + } + for db in self.ds.databases.values() + if db.name != ""_internal"" + ], + }, ) async def post(self, request): self.check_permission(request) post = await request.post_vars() + from pprint import pprint + + pprint(post) errors = [] duration = None if post.get(""expire_type""): ```","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1493390939, https://github.com/simonw/datasette/issues/1947#issuecomment-1350013016,https://api.github.com/repos/simonw/datasette/issues/1947,1350013016,IC_kwDOBm6k_c5Qd5BY,9599,2022-12-13T23:16:24Z,2022-12-13T23:17:17Z,OWNER,"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. I 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. It's that classic permission system problem: how to efficiently iterate through everything the user has permission to do in one go? Might 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.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1493390939, https://github.com/simonw/datasette/issues/1947#issuecomment-1350008636,https://api.github.com/repos/simonw/datasette/issues/1947,1350008636,IC_kwDOBm6k_c5Qd388,9599,2022-12-13T23:14:33Z,2022-12-13T23:14:33Z,OWNER,"Checkbox interface looks like this. It's not beautiful but it's good enough for the moment: ","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1493390939, https://github.com/simonw/datasette/issues/1947#issuecomment-1350002434,https://api.github.com/repos/simonw/datasette/issues/1947,1350002434,IC_kwDOBm6k_c5Qd2cC,9599,2022-12-13T23:11:50Z,2022-12-13T23:11:59Z,OWNER,"I think checkboxes will work well. Here's the data I get back from them (as `post_vars()`): ``` {'all:debug-menu': 'on', 'all:insert-row': 'on', 'expire_duration': '', 'expire_type': '', 'table:fixtures:delete-row': 'on', 'table:fixtures:drop-table': 'on', 'table:fixtures:view-query': 'on'} ```","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1493390939, https://github.com/simonw/datasette/issues/1947#issuecomment-1349975255,https://api.github.com/repos/simonw/datasette/issues/1947,1349975255,IC_kwDOBm6k_c5QdvzX,9599,2022-12-13T23:00:11Z,2022-12-13T23:00:11Z,OWNER,"My `
+ +
+ Restrict actions that can be performed using this token +

Restrict actions that can be performed using this token:

+

All databases and tables:

+

+
+ {% if token %} diff --git a/datasette/views/special.py b/datasette/views/special.py index 30345d14..9d0fcd31 100644 --- a/datasette/views/special.py +++ b/datasette/views/special.py @@ -231,7 +231,17 @@ class CreateTokenView(BaseView): return await self.render( [""create_token.html""], request, - {""actor"": request.actor}, + { + ""actor"": request.actor, + ""all_permissions"": self.ds.permissions.keys(), + ""database_permissions"": [key for key, value in self.ds.permissions.items() if value.takes_database], + ""table_permissions"": [key for key, value in self.ds.permissions.items() if value.takes_resource], + ""databases"": self.ds.databases.keys(), + ""database_with_tables"": [{ + ""database"": db.name, + ""tables"": await db.table_names(), + } for db in self.ds.databases.values()], + }, ) async def post(self, request): ```","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1493390939, https://github.com/simonw/datasette/issues/1947#issuecomment-1349974287,https://api.github.com/repos/simonw/datasette/issues/1947,1349974287,IC_kwDOBm6k_c5QdvkP,9599,2022-12-13T22:59:44Z,2022-12-13T22:59:44Z,OWNER,"Got an option group thing working: But... it strikes me that any time you're considering a `` for this. The usability for keyboards is still pretty awful, but it's a niche enough feature that maybe that's OK for the moment? ```javascript var select = document.querySelector('select'); var selected = Array.from(temp0.options).filter(o => o.selected).map(o => o.value) ```","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1493390939, https://github.com/simonw/datasette/issues/1947#issuecomment-1347768549,https://api.github.com/repos/simonw/datasette/issues/1947,1347768549,IC_kwDOBm6k_c5QVVDl,9599,2022-12-13T05:25:56Z,2022-12-13T22:29:12Z,OWNER,- [x] I should add a `--database` example to that help text.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1493390939, https://github.com/simonw/datasette/issues/1947#issuecomment-1347768328,https://api.github.com/repos/simonw/datasette/issues/1947,1347768328,IC_kwDOBm6k_c5QVVAI,9599,2022-12-13T05:25:31Z,2022-12-13T22:25:46Z,OWNER,"https://latest.datasette.io/-/create-token currently looks like this: ![Image](https://user-images.githubusercontent.com/9599/207458002-7c46940b-22c0-45d3-a668-ec7f1082588c.png) As a reminder, the CLI options that this needs to provide an alternative to are: https://github.com/simonw/datasette/blob/d4b98d3924dec625a99236e65b1b169ff957381f/docs/cli-reference.rst#L619-L638","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1493390939, https://github.com/simonw/datasette/issues/1947#issuecomment-1347775760,https://api.github.com/repos/simonw/datasette/issues/1947,1347775760,IC_kwDOBm6k_c5QVW0Q,9599,2022-12-13T05:38:47Z,2022-12-13T05:38:47Z,OWNER,I'm going to hide the options for reducing the scope of the token inside a details/summary element.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1493390939, https://github.com/simonw/datasette/issues/1947#issuecomment-1347760109,https://api.github.com/repos/simonw/datasette/issues/1947,1347760109,IC_kwDOBm6k_c5QVS_t,9599,2022-12-13T05:12:00Z,2022-12-13T05:12:00Z,OWNER,"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.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1493390939,