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-1350414961,https://api.github.com/repos/simonw/datasette/issues/1947,1350414961,IC_kwDOBm6k_c5QfbJx,9599,2022-12-14T05:22:00Z,2022-12-14T05:22:00Z,OWNER,I think the next big step for this feature is for me to actually use it to build a few things.,"{""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-1350414402,https://api.github.com/repos/simonw/datasette/issues/1947,1350414402,IC_kwDOBm6k_c5QfbBC,9599,2022-12-14T05:21:07Z,2022-12-14T05:21:07Z,OWNER,"It would be neat not to show write permissions against immutable databases too - and not hard from a performance perspective since it doesn't involve hundreds more permission checks.
That will need permissions to grow a flag for if they need a mutable database though, which is a bigger job.","{""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-1350413555,https://api.github.com/repos/simonw/datasette/issues/1947,1350413555,IC_kwDOBm6k_c5Qfazz,9599,2022-12-14T05:19:52Z,2022-12-14T05:19:52Z,OWNER,"Maybe I should have kept `_memory` listed for instances that are running with `--crossdb` enabled?
Yeah I think I should.","{""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-1350409537,https://api.github.com/repos/simonw/datasette/issues/1947,1350409537,IC_kwDOBm6k_c5QfZ1B,9599,2022-12-14T05:14:16Z,2022-12-14T05:14:16Z,OWNER,"New interface now live at https://latest.datasette.io/-/create-token
It shouldn't be showing `_memory` though.","{""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-1350402667,https://api.github.com/repos/simonw/datasette/issues/1947,1350402667,IC_kwDOBm6k_c5QfYJr,9599,2022-12-14T05:05:10Z,2022-12-14T05:05:10Z,OWNER,"Tests can go here:
https://github.com/simonw/datasette/blob/d98a8effb10ce8fe04a03eae42baa8a9cb0ca3f7/tests/test_auth.py#L143-L160","{""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-1350401651,https://api.github.com/repos/simonw/datasette/issues/1947,1350401651,IC_kwDOBm6k_c5QfX5z,9599,2022-12-14T05:03:59Z,2022-12-14T05:03:59Z,OWNER,I shipped a working interface. Could still do with some extra tests.,"{""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-1350215936,https://api.github.com/repos/simonw/datasette/issues/1947,1350215936,IC_kwDOBm6k_c5QeqkA,9599,2022-12-14T01:23:42Z,2022-12-14T01:23:42Z,OWNER,"With tilde-encoding for database and table names the HTML looks like this:
```html
```","{""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-1350148192,https://api.github.com/repos/simonw/datasette/issues/1947,1350148192,IC_kwDOBm6k_c5QeaBg,9599,2022-12-14T00:19:06Z,2022-12-14T00:19:06Z,OWNER,"Another option: I could set a time limit - say 200ms - on how long I'm willing to spend calculating permissions before displaying this form
First calculate view permissions for tables and databases (and maybe views and canned queries too).
Then see if I can check every permission that I'm going to show as a checkbox on this page. If I get that done within the time limit use that to show the options.
If I run out of time show all options and maybe include a note saying that some of them may not actually be available.","{""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-1350125018,https://api.github.com/repos/simonw/datasette/issues/1947,1350125018,IC_kwDOBm6k_c5QeUXa,9599,2022-12-14T00:08:09Z,2022-12-14T00:08:09Z,OWNER,Also: don't show hidden tables.,"{""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-1350124381,https://api.github.com/repos/simonw/datasette/issues/1947,1350124381,IC_kwDOBm6k_c5QeUNd,9599,2022-12-14T00:07:51Z,2022-12-14T00:07:51Z,OWNER,"Another thing to consider in the future: once Datasette can support thousands of tables (see #417) the list on this page will turn into multiple MBs of HTML, which may cause all kinds of problems - not to mention the overhead of all of those table visibility permission checks.
Hopefully by then I'll have a good fix for the permission listings problem:
- #1152
And I can apply the same mechanism here.","{""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-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 permission in all_permissions %}
+
+ {% endfor %}
+
+
+ {% for database in databases %}
+
All tables in database: {{ database }}
+
+ {% for permission in database_permissions %}
+
+ {% endfor %}
+
+ {% endfor %}
+
Specific tables
+ {% for dbt in database_with_tables %}
+ {% for table in dbt.tables %}
+
{{ dbt.database }}: {{ table }}
+
+ {% for permission in table_permissions %}
+
+ {% endfor %}
+
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:
+
+
+
+
{% 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 `