simonw / datasette-tiddlywiki

Run TiddlyWiki in Datasette and save Tiddlers to a SQLite database
Apache License 2.0
32 stars 0 forks source link

Implement authentication #3

Closed simonw closed 2 years ago

simonw commented 2 years ago

This shouldn't be public by default.

simonw commented 2 years ago

It looks like the /status endpoint is key for implementing authentication: https://tiddlywiki.com/#WebServer%20API%3A%20Get%20Server%20Status

The JSON data returned comprises the following properties:

  • username - the username of the currently authenticated user. If undefined, the WebServer Parameter: anon-username is returned instead
  • anonymous - true if the current user is anonymous
  • read_only - true if the current user is restricted to read only access to the server
  • space - always contains the object {recipe: "default"}
  • tiddlywiki_version - the current TiddlyWiki version

I could have an option for making the wiki read-only public to unauthenticated users - in which case I would return the read_only option here - and teach the PUT and DELETE endpoints to return errors.

simonw commented 2 years ago

Datasette Desktop signs the user in as root - https://github.com/simonw/datasette-app-support/blob/49078df0b6a038f8e0fe1bad5dfd42da4a6caff7/datasette_app_support/__init__.py#L273-L275

So I'm going to default to requiring root here.

simonw commented 2 years ago

This switched TiddlyWiki to read-only mode for users who are not logged in, but logging in with datasette ... --root made it read-write again:

async def status(request):
    username = None
    anonymous = True
    read_only = True
    if request.actor:
        username = request.actor["id"]
        anonymous = False
        # TODO: read_only based on permissions check
        # Maybe with actor_matches_allow({"id": "root"}, {"id": "*"})
        read_only = False

    return Response.json({
        "username": username,
        "anonymous": anonymous,
        "read_only": read_only,
        "space": {
            "recipe": "all"
        }
    })

Still need to perform that same check in the POST methods, and add tests.

simonw commented 2 years ago

I'll add two new permissions (see https://docs.datasette.io/en/stable/plugin_hooks.html#permission-allowed-datasette-actor-action-resource)

One point of confusion: should the read-tiddlywiki permission block access to reading from the tiddlywiki.db database too? I think it should.

simonw commented 2 years ago

Maybe in that case the rule should be "if the user is allowed access to the tiddlywiki database, they can also access the read-only TiddlyWiki interface" - otherwise you end up with confusing questions about what happens if read-tiddlywiki says no but can-read-database says yes, or vice-versa.

simonw commented 2 years ago

So only one new permission:

Plus code that does a permission check for view-database against the tiddlywiki database.

And view-instance too.

simonw commented 2 years ago

Documentation: https://github.com/simonw/datasette-tiddlywiki/blob/84c06dcffcf63829c4097fb2ea36aaccbf9d222e/README.md#authentication-and-permissions