package authn import ( "net/http" "forge.cadoles.com/cadoles/bouncer/internal/rule" ruleHTTP "forge.cadoles.com/cadoles/bouncer/internal/rule/http" "github.com/expr-lang/expr" "github.com/pkg/errors" ) type Env struct { User *User `expr:"user"` } func (l *Layer) applyRules(r *http.Request, options *LayerOptions, user *User) error { rules := options.Rules if len(rules) == 0 { return nil } engine, err := rule.NewEngine[*Env]( rule.WithRules(options.Rules...), rule.WithExpr(getAuthnAPI()...), ruleHTTP.WithRequestFuncs(r), ) if err != nil { return errors.WithStack(err) } env := &Env{ User: user, } if _, err := engine.Apply(env); err != nil { return errors.WithStack(err) } return nil } func getAuthnAPI() []expr.Option { options := make([]expr.Option, 0) // forbidden() allows the layer to hijack the current request and return a 403 Forbidden HTTP status forbidden := expr.Function( "forbidden", func(params ...any) (any, error) { return true, errors.WithStack(ErrForbidden) }, new(func() bool), ) options = append(options, forbidden) return options }