home / github

Menu
  • GraphQL API

issue_comments

Table actions
  • GraphQL API for issue_comments

43 rows where "updated_at" is on date 2022-12-13

✎ View and edit SQL

This data as json, CSV (advanced)

Suggested facets: created_at (date), updated_at (date)

id ▼ html_url issue_url node_id user created_at updated_at author_association body reactions issue performed_via_github_app
1313148519 https://github.com/simonw/datasette/issues/1855#issuecomment-1313148519 https://api.github.com/repos/simonw/datasette/issues/1855 IC_kwDOBm6k_c5ORQ5n simonw 9599 2022-11-14T06:13:43Z 2022-12-13T02:46:51Z OWNER The `datasette create-token` command will need to be able to do this too. Right now that command looks like this: ``` % datasette create-token --help Usage: datasette create-token [OPTIONS] ID Create a signed API token for the specified actor ID Options: --secret TEXT Secret used for signing the API tokens [required] -e, --expires-after INTEGER Token should expire after this many seconds --debug Show decoded token --help Show this message and exit. ``` ``` % datasette create-token root --secret sec --debug -e 445 dstok_eyJhIjoicm9vdCIsInRva2VuIjoiZHN0b2siLCJ0IjoxNjY4NDA2MjEzLCJkIjo0NDV9.Hd6qRli6xRKkOIRQgZkPO5iN1wM Decoded: { "a": "root", "token": "dstok", "t": 1668406213, "d": 445 } ``` (The `--debug` bit adds the decoded token.) Syntax for adding "insert row" for everything, "update row" for all in the "data" database and "delete row" just for the docs / titles table: ``` datasette create-token root --secret sec \ --all insert-row \ --database data update-row \ --table docs titles delete-row ``` The `ir` / `ur` / `dr` options would work too. To add multiple permissions use these options multiple times: ``` datasette create-token root --secret sec \ --all insert-row \ --all delete-row ``` Short versions: `-a` and `-d` and `-t`. UPDATE: 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. So `--resource` and `-r`, not `-t`. {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} `datasette create-token` ability to create tokens with a reduced set of permissions 1423336089  
1347616055 https://github.com/simonw/datasette/pull/1940#issuecomment-1347616055 https://api.github.com/repos/simonw/datasette/issues/1940 IC_kwDOBm6k_c5QUv03 simonw 9599 2022-12-13T01:27:03Z 2022-12-13T01:27:03Z OWNER 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. {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} register_permissions() plugin hook 1486011362  
1347620733 https://github.com/simonw/datasette/pull/1940#issuecomment-1347620733 https://api.github.com/repos/simonw/datasette/issues/1940 IC_kwDOBm6k_c5QUw99 simonw 9599 2022-12-13T01:33:06Z 2022-12-13T01:33:06Z OWNER It's this change which triggers the failures: ```diff diff --git a/datasette/app.py b/datasette/app.py index 760063d5..defa9688 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -707,9 +707,12 @@ class Datasette: ) return crumbs - async def permission_allowed(self, actor, action, resource=None, default=False): + async def permission_allowed(self, actor, action, resource=None, default=None): """Check permissions using the permissions_allowed plugin hook""" result = None + # Use default from registered permission, if available + if default is None and action in self.permissions: + default = self.permissions[action].default for check in pm.hook.permission_allowed( datasette=self, actor=actor, ``` {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} register_permissions() plugin hook 1486011362  
1347632350 https://github.com/simonw/datasette/pull/1940#issuecomment-1347632350 https://api.github.com/repos/simonw/datasette/issues/1940 IC_kwDOBm6k_c5QUzze codecov[bot] 22429695 2022-12-13T01:48:40Z 2022-12-13T02:00:52Z NONE # [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 Base: **92.00**% // Head: **92.03**% // Increases project coverage by **`+0.02%`** :tada: > 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). > Patch coverage: 100.00% of modified lines in pull request are covered. > :exclamation: Current head a1317ab differs from pull request most recent head 94e5c75. Consider uploading reports for the commit 94e5c75 to get more accurate results <details><summary>Additional details and impacted files</summary> ```diff @@ Coverage Diff @@ ## main #1940 +/- ## ========================================== + Coverage 92.00% 92.03% +0.02% ========================================== Files 38 38 Lines 5378 5396 +18 ========================================== + Hits 4948 4966 +18 Misses 430 430 ``` | [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 Δ | | |---|---|---| | [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% <ø> (ø)` | | | [datasette/views/database.py](https://codecov.io/gh/simonw/datasette… {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} register_permissions() plugin hook 1486011362  
1347634128 https://github.com/simonw/datasette/pull/1940#issuecomment-1347634128 https://api.github.com/repos/simonw/datasette/issues/1940 IC_kwDOBm6k_c5QU0PQ simonw 9599 2022-12-13T01:51:56Z 2022-12-13T01:51:56Z OWNER Actually one last thing: I said that the error would only occur if the permissions differed in some way. {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} register_permissions() plugin hook 1486011362  
1347640542 https://github.com/simonw/datasette/pull/1940#issuecomment-1347640542 https://api.github.com/repos/simonw/datasette/issues/1940 IC_kwDOBm6k_c5QU1ze simonw 9599 2022-12-13T02:02:10Z 2022-12-13T02:02:10Z OWNER This PR ended up bundling part of the implementation of: - #1636 I'm going to be bad an NOT untangle that from this before I merge it. {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} register_permissions() plugin hook 1486011362  
1347645615 https://github.com/simonw/datasette/issues/1943#issuecomment-1347645615 https://api.github.com/repos/simonw/datasette/issues/1943 IC_kwDOBm6k_c5QU3Cv simonw 9599 2022-12-13T02:06:47Z 2022-12-13T02:06:47Z OWNER 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. {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} `/-/permissions` should list available permissions 1490576818  
1347646516 https://github.com/simonw/datasette/issues/1939#issuecomment-1347646516 https://api.github.com/repos/simonw/datasette/issues/1939 IC_kwDOBm6k_c5QU3Q0 simonw 9599 2022-12-13T02:07:50Z 2022-12-13T02:07:50Z OWNER Documentation for the new hook: https://docs.datasette.io/en/latest/plugin_hooks.html#register-permissions-datasette {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} register_permissions(datasette) plugin hook 1485757511  
1347647298 https://github.com/simonw/datasette/issues/1636#issuecomment-1347647298 https://api.github.com/repos/simonw/datasette/issues/1636 IC_kwDOBm6k_c5QU3dC simonw 9599 2022-12-13T02:08:46Z 2022-12-13T02:08:46Z OWNER A bunch of the work for this just landed - in particular the new scheme is now documented (even though it doesn't work yet): https://docs.datasette.io/en/latest/authentication.html#other-permissions-in-metadata {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} "permissions" propery in metadata for configuring arbitrary permissions 1138008042  
1347648326 https://github.com/simonw/datasette/issues/1636#issuecomment-1347648326 https://api.github.com/repos/simonw/datasette/issues/1636 IC_kwDOBm6k_c5QU3tG simonw 9599 2022-12-13T02:10:02Z 2022-12-13T02:10:02Z OWNER The implementation for this will go here: https://github.com/simonw/datasette/blob/8bf06a76b51bc9ace7cf72cf0cca8f1da7704ea7/datasette/default_permissions.py#L81-L83 Here's the start of the tests (currently marked as `xfail`): https://github.com/simonw/datasette/blob/8bf06a76b51bc9ace7cf72cf0cca8f1da7704ea7/tests/test_permissions.py#L652-L689 {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} "permissions" propery in metadata for configuring arbitrary permissions 1138008042  
1347655074 https://github.com/simonw/datasette/issues/1636#issuecomment-1347655074 https://api.github.com/repos/simonw/datasette/issues/1636 IC_kwDOBm6k_c5QU5Wi simonw 9599 2022-12-13T02:21:04Z 2022-12-13T02:21:23Z OWNER 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. Maybe the algorithm when `_resolve_metadata_permissions_blocks(datasette, actor, action, resource)` is called should do this: 1. If a root permission block matching that action exists, test with that 2. Next, if resource has been passed, check at the database level 3. If the resource included a table/query, check at that level too So everything is keyed off the incoming `action` name. {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} "permissions" propery in metadata for configuring arbitrary permissions 1138008042  
1347669087 https://github.com/simonw/datasette/issues/1855#issuecomment-1347669087 https://api.github.com/repos/simonw/datasette/issues/1855 IC_kwDOBm6k_c5QU8xf simonw 9599 2022-12-13T02:45:15Z 2022-12-13T02:45:15Z OWNER The hardest piece here is the UI. I'm going to implement the CLI command first. {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} `datasette create-token` ability to create tokens with a reduced set of permissions 1423336089  
1347675456 https://github.com/simonw/datasette/issues/1855#issuecomment-1347675456 https://api.github.com/repos/simonw/datasette/issues/1855 IC_kwDOBm6k_c5QU-VA simonw 9599 2022-12-13T02:57:46Z 2022-12-13T02:57:46Z OWNER 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. So I might have it output warnings instead. {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} `datasette create-token` ability to create tokens with a reduced set of permissions 1423336089  
1347693620 https://github.com/simonw/datasette/issues/1855#issuecomment-1347693620 https://api.github.com/repos/simonw/datasette/issues/1855 IC_kwDOBm6k_c5QVCw0 simonw 9599 2022-12-13T03:25:41Z 2022-12-13T03:25:41Z OWNER I'm going to rename "t" in the magic format to "r" for resource. {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} `datasette create-token` ability to create tokens with a reduced set of permissions 1423336089  
1347694871 https://github.com/simonw/datasette/issues/1855#issuecomment-1347694871 https://api.github.com/repos/simonw/datasette/issues/1855 IC_kwDOBm6k_c5QVDEX simonw 9599 2022-12-13T03:28:15Z 2022-12-13T03:28:15Z OWNER Initial prototype of the `create-token` command changes: ```diff diff --git a/datasette/default_permissions.py b/datasette/default_permissions.py index 406dae40..bbe1247e 100644 --- a/datasette/default_permissions.py +++ b/datasette/default_permissions.py @@ -278,17 +278,55 @@ def register_commands(cli): help="Token should expire after this many seconds", type=int, ) + @click.option( + "alls", + "-a", + "--all", + type=str, + multiple=True, + help="Restrict token to this permission", + ) + @click.option( + "databases", + "-d", + "--database", + type=(str, str), + multiple=True, + help="Restrict token to this permission on this database", + ) + @click.option( + "resources", + "-r", + "--resource", + type=(str, str, str), + multiple=True, + help="Restrict token to this permission on this database resource (a table, SQL view or named query)", + ) @click.option( "--debug", help="Show decoded token", is_flag=True, ) - def create_token(id, secret, expires_after, debug): + def create_token(id, secret, expires_after, alls, databases, resources, debug): "Create a signed API token for the specified actor ID" ds = Datasette(secret=secret) bits = {"a": id, "token": "dstok", "t": int(time.time())} if expires_after: bits["d"] = expires_after + if alls or databases or resources: + bits["_r"] = {} + if alls: + bits["_r"]["a"] = list(alls) + if databases: + bits["_r"]["d"] = {} + for database, action in databases: + bits["_r"]["d"].setdefault(database, []).append(action) + if resources: + bits["_r"]["r"] = {} + for database, table, action in resources: + bi… {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} `datasette create-token` ability to create tokens with a reduced set of permissions 1423336089  
1347695728 https://github.com/simonw/datasette/issues/1855#issuecomment-1347695728 https://api.github.com/repos/simonw/datasette/issues/1855 IC_kwDOBm6k_c5QVDRw simonw 9599 2022-12-13T03:30:09Z 2022-12-13T03:30:09Z OWNER I just noticed this in the existing code: https://github.com/simonw/datasette/blob/c5d30b58a1cd1c66bbddcf3561db005543ecaf25/datasette/default_permissions.py#L195-L203 Hard-coding those action names should not be necessary any more, especially now we have `datasette.permissions` for looking up metadata about the permissions. {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} `datasette create-token` ability to create tokens with a reduced set of permissions 1423336089  
1347707683 https://github.com/simonw/datasette/issues/1855#issuecomment-1347707683 https://api.github.com/repos/simonw/datasette/issues/1855 IC_kwDOBm6k_c5QVGMj simonw 9599 2022-12-13T03:55:35Z 2022-12-13T04:15:27Z OWNER Help looks like this: ``` Usage: datasette create-token [OPTIONS] ID Create a signed API token for the specified actor ID Example: datasette create-token root --secret mysecret To only allow create-table: datasette create-token root --secret mysecret \ --all create-table Or to only allow insert-row against a specific table: datasette create-token root --secret myscret \ --resource mydb mytable insert-row Restricted actions can be specified multiple times using multiple --all, --database, and --resource options. Add --debug to see a decoded version of the token. Options: --secret TEXT Secret used for signing the API tokens [required] -e, --expires-after INTEGER Token should expire after this many seconds -a, --all ACTION Restrict token to this action -d, --database DB ACTION Restrict token to this action on this database -r, --resource DB RESOURCE ACTION Restrict token to this action on this database resource (a table, SQL view or named query) --debug Show decoded token --plugins-dir DIRECTORY Path to directory containing custom plugins --help Show this message and exit. ``` {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} `datasette create-token` ability to create tokens with a reduced set of permissions 1423336089  
1347726302 https://github.com/simonw/datasette/issues/1855#issuecomment-1347726302 https://api.github.com/repos/simonw/datasette/issues/1855 IC_kwDOBm6k_c5QVKve simonw 9599 2022-12-13T04:16:26Z 2022-12-13T04:16:26Z OWNER 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). {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} `datasette create-token` ability to create tokens with a reduced set of permissions 1423336089  
1347731288 https://github.com/simonw/datasette/issues/1855#issuecomment-1347731288 https://api.github.com/repos/simonw/datasette/issues/1855 IC_kwDOBm6k_c5QVL9Y simonw 9599 2022-12-13T04:24:50Z 2022-12-13T04:24:50Z OWNER For the tests for `datasette create-token` it would be useful if `datasette --get` had a mechanism for sending an `Authorization: Bearer X` header. {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} `datasette create-token` ability to create tokens with a reduced set of permissions 1423336089  
1347732039 https://github.com/simonw/datasette/issues/1946#issuecomment-1347732039 https://api.github.com/repos/simonw/datasette/issues/1946 IC_kwDOBm6k_c5QVMJH simonw 9599 2022-12-13T04:26:20Z 2022-12-13T04:26:20Z OWNER Two options: - `--header "Authorization: Bearer XXX"` which can be used to send any headers - `--token XXX` to specify the token, which is then sent using that header I 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. {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} `datasette --get` mechanism for sending tokens 1493339206  
1347733217 https://github.com/simonw/datasette/issues/1946#issuecomment-1347733217 https://api.github.com/repos/simonw/datasette/issues/1946 IC_kwDOBm6k_c5QVMbh simonw 9599 2022-12-13T04:28:45Z 2022-12-13T04:28:45Z OWNER Demo of the new feature: ``` % datasette create-token --secret s root dstok_eyJhIjoicm9vdCIsInRva2VuIjoiZHN0b2siLCJ0IjoxNjcwOTA1NjgwfQ.pqSWOwCSNp678hEWl9l5o7m1GaM % datasette --get /-/actor.json {"actor": null} % DATASETTE_SECRET=s datasette --get /-/actor.json --token dstok_eyJhIjoicm9vdCIsInRva2VuIjoiZHN0b2siLCJ0IjoxNjcwOTA1NjgwfQ.pqSWOwCSNp678hEWl9l5o7m1GaM {"actor": {"id": "root", "token": "dstok"}} ``` {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} `datasette --get` mechanism for sending tokens 1493339206  
1347759522 https://github.com/simonw/datasette/issues/1855#issuecomment-1347759522 https://api.github.com/repos/simonw/datasette/issues/1855 IC_kwDOBm6k_c5QVS2i simonw 9599 2022-12-13T05:11:43Z 2022-12-13T05:11:43Z OWNER Decided to do the `/-/create-token` UI in a separate ticket: - #1947 {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} `datasette create-token` ability to create tokens with a reduced set of permissions 1423336089  
1347760109 https://github.com/simonw/datasette/issues/1947#issuecomment-1347760109 https://api.github.com/repos/simonw/datasette/issues/1947 IC_kwDOBm6k_c5QVS_t simonw 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} UI to create reduced scope tokens from the `/-/create-token` page 1493390939  
1347761892 https://github.com/simonw/datasette/issues/1855#issuecomment-1347761892 https://api.github.com/repos/simonw/datasette/issues/1855 IC_kwDOBm6k_c5QVTbk simonw 9599 2022-12-13T05:14:25Z 2022-12-13T05:14:25Z OWNER New documentation: https://docs.datasette.io/en/latest/authentication.html#restricting-the-actions-that-a-token-can-perform {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} `datasette create-token` ability to create tokens with a reduced set of permissions 1423336089  
1347766530 https://github.com/simonw/datasette/issues/1948#issuecomment-1347766530 https://api.github.com/repos/simonw/datasette/issues/1948 IC_kwDOBm6k_c5QVUkC simonw 9599 2022-12-13T05:22:19Z 2022-12-13T05:22:19Z OWNER I tested: ``` {"id": "root", "_r": {"a": "view-table"}} ``` {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} 500 error on permission debug page when testing actors with _r 1493404423  
1347767048 https://github.com/simonw/datasette/pull/1938#issuecomment-1347767048 https://api.github.com/repos/simonw/datasette/issues/1938 IC_kwDOBm6k_c5QVUsI simonw 9599 2022-12-13T05:23:18Z 2022-12-13T05:23:18Z OWNER I landed this already: - #1636 {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} "permissions" blocks in metadata.json/yaml 1485488236  
1347768328 https://github.com/simonw/datasette/issues/1947#issuecomment-1347768328 https://api.github.com/repos/simonw/datasette/issues/1947 IC_kwDOBm6k_c5QVVAI simonw 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} UI to create reduced scope tokens from the `/-/create-token` page 1493390939  
1347768549 https://github.com/simonw/datasette/issues/1947#issuecomment-1347768549 https://api.github.com/repos/simonw/datasette/issues/1947 IC_kwDOBm6k_c5QVVDl simonw 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} UI to create reduced scope tokens from the `/-/create-token` page 1493390939  
1347770871 https://github.com/simonw/datasette/issues/1937#issuecomment-1347770871 https://api.github.com/repos/simonw/datasette/issues/1937 IC_kwDOBm6k_c5QVVn3 simonw 9599 2022-12-13T05:30:43Z 2022-12-13T05:30:43Z OWNER Also you should need `update-row` permission to use the `"replace": true` option - I should add that rule to `/-/insert` add well. {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} /db/-/create API should require insert-rows permission to use row: or rows: option 1483320357  
1347775760 https://github.com/simonw/datasette/issues/1947#issuecomment-1347775760 https://api.github.com/repos/simonw/datasette/issues/1947 IC_kwDOBm6k_c5QVW0Q simonw 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} UI to create reduced scope tokens from the `/-/create-token` page 1493390939  
1347801679 https://github.com/simonw/datasette/issues/1914#issuecomment-1347801679 https://api.github.com/repos/simonw/datasette/issues/1914 IC_kwDOBm6k_c5QVdJP simonw 9599 2022-12-13T06:15:54Z 2022-12-13T06:15:54Z OWNER 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. {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} Finalize design of JSON for Datasette 1.0 1468689139  
1349855620 https://github.com/simonw/datasette/issues/1950#issuecomment-1349855620 https://api.github.com/repos/simonw/datasette/issues/1950 IC_kwDOBm6k_c5QdSmE simonw 9599 2022-12-13T22:08:50Z 2022-12-13T22:08:50Z OWNER https://github.com/simonw/datasette/blob/d4b98d3924dec625a99236e65b1b169ff957381f/datasette/views/table.py#L392-L400 {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} Bad ?_sort returns a 500 error, should be a 400 1495241162  
1349864950 https://github.com/simonw/datasette/issues/1950#issuecomment-1349864950 https://api.github.com/repos/simonw/datasette/issues/1950 IC_kwDOBm6k_c5QdU32 simonw 9599 2022-12-13T22:11:15Z 2022-12-13T22:11:15Z OWNER Most places I use that exception at the moment set their own non-500 status error: ``` datasette % rg DatasetteError datasette/handle_exception.py 7:from .views.base import DatasetteError 33: elif isinstance(exception, DatasetteError): datasette/filters.py 2:from datasette.views.base import DatasetteError 22: raise DatasetteError("_where= is not allowed", status=403) 141: raise DatasetteError( datasette/views/table.py 34:from .base import BaseView, DataView, DatasetteError, ureg, _error 178: raise DatasetteError( 192: raise DatasetteError( 390: raise DatasetteError("Cannot use _sort and _sort_desc at the same time") 394: raise DatasetteError(f"Cannot sort table by {sort}") 400: raise DatasetteError(f"Cannot sort table by {sort_desc}") datasette/views/base.py 39:class DatasetteError(Exception): 219: raise DatasetteError(str(e), title="Invalid SQL", status=400) 222: raise DatasetteError(str(e)) 224: except DatasetteError: 382: raise DatasetteError( 402: raise DatasetteError(str(e), title="Invalid SQL", status=400) 405: raise DatasetteError(str(e)) 407: except DatasetteError: datasette/views/table2.py 28:from .base import DataView, DatasetteError, ureg 296: raise DatasetteError( 310: raise DatasetteError( 472: raise DatasetteError("Cannot use _sort and _sort_desc at the same time") 476: raise DatasetteError(f"Cannot sort table by {sort}") 482: raise DatasetteError(f"Cannot sort table by {sort_desc}") datasette/views/database.py 31:from .base import BaseView, DatasetteError, DataView, _error 188: raise DatasetteError("Invalid database", status=404) 190: raise DatasetteError("Cannot download in-memory databases", status=404) 194: raise DatasetteError("Cannot download database", status=404) ``` {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} Bad ?_sort returns a 500 error, should be a 400 1495241162  
1349972480 https://github.com/simonw/datasette/issues/1947#issuecomment-1349972480 https://api.github.com/repos/simonw/datasette/issues/1947 IC_kwDOBm6k_c5QdvIA simonw 9599 2022-12-13T22:58:51Z 2022-12-13T22:58:51Z OWNER I'm experimenting with a `<select multiple>` 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} UI to create reduced scope tokens from the `/-/create-token` page 1493390939  
1349974287 https://github.com/simonw/datasette/issues/1947#issuecomment-1349974287 https://api.github.com/repos/simonw/datasette/issues/1947 IC_kwDOBm6k_c5QdvkP simonw 9599 2022-12-13T22:59:44Z 2022-12-13T22:59:44Z OWNER Got an option group thing working: <img width="445" alt="image" src="https://user-images.githubusercontent.com/9599/207463308-15268283-a0e9-4c05-b5e5-952def0f3ef1.png"> But... it strikes me that any time you're considering a `<select multiple>` like this a nested list of checkboxes would actually be better - easier for people to use. {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} UI to create reduced scope tokens from the `/-/create-token` page 1493390939  
1349975255 https://github.com/simonw/datasette/issues/1947#issuecomment-1349975255 https://api.github.com/repos/simonw/datasette/issues/1947 IC_kwDOBm6k_c5QdvzX simonw 9599 2022-12-13T23:00:11Z 2022-12-13T23:00:11Z OWNER My `<select multiple>` prototype: ```diff diff --git a/datasette/templates/create_token.html b/datasette/templates/create_token.html index a94881ed..5bd641cc 100644 --- a/datasette/templates/create_token.html +++ b/datasette/templates/create_token.html @@ -6,7 +6,7 @@ <h1>Create an API token</h1> -<p>This token will allow API access with the same abilities as your current user.</p> +<p>This token will allow API access with the same abilities as your current user, <strong>{{ request.actor.id }}</strong></p> {% if errors %} {% for error in errors %} @@ -28,6 +28,36 @@ <input type="hidden" name="csrftoken" value="{{ csrftoken() }}"> <input type="submit" value="Create token"> </div> + + <details style="margin-top: 1em" open> + <summary style="cursor: pointer;">Restrict actions that can be performed using this token</summary> + <p style="margin-top: 1em">Restrict actions that can be performed using this token:</p> + <p><label="all_permissions">All databases and tables:</label></p> + <p><select multiple id="all_permissions" size="{{ all_permissions|length * 4 }}"> + <optgroup label="All databases and tables"> + {% for permission in all_permissions %} + <option value="all:{{ permission }}">{{ permission }}</option> + {% endfor %} + </optgroup> + {% for database in databases %} + <optgroup label="All tables in database: {{ database }}"> + {% for permission in database_permissions %} + <option value="db:{{ database }}:{{ permission }}">{{ permission }}</option> + {% endfor %} + </optgroup> + {% endfor %} + {% for dbt in database_with_tables %} + {% for table in dbt.tables %} + <optgroup label="Table {{ dbt.database }}.{{ table }}"> + {% for permission in table_permissions %} + <option value="table:{{ dbt.database }}:{{ permission }}">{{ permission }}</option> + {% endfor %} + </optgroup> + {% endfor %} + {% endfor %} + … {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} UI to create reduced scope tokens from the `/-/create-token` page 1493390939  
1350002434 https://github.com/simonw/datasette/issues/1947#issuecomment-1350002434 https://api.github.com/repos/simonw/datasette/issues/1947 IC_kwDOBm6k_c5Qd2cC simonw 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} UI to create reduced scope tokens from the `/-/create-token` page 1493390939  
1350008636 https://github.com/simonw/datasette/issues/1947#issuecomment-1350008636 https://api.github.com/repos/simonw/datasette/issues/1947 IC_kwDOBm6k_c5Qd388 simonw 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: <img width="598" alt="image" src="https://user-images.githubusercontent.com/9599/207465391-78b6e440-65b0-4a02-9911-0b948e65c357.png"> {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} UI to create reduced scope tokens from the `/-/create-token` page 1493390939  
1350013016 https://github.com/simonw/datasette/issues/1947#issuecomment-1350013016 https://api.github.com/repos/simonw/datasette/issues/1947 IC_kwDOBm6k_c5Qd5BY simonw 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} UI to create reduced scope tokens from the `/-/create-token` page 1493390939  
1350019528 https://github.com/simonw/datasette/issues/1947#issuecomment-1350019528 https://api.github.com/repos/simonw/datasette/issues/1947 IC_kwDOBm6k_c5Qd6nI simonw 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 %} +<style type="text/css"> +#restrict-permissions label { + display: inline; + width: 90%; +} +</style> +{% endblock %} + {% block content %} <h1>Create an API token</h1> -<p>This token will allow API access with the same abilities as your current user.</p> +<p>This token will allow API access with the same abilities as your current user, <strong>{{ request.actor.id }}</strong></p> {% if errors %} {% for error in errors %} @@ -27,8 +36,39 @@ <input type="text" name="expire_duration" style="width: 10%"> <input type="hidden" name="csrftoken" value="{{ csrftoken() }}"> <input type="submit" value="Create token"> - </div> + + <details style="margin-top: 1em" open id="restrict-permissions"> + <summary style="cursor: pointer;">Restrict actions that can be performed using this token</summary> + <h2>All databases and tables</h2> + <ul> + {% for permission in all_permissions %} + <li><label><input type="checkbox" name="all:{{ permission }}"> {{ permission }}</label></li> + {% endfor %} + </ul> + + {% for database in databases %} + <h2>All tables in database: {{ database }}</h2> + <ul> + {% for permission in database_permissions %} + <li><label><input type="checkbox" name="db:{{ database }}:{{ permission }}"> {{ permission }}</label></li> + {% endfor %} + </ul> + {% endfor %} + <h2>Specific tables</h2> + {% for dbt in database_with_tables %} + {% for table in dbt.tables %} + <h3>{{ dbt.database }}: {{ table }}</h3> + <ul> + {% for permission in table_permissions %} + <li><label><inp… {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} UI to create reduced scope tokens from the `/-/create-token` page 1493390939  
1350037572 https://github.com/simonw/datasette/issues/1947#issuecomment-1350037572 https://api.github.com/repos/simonw/datasette/issues/1947 IC_kwDOBm6k_c5Qd_BE simonw 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} UI to create reduced scope tokens from the `/-/create-token` page 1493390939  
1352644262 https://github.com/simonw/datasette/issues/1958#issuecomment-1352644262 https://api.github.com/repos/simonw/datasette/issues/1958 IC_kwDOBm6k_c5Qn7am davidhaley 11729897 2022-12-13T16:49:31Z 2022-12-13T16:49:52Z NONE I may have found the reason. I don't think the `--root` option is taking effect. Visited: http://127.0.0.1:8001/-/permissions ![image](https://user-images.githubusercontent.com/11729897/207394127-59f8320f-3410-4ff8-869d-b19ab955d67c.png) {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} datasette --root running in Docker doesn't reliably show the magic URL 1497909798  
1352644267 https://github.com/simonw/datasette/issues/1958#issuecomment-1352644267 https://api.github.com/repos/simonw/datasette/issues/1958 IC_kwDOBm6k_c5Qn7ar simonw 9599 2022-12-13T18:33:32Z 2022-12-13T18:33:32Z OWNER When you run `--root` you need to follow the special link that gets output to the console: ``` % datasette --root http://127.0.0.1:8001/-/auth-token?token=036d8055cc8000e9667f21c1dd08722a9358c066463873ad9566d23d88765c52 INFO: Started server process [53934] INFO: Waiting for application startup. INFO: Application startup complete. ``` That `/-/auth-token?...` link is the one that sets the cookie and lets you in. {"total_count": 1, "+1": 1, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} datasette --root running in Docker doesn't reliably show the magic URL 1497909798  

Advanced export

JSON shape: default, array, newline-delimited, object

CSV options:

CREATE TABLE [issue_comments] (
   [html_url] TEXT,
   [issue_url] TEXT,
   [id] INTEGER PRIMARY KEY,
   [node_id] TEXT,
   [user] INTEGER REFERENCES [users]([id]),
   [created_at] TEXT,
   [updated_at] TEXT,
   [author_association] TEXT,
   [body] TEXT,
   [reactions] TEXT,
   [issue] INTEGER REFERENCES [issues]([id])
, [performed_via_github_app] TEXT);
CREATE INDEX [idx_issue_comments_issue]
                ON [issue_comments] ([issue]);
CREATE INDEX [idx_issue_comments_user]
                ON [issue_comments] ([user]);
Powered by Datasette · Queries took 950.195ms · About: simonw/datasette-graphql