package jess import ( "errors" "fmt" "sync" ) // TrustStore filter options. const ( FilterAny uint8 = iota FilterSignetOnly FilterRecipientOnly ) // TrustStore errors. var ( ErrSignetNotFound = errors.New("could not find signet") ErrEnvelopeNotFound = errors.New("could not find envelope") ) // TrustStore holds a set of trusted Signets and Recipients. type TrustStore interface { // GetSignet returns the Signet with the given ID. GetSignet(id string, recipient bool) (*Signet, error) } // MemTrustStore is a simple trust store using a Go map as backend. type MemTrustStore struct { lock sync.Mutex storage map[string]*Signet } // GetSignet returns the Signet with the given ID. func (mts *MemTrustStore) GetSignet(id string, recipient bool) (*Signet, error) { mts.lock.Lock() defer mts.lock.Unlock() // get from storage signet, ok := mts.storage[makeStorageID(id, recipient)] if !ok { return nil, ErrSignetNotFound } return signet, nil } // StoreSignet stores a Signet in the TrustStore. func (mts *MemTrustStore) StoreSignet(signet *Signet) error { // check for ID if signet.ID == "" { return errors.New("signets require an ID to be stored in a trust store") } mts.lock.Lock() defer mts.lock.Unlock() // store mts.storage[makeStorageID(signet.ID, signet.Public)] = signet return nil } // DeleteSignet deletes the Signet or Recipient with the given ID. func (mts *MemTrustStore) DeleteSignet(id string, recipient bool) error { mts.lock.Lock() defer mts.lock.Unlock() // delete delete(mts.storage, makeStorageID(id, recipient)) return nil } // SelectSignets returns a selection of the signets in the trust store. Results are filtered by tool/algorithm and whether it you're looking for a signet (private key) or a recipient (public key). func (mts *MemTrustStore) SelectSignets(filter uint8, schemes ...string) ([]*Signet, error) { mts.lock.Lock() defer mts.lock.Unlock() var selection []*Signet //nolint:prealloc for _, signet := range mts.storage { // check signet scheme if len(schemes) > 0 && !stringInSlice(signet.Scheme, schemes) { return nil, nil } // check type filter switch filter { case FilterSignetOnly: if signet.Public { continue } case FilterRecipientOnly: if !signet.Public { continue } } selection = append(selection, signet) } return selection, nil } // NewMemTrustStore returns a new in-memory TrustStore. func NewMemTrustStore() *MemTrustStore { return &MemTrustStore{ storage: make(map[string]*Signet), } } func makeStorageID(id string, recipient bool) string { if recipient { return fmt.Sprintf("%s.recipient", id) } return fmt.Sprintf("%s.signet", id) } func stringInSlice(s string, a []string) bool { for _, entry := range a { if entry == s { return true } } return false }