Coder Social home page Coder Social logo

Comments (14)

cldellow avatar cldellow commented on June 24, 2024

Hmmm, this might work for read-only queries, but I think write queries are executed in another thread?

Maybe we could use datasette-rewrite-sql to rewrite the query to include a comment with the actor ID, and then, just before actually passing the SQL off to SQLite, we'd set a thread local.

from datasette-ui-extras.

cldellow avatar cldellow commented on June 24, 2024

https://blog.sqreen.com/asyncio/ seems relevant

from datasette-ui-extras.

cldellow avatar cldellow commented on June 24, 2024

Huh, would this also let you write views like:

CREATE row_level_security_view AS
SELECT * FROM data
WHERE approved_by = current_actor() OR current_actor() = 'superuser'

The view would only work in the context of Datasette, not via vanilla sqlite CLI.

from datasette-ui-extras.

cldellow avatar cldellow commented on June 24, 2024

The request that actor_from_request is passed is a datasette thing: https://github.com/simonw/datasette/blob/0b4a28691468b5c758df74fa1d72a823813c96bf/datasette/utils/asgi.py#L56

We could mint one in order to call actor_from_request...but I wonder if plugins depend on getting the same request (eg, to cache a lookup, to log things).

The actual auth happens here: https://github.com/simonw/datasette/blob/0b4a28691468b5c758df74fa1d72a823813c96bf/datasette/app.py#L1481-L1522

Maybe we can write a hookwrapper for actor_from_request? See https://pluggy.readthedocs.io/en/stable/#wrappers

from datasette-ui-extras.

cldellow avatar cldellow commented on June 24, 2024

We might also be able to have a hook that stashes the request in the current_task ? Then we could always inspect stashed_request.scope.actor.

from datasette-ui-extras.

cldellow avatar cldellow commented on June 24, 2024

Stashing the request seems a little less skeezy, then we don't have to interrogate the result object and risk Datasette's logic changing.

from datasette-ui-extras.

cldellow avatar cldellow commented on June 24, 2024

Even once we've stashed it, we have the problem that we're in some asyncio context, and the actual execution of the SQL may be in a different thread, e.g. for writes.

A not-very-good solution: in rewrite_sql replace all instances of current_user() with a literal value.

Ah, but this doesn't actually solve the case I care about, which is I want to be able to create views with RLS where clauses, and have triggers that do the right thing.

from datasette-ui-extras.

cldellow avatar cldellow commented on June 24, 2024

Another oddness:

I did create view xxx as select current_user(), then went to http://localhost:8001/cooking/xxx

actor_from_request hadn't/didn't run before rewrite_sql...maybe we need something earlier?

from datasette-ui-extras.

cldellow avatar cldellow commented on June 24, 2024

Alternate idea: datasette-rewrite-sql only patches the entry points like execute, execute_write, execute_write_many, execute_write_script.

This isn't actually what needs to be patched -- we need to patch execute_fn and execute_write_fn, to control setting the value right before we pass control to SQLite.

from datasette-ui-extras.

cldellow avatar cldellow commented on June 24, 2024

I have a buggy proof of concept, it's incorrect under concurrent load.

I added an actor_from_request hook like:

@hookimpl
def actor_from_request(datasette, request):
    _id = None
    if 'x-me' in request.headers:
        _id = request.headers['x-me']
    return {'id': _id}

And then tested by having multiple bash windows open like:

while :; do curl -H "x-me: $$" http://localhost:8001/cooking/xxx.json?_shape=array; echo; done

I expect the output from each window to always show the same value, but instead, I get interleaved results.

This means my understanding of something is flawed. I wonder if it works with num_sql_threads=1? I stash the request on the asyncio.current_task(), but when we transition into SQLite I stash the ID in a global...that might be flawed.

from datasette-ui-extras.

cldellow avatar cldellow commented on June 24, 2024

--config num_sql_threads=1 gives correct results, so yeah, a global is not an OK way to store this.

from datasette-ui-extras.

cldellow avatar cldellow commented on June 24, 2024

Using a threading.local() resolves this

from datasette-ui-extras.

cldellow avatar cldellow commented on June 24, 2024

This might be worth its own plugin, and we'll just depend on it.

from datasette-ui-extras.

cldellow avatar cldellow commented on June 24, 2024

Released as https://github.com/cldellow/datasette-current-actor

from datasette-ui-extras.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.