๐ค scope
amadan.net/rastrillo/rastrillo/scope
Owner-filtered GORM scopes. Two functions, and that is the whole package. It exists to make one discipline the short path, so every query on a model somebody owns carries its owner in the SQL and a handler cannot read or write another user's row by accident.
Scoping separates users within one instance. It is not tenancy: a CARLOS app serves one team, and a product with many teams gives each team its own instance. Scoping has the reasoning and the handler patterns; this page is the surface.
Owned
func Owned(g *gorm.DB, owner int64) *gorm.DB
Returns g with WHERE user_id = ? applied. This is the common case,
and the one most apps wrap in an owned(r) method:
func (a *app) owned(r *http.Request) *gorm.DB {
uid, _ := sessions.UserID(r)
return scope.Owned(a.db, uid)
}
Notice what that method drops. sessions.UserID returns (id, ok), and
ok is false for an identity plugin whose subject is not a numeric user
id. The magic-link plugin's subject is a verified email address, so
UserID returns (0, false) and this scopes every query to
user_id = 0. Read the viewer with auth.From(r) there and map the
address to your user row's id first โ
Magic links covers it.
OwnedBy
func OwnedBy(g *gorm.DB, column string, owner any) *gorm.DB
The same filter against any owner column, for a model that does not call
it user_id, and against any owner type โ a string subject as readily
as an int64 id.
rows := scope.OwnedBy(a.db, "author_id", subject).Find(&posts)
The column name is interpolated into the SQL rather than bound, because
a column name cannot be a placeholder. So OwnedBy panics unless the
name matches ^[a-z][a-z0-9_]*$.
The panic is the design. A column name reaching this function from anywhere but a Go string literal is a bug, and crashing on the first call in development is louder than a subtly wrong query in production. There is no error-returning variant to reach for instead: if the name is not a constant in your source, make it one.
Read this page as markdown โ exact, unstyled, and cheap for an agent to fetch.