{"ok": true, "next": null, "rows": [{"id": "changelog:authentication", "page": "changelog", "ref": "authentication", "title": "Authentication", "content": "Prior to this release the Datasette ecosystem has treated authentication as exclusively the realm of plugins, most notably through  datasette-auth-github . \n                 0.44 introduces  Authentication and permissions  as core Datasette concepts ( #699 ). This enables different plugins to share responsibility for authenticating requests - you might have one plugin that handles user accounts and another one that allows automated access via API keys, for example. \n                 You'll need to install plugins if you want full user accounts, but default Datasette can now authenticate a single root user with the new  --root  command-line option, which outputs a one-time use URL to  authenticate as a root actor  ( #784 ): \n                 datasette fixtures.db --root \n                 http://127.0.0.1:8001/-/auth-token?token=5b632f8cd44b868df625f5a6e2185d88eea5b22237fd3cc8773f107cc4fd6477\nINFO:     Started server process [14973]\nINFO:     Waiting for application startup.\nINFO:     Application startup complete.\nINFO:     Uvicorn running on http://127.0.0.1:8001 (Press CTRL+C to quit) \n                 Plugins can implement new ways of authenticating users using the new  actor_from_request(datasette, request)  hook.", "breadcrumbs": "[\"Changelog\", \"0.44 (2020-06-11)\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette-auth-github\", \"label\": \"datasette-auth-github\"}, {\"href\": \"https://github.com/simonw/datasette/issues/699\", \"label\": \"#699\"}, {\"href\": \"https://github.com/simonw/datasette/issues/784\", \"label\": \"#784\"}]"}, {"id": "changelog:cookie-methods", "page": "changelog", "ref": "cookie-methods", "title": "Cookie methods", "content": "Plugins can now use the new  response.set_cookie()  method to set cookies. \n                 A new  request.cookies  method on the :ref:internals_request` can be used to read incoming cookies.", "breadcrumbs": "[\"Changelog\", \"0.44 (2020-06-11)\"]", "references": "[]"}, {"id": "changelog:csrf-protection", "page": "changelog", "ref": "csrf-protection", "title": "CSRF protection", "content": "Since writable canned queries are built using POST forms, Datasette now ships with  CSRF protection  ( #798 ). This applies automatically to any POST request, which means plugins need to include a  csrftoken  in any POST forms that they render. They can do that like so: \n                 <input type=\"hidden\" name=\"csrftoken\" value=\"{{ csrftoken() }}\">", "breadcrumbs": "[\"Changelog\", \"0.44 (2020-06-11)\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/798\", \"label\": \"#798\"}]"}, {"id": "changelog:flash-messages", "page": "changelog", "ref": "flash-messages", "title": "Flash messages", "content": "Writable canned queries needed a mechanism to let the user know that the query has been successfully executed. The new flash messaging system ( #790 ) allows messages to persist in signed cookies which are then displayed to the user on the next page that they visit. Plugins can use this mechanism to display their own messages, see  .add_message(request, message, type=datasette.INFO)  for details. \n                 You can try out the new messages using the  /-/messages  debug tool, for example at  https://latest.datasette.io/-/messages", "breadcrumbs": "[\"Changelog\", \"0.44 (2020-06-11)\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/790\", \"label\": \"#790\"}, {\"href\": \"https://latest.datasette.io/-/messages\", \"label\": \"https://latest.datasette.io/-/messages\"}]"}, {"id": "changelog:id70", "page": "changelog", "ref": "id70", "title": "Smaller changes", "content": "New internals documentation for  Request object  and  Response class . ( #706 ) \n                     \n                     \n                         request.url  now respects the  force_https_urls  config setting. closes ( #781 ) \n                     \n                     \n                         request.args.getlist()  returns  []  if missing. Removed  request.raw_args  entirely. ( #774 ) \n                     \n                     \n                         New  datasette.get_database()  method. \n                     \n                     \n                         Added  _  prefix to many private, undocumented methods of the Datasette class. ( #576 ) \n                     \n                     \n                         Removed the  db.get_outbound_foreign_keys()  method which duplicated the behaviour of  db.foreign_keys_for_table() . \n                     \n                     \n                         New  await datasette.permission_allowed()  method. \n                     \n                     \n                         /-/actor  debugging endpoint for viewing the currently authenticated actor. \n                     \n                     \n                         New  request.cookies  property. \n                     \n                     \n                         /-/plugins  endpoint now shows a list of hooks implemented by each plugin, e.g.  https://latest.datasette.io/-/plugins?all=1 \n                     \n                     \n                         request.post_vars()  method no longer discards empty values. \n                     \n                     \n                         New \"params\" canned query key for explicitly setting named parameters, see  Canned query parameters . ( #797 ) \n                     \n                     \n                         request.args  is now a  MultiParams  object. \n                     \n                     \n                         Fixed a bug with the  datasette plugins  command. ( #802 ) \n                     \n                     \n                         Nicer pattern for using  make_app_client()  in tests. ( #395 ) \n                     \n                     \n                         New  request.actor  property. \n                     \n                     \n                         Fixed broken CSS on nested 404 pages. ( #777 ) \n                     \n                     \n                         New  request.url_vars  property. ( #822 ) \n                     \n                     \n                         Fixed a bug with the  python tests/fixtures.py  command for outputting Datasette's testing fixtures database and plugins. ( #804 ) \n                     \n                     \n                         datasette publish heroku  now deploys using Python 3.8.3. \n                     \n                     \n                         Added a warning that the  register_facet_classes()  hook is unstable and may change in the future. ( #830 ) \n                     \n                     \n                         The  {\"$env\": \"ENVIRONMENT_VARIBALE\"}  mechanism (see  Secret configuration values ) now works with variables inside nested lists. ( #837 )", "breadcrumbs": "[\"Changelog\", \"0.44 (2020-06-11)\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/706\", \"label\": \"#706\"}, {\"href\": \"https://github.com/simonw/datasette/issues/781\", \"label\": \"#781\"}, {\"href\": \"https://github.com/simonw/datasette/issues/774\", \"label\": \"#774\"}, {\"href\": \"https://github.com/simonw/datasette/issues/576\", \"label\": \"#576\"}, {\"href\": \"https://latest.datasette.io/-/plugins?all=1\", \"label\": \"https://latest.datasette.io/-/plugins?all=1\"}, {\"href\": \"https://github.com/simonw/datasette/issues/797\", \"label\": \"#797\"}, {\"href\": \"https://github.com/simonw/datasette/issues/802\", \"label\": \"#802\"}, {\"href\": \"https://github.com/simonw/datasette/issues/395\", \"label\": \"#395\"}, {\"href\": \"https://github.com/simonw/datasette/issues/777\", \"label\": \"#777\"}, {\"href\": \"https://github.com/simonw/datasette/issues/822\", \"label\": \"#822\"}, {\"href\": \"https://github.com/simonw/datasette/issues/804\", \"label\": \"#804\"}, {\"href\": \"https://github.com/simonw/datasette/issues/830\", \"label\": \"#830\"}, {\"href\": \"https://github.com/simonw/datasette/issues/837\", \"label\": \"#837\"}]"}, {"id": "changelog:permissions", "page": "changelog", "ref": "permissions", "title": "Permissions", "content": "Datasette also now has a built-in concept of  Permissions . The permissions system answers the following question: \n                 \n                     Is this  actor  allowed to perform this  action , optionally against this particular  resource ? \n                 \n                 You can use the new  \"allow\"  block syntax in  metadata.json  (or  metadata.yaml ) to set required permissions at the instance, database, table or canned query level. For example, to restrict access to the  fixtures.db  database to the  \"root\"  user: \n                 {\n    \"databases\": {\n        \"fixtures\": {\n            \"allow\": {\n                \"id\" \"root\"\n            }\n        }\n    }\n} \n                 See  Defining permissions with \"allow\" blocks  for more details. \n                 Plugins can implement their own custom permission checks using the new  plugin_hook_permission_allowed()  plugin hook. \n                 A new debug page at  /-/permissions  shows recent permission checks, to help administrators and plugin authors understand exactly what checks are being performed. This tool defaults to only being available to the root user, but can be exposed to other users by plugins that respond to the  permissions-debug  permission. ( #788 )", "breadcrumbs": "[\"Changelog\", \"0.44 (2020-06-11)\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/788\", \"label\": \"#788\"}]"}, {"id": "changelog:register-routes-plugin-hooks", "page": "changelog", "ref": "register-routes-plugin-hooks", "title": "register_routes() plugin hooks", "content": "Plugins can now register new views and routes via the  register_routes(datasette)  plugin hook ( #819 ). View functions can be defined that accept any of the current  datasette  object, the current  request , or the ASGI  scope ,  send  and  receive  objects.", "breadcrumbs": "[\"Changelog\", \"0.44 (2020-06-11)\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/issues/819\", \"label\": \"#819\"}]"}, {"id": "changelog:signed-values-and-secrets", "page": "changelog", "ref": "signed-values-and-secrets", "title": "Signed values and secrets", "content": "Both flash messages and user authentication needed a way to sign values and set signed cookies. Two new methods are now available for plugins to take advantage of this mechanism:  .sign(value, namespace=\"default\")  and  .unsign(value, namespace=\"default\") . \n                 Datasette will generate a secret automatically when it starts up, but to avoid resetting the secret (and hence invalidating any cookies) every time the server restarts you should set your own secret. You can pass a secret to Datasette using the new  --secret  option or with a  DATASETTE_SECRET  environment variable. See  Configuring the secret  for more details. \n                 You can also set a secret when you deploy Datasette using  datasette publish  or  datasette package  - see  Using secrets with datasette publish . \n                 Plugins can now sign values and verify their signatures using the  datasette.sign()  and  datasette.unsign()  methods.", "breadcrumbs": "[\"Changelog\", \"0.44 (2020-06-11)\"]", "references": "[]"}, {"id": "changelog:the-road-to-datasette-1-0", "page": "changelog", "ref": "the-road-to-datasette-1-0", "title": "The road to Datasette 1.0", "content": "I've assembled a  milestone for Datasette 1.0 . The focus of the 1.0 release will be the following: \n                 \n                     \n                         Signify confidence in the quality/stability of Datasette \n                     \n                     \n                         Give plugin authors confidence that their plugins will work for the whole 1.x release cycle \n                     \n                     \n                         Provide the same confidence to developers building against Datasette JSON APIs \n                     \n                 \n                 If you have thoughts about what you would like to see for Datasette 1.0 you can join  the conversation on issue #519 .", "breadcrumbs": "[\"Changelog\", \"0.44 (2020-06-11)\"]", "references": "[{\"href\": \"https://github.com/simonw/datasette/milestone/7\", \"label\": \"milestone for Datasette 1.0\"}, {\"href\": \"https://github.com/simonw/datasette/issues/519\", \"label\": \"the conversation on issue #519\"}]"}, {"id": "changelog:writable-canned-queries", "page": "changelog", "ref": "writable-canned-queries", "title": "Writable canned queries", "content": "Datasette's  Canned queries  feature lets you define SQL queries in  metadata.json  which can then be executed by users visiting a specific URL.  https://latest.datasette.io/fixtures/neighborhood_search  for example. \n                 Canned queries were previously restricted to  SELECT , but Datasette 0.44 introduces the ability for canned queries to execute  INSERT  or  UPDATE  queries as well, using the new  \"write\": true  property ( #800 ): \n                 {\n    \"databases\": {\n        \"dogs\": {\n            \"queries\": {\n                \"add_name\": {\n                    \"sql\": \"INSERT INTO names (name) VALUES (:name)\",\n                    \"write\": true\n                }\n            }\n        }\n    }\n} \n                 See  Writable canned queries  for more details.", "breadcrumbs": "[\"Changelog\", \"0.44 (2020-06-11)\"]", "references": "[{\"href\": \"https://latest.datasette.io/fixtures/neighborhood_search\", \"label\": \"https://latest.datasette.io/fixtures/neighborhood_search\"}, {\"href\": \"https://github.com/simonw/datasette/issues/800\", \"label\": \"#800\"}]"}], "truncated": false}