func (o *Oven) AddCaveats(ctx context.Context, m *Macaroon, caveats []checkers.Caveat) error {
	return m.AddCaveats(ctx, caveats, o.p.Key, o.p.Locator)
}
AddCaveats adds all the caveats to the given macaroon.
package bakery
import (
	"bytes"
	"encoding/base64"
	"sort"
	"github.com/rogpeppe/fastuuid"
	"golang.org/x/net/context"
	errgo "gopkg.in/errgo.v1"
	"gopkg.in/macaroon.v2"
	"gopkg.in/macaroon-bakery.v2/bakery/checkers"
	"gopkg.in/macaroon-bakery.v2/bakery/internal/macaroonpb"
)
type MacaroonVerifier interface {
	VerifyMacaroon(ctx context.Context, ms macaroon.Slice) ([]Op, []string, error)
}
var uuidGen = fastuuid.MustNewGenerator()
type Oven struct {
	p OvenParams
}
type OvenParams struct {
	Namespace *checkers.Namespace
	RootKeyStoreForOps func(ops []Op) RootKeyStore
	Key *KeyPair
	Location string
	Locator ThirdPartyLocator
	LegacyMacaroonOp Op
}
func NewOven(p OvenParams) *Oven {
	if p.Locator == nil {
		p.Locator = emptyLocator{}
	}
	if p.RootKeyStoreForOps == nil {
		store := NewMemRootKeyStore()
		p.RootKeyStoreForOps = func(ops []Op) RootKeyStore {
			return store
		}
	}
	if p.Namespace == nil {
		p.Namespace = checkers.New(nil).Namespace()
	}
	return &Oven{
		p: p,
	}
}
func (o *Oven) VerifyMacaroon(ctx context.Context, ms macaroon.Slice) (ops []Op, conditions []string, err error) {
	if len(ms) == 0 {
		return nil, nil, errgo.Newf("no macaroons in slice")
	}
	storageId, ops, err := o.decodeMacaroonId(ms[0].Id())
	if err != nil {
		return nil, nil, errgo.Mask(err)
	}
	rootKey, err := o.p.RootKeyStoreForOps(ops).Get(ctx, storageId)
	if err != nil {
		if errgo.Cause(err) != ErrNotFound {
			return nil, nil, errgo.Notef(err, "cannot get macaroon")
		}
		return nil, nil, &VerificationError{
			Reason: errgo.Newf("macaroon not found in storage"),
		}
	}
	conditions, err = ms[0].VerifySignature(rootKey, ms[1:])
	if err != nil {
		return nil, nil, &VerificationError{
			Reason: errgo.Mask(err),
		}
	}
	return ops, conditions, nil
}
func (o *Oven) decodeMacaroonId(id []byte) (storageId []byte, ops []Op, err error) {
	base64Decoded := false
	if id[0] == 'A' {
		dec := make([]byte, base64.RawURLEncoding.DecodedLen(len(id)))
		n, err := base64.RawURLEncoding.Decode(dec, id)
		if err == nil {
			id = dec[0:n]
			base64Decoded = true
		}
	}
	switch id[0] {
	case byte(Version2):
		storageId = id[1+16:]
	case byte(Version3):
		var id1 macaroonpb.MacaroonId
		if err := id1.UnmarshalBinary(id[1:]); err != nil {
			return nil, nil, errgo.Notef(err, "cannot unmarshal macaroon id")
		}
		if len(id1.Ops) == 0 || len(id1.Ops[0].Actions) == 0 {
			return nil, nil, errgo.Newf("no operations found in macaroon")
		}
		ops = make([]Op, 0, len(id1.Ops))
		for _, op := range id1.Ops {
			for _, action := range op.Actions {
				ops = append(ops, Op{
					Entity: op.Entity,
					Action: action,
				})
			}
		}
		return id1.StorageId, ops, nil
	}
	if !base64Decoded && isLowerCaseHexChar(id[0]) {
		if i := bytes.LastIndexByte(id, '-'); i >= 0 {
			storageId = id[0:i]
		}
	}
	if op := o.p.LegacyMacaroonOp; op != (Op{}) {
		ops = []Op{op}
	}
	return storageId, ops, nil
}
func (o *Oven) NewMacaroon(ctx context.Context, version Version, caveats []checkers.Caveat, ops ...Op) (*Macaroon, error) {
	if len(ops) == 0 {
		return nil, errgo.Newf("cannot mint a macaroon associated with no operations")
	}
	ops = CanonicalOps(ops)
	rootKey, storageId, err := o.p.RootKeyStoreForOps(ops).RootKey(ctx)
	if err != nil {
		return nil, errgo.Mask(err)
	}
	id, err := o.newMacaroonId(ctx, ops, storageId)
	if err != nil {
		return nil, errgo.Mask(err)
	}
	idBytesNoVersion, err := id.MarshalBinary()
	if err != nil {
		return nil, errgo.Mask(err)
	}
	idBytes := make([]byte, len(idBytesNoVersion)+1)
	idBytes[0] = byte(LatestVersion)
	copy(idBytes[1:], idBytesNoVersion)
	if MacaroonVersion(version) < macaroon.V2 {
		b64data := make([]byte, base64.RawURLEncoding.EncodedLen(len(idBytes)))
		base64.RawURLEncoding.Encode(b64data, idBytes)
		idBytes = b64data
	}
	m, err := NewMacaroon(rootKey, idBytes, o.p.Location, version, o.p.Namespace)
	if err != nil {
		return nil, errgo.Notef(err, "cannot create macaroon with version %v", version)
	}
	if err := o.AddCaveats(ctx, m, caveats); err != nil {
		return nil, errgo.Mask(err)
	}
	return m, nil
}
func (o *Oven) AddCaveat(ctx context.Context, m *Macaroon, cav checkers.Caveat) error {
	return m.AddCaveat(ctx, cav, o.p.Key, o.p.Locator)
}