Multi-tenant with hooks for all operations? #2585
-
I'm coming from Bun which has Hooks too: It is very easy with Bun to add a tenanted hook on each operation (even the select one): type Player struct {
Id uint64
Name string
}
var _ bun.BeforeSelectHook = (*Player)(nil)
func (*Player) BeforeSelect(ctx context.Context, query *bun.SelectQuery) error {
query.Where("?TableAlias.tenant_id = ?", GetTenantID(ctx))
return nil
}
var _ bun.BeforeInsertHook = (*Player)(nil)
func (*Player) BeforeInsert(ctx context.Context, query *bun.InsertQuery) error {
query.Value("?TableAlias.tenant_id = ?", GetTenantID(ctx))
return nil
}
var _ bun.BeforeUpdateHook = (*Player)(nil)
func (*Player) BeforeUpdate(ctx context.Context, query *bun.UpdateQuery) error {
query.Where("?TableAlias.tenant_id = ?", GetTenantID(ctx))
return nil
}
var _ bun.BeforeDeleteHook = (*Player)(nil)
func (*Player) BeforeDelete(ctx context.Context, query *bun.DeleteQuery) error {
query.Where("?TableAlias.tenant_id = ?", GetTenantID(ctx))
return nil
} In this case I can rest assured that no one on the team will forget to add a I'm learning Ent from today and saw this description on Readme for Tenant example which is not something I expect for it: Is it a misprint? Can you direct me to a guide for a multi-tenant with hooks for all operations? I'm a bit scared because in this page https://entgo.io/docs/hooks there are no hook for operations like "Select". |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
Hey @frederikhors, for this use case, you can use the Privacy Filter Rules to apply filtering to all your queries/mutations (including
Fixed. Thanks for reporting this. |
Beta Was this translation helpful? Give feedback.
-
I implemented with Ent a few different approaches for multi-tenacy. Named-database per tenant, tenant edge, and tenant_id field. The field/edge-based approaches were implemented with FilterRule as follows: func FilterTenantRule() privacy.QueryRule {
type TenantFilter interface {
WhereTenantID(int)
}
return privacy.FilterFunc(func(ctx context.Context, f privacy.Filter) error {
t := viewer.TenantFromContext(ctx)
tf, ok := f.(FilterTenantRule)
if !ok {
return privacy.Denyf("unexpected filter type %T. All schemas must include the Tenant mixin", f)
}
tf.WhereTenantID(t.ID)
// Skip to the next privacy rule (equivalent to return nil).
return privacy.Skip
})
} Let me know if it helps or if you need help with it. |
Beta Was this translation helpful? Give feedback.
I implemented with Ent a few different approaches for multi-tenacy. Named-database per tenant, tenant edge, and tenant_id field. The field/edge-based approaches were implemented with FilterRule as follows:
Let me know i…