Comments (12)
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.
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.
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.
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.
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.
@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.
Long time ago I asked this go-gorm/gorm#3832.
from bun.
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)
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.
@adpande I love you! ❤️
@vmihailenco, @elliotcourant what do you think about?
from bun.
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.
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.
Closing since I don't know what else can be done here. Also see this disclaimer regarding hooks.
from bun.
Related Issues (20)
- [bug] Query Select uses wrong table name when ModelTableExpr is called HOT 2
- I want to be able to use PostgreSQL's parametric placeholders.
- inconsistent behavior for ModelTableExpr (select <--> create/insert/update/delete)
- race detected in ```schema.Field.Clone()``` HOT 2
- Issue with BeforeAppendModel when selecting columns to update HOT 1
- Go migrations are not discovered
- Custom sum column on a relation
- In v1.2, about 'unique' tag option in embedded structures HOT 1
- Call BeforeAppendModel on embedded types
- incorrect CTE generation
- Is []int64 supported for Arrays
- Support for DuckDB dialect
- Ambiguous Column Reference Id
- Scan error on column: bun: Scan(unsupported [32]uint8)"
- m2m relations with composite keys
- can't scan 1 (float32) into float32
- Issue: Panic on Bulk Upsert with Pointer Fields in Slice of Interfaces HOT 1
- Documentation Pgx section update HOT 2
- Is it possible to insert a comment before or after a sql query?
- how can i tag index in struct filed?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from bun.