Skip to content

Commit

Permalink
feat(session): user in context and transaction as user
Browse files Browse the repository at this point in the history
  • Loading branch information
enisdenjo committed Nov 12, 2021
1 parent 5c7b8cf commit 05dd55d
Showing 1 changed file with 53 additions and 0 deletions.
53 changes: 53 additions & 0 deletions pkg/session/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package session

import (
"context"
"database/sql"
"errors"
"fmt"

"github.com/domonda/go-errs"
"github.com/domonda/go-sqldb/db"
"github.com/domonda/go-types/uu"
)

type userCtxKeyType struct{}

var userCtxKey userCtxKeyType

func ContextWithUser(ctx context.Context, userID uu.ID) context.Context {
return context.WithValue(ctx, userCtxKey, userID)
}

func UserFromContext(ctx context.Context) (userID uu.ID, err error) {
userIDVal := ctx.Value(userCtxKey)
userID = uu.IDFrom(userIDVal)
if userID == uu.IDNil {
return uu.IDNil, errors.New("user not in context")
}
return userID, nil
}

func TransactionAsUser(ctx context.Context, txFunc func(ctx context.Context) error) (err error) {
return db.Transaction(ctx, func(ctx context.Context) (err error) {
userID, err := UserFromContext(ctx)
if err != nil {
return err
}

// impersonate user in transaction
err = db.Conn(ctx).Exec(fmt.Sprintf("set local session.user_id to '%s'; set role viewer;", userID))
if err != nil {
return err
}
defer func() {
if !errors.Is(err, sql.ErrTxDone) {
// for when this transaction is within another one
e := db.Conn(ctx).Exec("reset session.user_id; reset role;")
err = errs.Combine(err, e)
}
}()

return txFunc(ctx)
})
}

0 comments on commit 05dd55d

Please sign in to comment.