Giter Site home page Giter Site logo

Comments (12)

elliotcourant avatar elliotcourant commented on July 18, 2024 1

I will definitely be moving a lot of my stuff over from go-pg to bun, I'll probably make another repo with the implementation that I use as a boilerplate.

from bun.

elliotcourant avatar elliotcourant commented on July 18, 2024 1

Any orm that is pooling connections is not a good mix for row level security in my opinion. The safest way I've seen it done is to authenticate postgres using a user that only has access to that user's rows. That can be an expensive operation for applications that need to create many sessions to serve data. It might be possible to set a variable's value at the beginning of each session and then enforcing the row level security based on that variable, but then you risk the same problem; if you forget to set the variable in one spot -> now someone is reading someone else's data. But you have significantly overcomplicated your code in the process.

Row level security is best implemented where a connection is for a single tenant and thus there is no risk of it being misused. The connection is established for that tenant's sole user within postgres, and closed at the end of the work so that it is not re-used by a different tenant.

@vmihailenco do you want to move this do discussions?

from bun.

vmihailenco avatar vmihailenco commented on July 18, 2024

Such an approach only works for a single struct, not a slice. Why should we support the first and ignore the latter?

Overall it is not clear why make tenant filter so special. I write filters like this and tenant filter is just one of many.

from bun.

frederikhors avatar frederikhors commented on July 18, 2024

Overall it is not clear why make tenant filter so special.

What we're asking you since go-pg is a "global" and "safe" method that does not allow human errors (nobody can forget to filter by tenant_id).

from bun.

elliotcourant avatar elliotcourant commented on July 18, 2024

I mean to be fair, multi tenant implementations are so unique from application to application it's very hard for the ORM itself to properly implement such a system that adequately serves each use case; each use case being good and valid.

It is often better to implement multi-tenant safety at the database level with something like row level security. Or by building a layer on top of the ORM you are using and making that layer a common interface throughout your code.

from bun.

frederikhors avatar frederikhors commented on July 18, 2024

@elliotcourant any idea on how to use row level security with go-pg or bun? Can we set tenant_id on each connection?

from bun.

frederikhors avatar frederikhors commented on July 18, 2024

Long time ago I asked this go-gorm/gorm#3832.

from bun.

adpande avatar adpande commented on July 18, 2024

To handle multi-tenancy using postgres RLS
I think, if we set a key value like ("pgenv": [map of env variables] ) that we need to set in postgres environment at runtime using "SET" keyword in the context itself (https://golang.org/src/context/context.go?s=16244:16304#L509) and then pass the context along, and then in driver.go exec function we check if "pgenv" key is present in the coming context, if yes then get the map iterate over it and set the values before actually executing the query.

pgEnv := map[string]string{"tenant_id":"tenant_1" , "user_role": "admin"}
ctx := context.WithValue(context.Background(), "pgenv", pgEnv)
err := db.NewSelect().Model(book).Column("title", "text").Where("id = ?", 1).Scan(ctx)

Then in https://github.com/uptrace/bun/blob/0c18420f6be6b7188849ed24cdcc486a324176c5/driver/pgdriver/driver.go

We can check if the context have a value named "pgenv", if present then iterate over it and run the SET statements just before the execution of query.

  • I am new to golang

from bun.

frederikhors avatar frederikhors commented on July 18, 2024

@adpande I love you! ❤️

@vmihailenco, @elliotcourant what do you think about?

from bun.

vmihailenco avatar vmihailenco commented on July 18, 2024

It is possible to add BeforeSelectQueryHook and AfterSelectQueryHook that can change queries based on data in context

type BeforeSelectQueryHook interface {
	BeforeSelectQuery(ctx context.Context, query *SelectQuery) error
}

type AfterSelectQueryHook interface {
	AfterSelectQuery(ctx context.Context, query *SelectQuery) error
}

I personally think that such design brings more problems than it solves but I can live with it.

I mean to be fair, multi tenant implementations are so unique from application to application it's very hard for the ORM itself to properly implement such a system that adequately serves each use case; each use case being good and valid.

👍 I am even more skeptical and believe that it is better to write a little bit more code and repeat yourself here and there rather than relying on hooks & hacks.

(nobody can forget to filter by tenant_id)

You are lucky if this is the only / top10 problem in your app. It is easy to spot and even easier to fix...

from bun.

vmihailenco avatar vmihailenco commented on July 18, 2024

Hooks are re-worked in v0.2.0 - https://bun.uptrace.dev/guide/hooks.html#model-query-hooks. This example demonstrates how to modify query based on values in context.

from bun.

vmihailenco avatar vmihailenco commented on July 18, 2024

Closing since I don't know what else can be done here. Also see this disclaimer regarding hooks.

from bun.

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.