package authn import ( "context" "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 Vars struct { User *User `expr:"user"` } func (l *Layer) applyRules(ctx context.Context, r *http.Request, options *LayerOptions, user *User) error { rules := options.Rules if len(rules) == 0 { return nil } engine, err := rule.NewEngine[*Vars]( rule.WithRules(options.Rules...), rule.WithExpr(getAuthnAPI()...), ruleHTTP.WithRequestFuncs(), ) if err != nil { return errors.WithStack(err) } vars := &Vars{ User: user, } ctx = ruleHTTP.WithRequest(ctx, r) if _, err := engine.Apply(ctx, vars); 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 }