daddy/internal/voter/manager.go

61 lines
1.2 KiB
Go

package voter
import (
"context"
"github.com/pkg/errors"
"gitlab.com/wpetit/goweb/logger"
)
type Voter interface {
Vote(ctx context.Context, subject interface{}, obj interface{}, action interface{}) (Decision, error)
}
type Strategy func(ctx context.Context, decisions []Decision) (Decision, error)
type Manager struct {
strategy Strategy
voters []Voter
}
func (m *Manager) Authorized(ctx context.Context, subject interface{}, obj interface{}, action interface{}) (Decision, error) {
decisions := make([]Decision, 0, len(m.voters))
logger.Debug(
ctx,
"checking authorization",
logger.F("subject", subject),
logger.F("object", obj),
logger.F("action", action),
)
for _, v := range m.voters {
dec, err := v.Vote(ctx, subject, obj, action)
if err != nil {
return Deny, errors.WithStack(err)
}
decisions = append(decisions, dec)
}
result, err := m.strategy(ctx, decisions)
if err != nil {
return Deny, errors.WithStack(err)
}
logger.Debug(
ctx,
"authorization checked",
logger.F("subject", subject),
logger.F("object", obj),
logger.F("action", action),
logger.F("result", AsString(result)),
)
return result, nil
}
func NewManager(strategy Strategy, voters ...Voter) *Manager {
return &Manager{strategy, voters}
}