func (a *AuthChecker) Allowed(ctx context.Context) (*AuthInfo, error) {
	actx, err := a.newAllowContext(ctx, nil)
	if err != nil {
		return nil, errgo.Mask(err)
	}
	for op, mindexes := range a.authIndexes {
		for _, mindex := range mindexes {
			if actx.status[mindex]&statusOK != 0 {
				actx.status[mindex] |= statusUsed
				actx.opIndexes[op] = mindex
				break
			}
		}
	}
	return actx.newAuthInfo(), nil
}
Allowed returns an AuthInfo that provides information on all
operations directly authorized by the macaroons provided
to Checker.Auth. Note that this does not include operations that would be indirectly
allowed via the OpAuthorizer.

Allowed returns an error only when there is an underlying storage failure,
not when operations are not authorized.
package bakery
import (
	"sort"
	"sync"
	"time"
	"golang.org/x/net/context"
	errgo "gopkg.in/errgo.v1"
	macaroon "gopkg.in/macaroon.v2"
	"gopkg.in/macaroon-bakery.v2/bakery/checkers"
)
type Op struct {
	Entity string
	Action string
}
var NoOp = Op{}
type CheckerParams struct {
	Checker FirstPartyCaveatChecker
	OpsAuthorizer OpsAuthorizer
	MacaroonVerifier MacaroonVerifier
	Logger Logger
}
type OpsAuthorizer interface {
	AuthorizeOps(ctx context.Context, authorizedOp Op, queryOps []Op) ([]bool, []checkers.Caveat, error)
}
type AuthInfo struct {
	Macaroons []macaroon.Slice
	Used []bool
	OpIndexes map[Op]int
}
func (a *AuthInfo) Conditions() []string {
	var squasher caveatSquasher
	for i, ms := range a.Macaroons {
		if !a.Used[i] {
			continue
		}
		for _, m := range ms {
			for _, cav := range m.Caveats() {
				if len(cav.VerificationId) > 0 {
					continue
				}
				squasher.add(string(cav.Id))
			}
		}
	}
	return squasher.final()
}
type Checker struct {
	FirstPartyCaveatChecker
	p CheckerParams
}
func NewChecker(p CheckerParams) *Checker {
	if p.Checker == nil {
		p.Checker = checkers.New(nil)
	}
	if p.Logger == nil {
		p.Logger = DefaultLogger("bakery")
	}
	return &Checker{
		FirstPartyCaveatChecker: p.Checker,
		p: p,
	}
}
func (c *Checker) Auth(mss ...macaroon.Slice) *AuthChecker {
	return &AuthChecker{
		Checker:   c,
		macaroons: mss,
	}
}
type AuthChecker struct {
	*Checker
	macaroons []macaroon.Slice
	conditions [][]string
	initOnce   sync.Once
	initError  error
	initErrors []error
	authIndexes map[Op][]int
}
func (a *AuthChecker) init(ctx context.Context) error {
	a.initOnce.Do(func() {
		a.initError = a.initOnceFunc(ctx)
	})
	return a.initError
}
func (a *AuthChecker) initOnceFunc(ctx context.Context) error {
	a.authIndexes = make(map[Op][]int)
	a.conditions = make([][]string, len(a.macaroons))
	for i, ms := range a.macaroons {
		ops, conditions, err := a.p.MacaroonVerifier.VerifyMacaroon(ctx, ms)
		if err != nil {
			if !isVerificationError(err) {
				return errgo.Notef(err, "cannot retrieve macaroon")
			}
			a.initErrors = append(a.initErrors, errgo.Mask(err))
			continue
		}
		a.p.Logger.Debugf(ctx, "macaroon %d has valid sig; ops %q, conditions %q", i, ops, conditions)
		a.conditions[i] = conditions
		for _, op := range ops {
			a.authIndexes[op] = append(a.authIndexes[op], i)
		}
	}
	return nil
}