2024-04-12 16:41:11 +02:00
|
|
|
package authn
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
|
|
|
|
2024-06-26 13:52:49 +02:00
|
|
|
"forge.cadoles.com/cadoles/bouncer/internal/rule"
|
|
|
|
ruleHTTP "forge.cadoles.com/cadoles/bouncer/internal/rule/http"
|
2024-04-12 16:41:11 +02:00
|
|
|
"github.com/expr-lang/expr"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
)
|
|
|
|
|
2024-06-26 13:52:49 +02:00
|
|
|
type Env struct {
|
|
|
|
User *User `expr:"user"`
|
2024-04-12 16:41:11 +02:00
|
|
|
}
|
|
|
|
|
2024-05-21 12:10:52 +02:00
|
|
|
func (l *Layer) applyRules(r *http.Request, options *LayerOptions, user *User) error {
|
|
|
|
rules := options.Rules
|
2024-04-12 16:41:11 +02:00
|
|
|
if len(rules) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-06-26 13:52:49 +02:00
|
|
|
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,
|
2024-04-12 16:41:11 +02:00
|
|
|
}
|
|
|
|
|
2024-06-26 13:52:49 +02:00
|
|
|
if _, err := engine.Apply(env); err != nil {
|
|
|
|
return errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2024-05-21 12:10:52 +02:00
|
|
|
|
2024-06-26 13:52:49 +02:00
|
|
|
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
|
2024-05-21 12:10:52 +02:00
|
|
|
forbidden := expr.Function(
|
|
|
|
"forbidden",
|
|
|
|
func(params ...any) (any, error) {
|
2024-06-26 13:52:49 +02:00
|
|
|
return true, errors.WithStack(ErrForbidden)
|
2024-05-21 12:10:52 +02:00
|
|
|
},
|
|
|
|
new(func() bool),
|
|
|
|
)
|
|
|
|
|
2024-06-26 13:52:49 +02:00
|
|
|
options = append(options, forbidden)
|
2024-05-21 12:10:52 +02:00
|
|
|
|
2024-06-26 13:52:49 +02:00
|
|
|
return options
|
2024-04-12 16:41:11 +02:00
|
|
|
}
|