guesstimate/internal/auth/auth.go

72 lines
1.2 KiB
Go

package auth
import (
"sync"
"forge.cadoles.com/Cadoles/guesstimate/internal/model"
"github.com/antonmedv/expr"
"github.com/antonmedv/expr/vm"
"github.com/pkg/errors"
)
var (
ErrUnexpectedRuleResult = errors.New("unexpected rule result")
)
type Service struct {
rules []*vm.Program
mutex sync.RWMutex
}
func (s *Service) LoadRules(rawRules ...string) error {
rules := make([]*vm.Program, 0, len(rawRules))
for _, rr := range rawRules {
r, err := expr.Compile(rr)
if err != nil {
return errors.WithStack(err)
}
rules = append(rules, r)
}
s.mutex.Lock()
s.rules = rules
s.mutex.Unlock()
return nil
}
func (s *Service) Authorize(user *model.User) (bool, error) {
s.mutex.RLock()
defer s.mutex.RUnlock()
env := map[string]interface{}{
"user": user,
}
for _, r := range s.rules {
result, err := expr.Run(r, env)
if err != nil {
return false, errors.WithStack(err)
}
authorized, ok := result.(bool)
if !ok {
return false, errors.WithStack(ErrUnexpectedRuleResult)
}
if !authorized {
return false, nil
}
}
return true, nil
}
func NewService() *Service {
return &Service{
rules: make([]*vm.Program, 0),
}
}