61 lines
1.2 KiB
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}
|
||
|
}
|